import { useAtomValue } from 'jotai'; import { useMemo } from 'react'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { mDirectAtom } from '../../../state/mDirectList'; import { allRoomsAtom } from '../../../state/room-list/roomList'; import { useDirects, useOrphanRooms } from '../../../state/hooks/roomList'; import { roomToParentsAtom } from '../../../state/room/roomToParents'; // After P3c the Direct tab is universal: every joined non-space «orphan» // room renders here, regardless of `m.direct`. Implementation = // `useOrphanRooms ∪ useDirects`: // // - `useOrphanRooms` = `isRoom && !mDirects.has && !roomToParents.has` → // non-space rooms that don't live inside any space and aren't m.direct- // tagged. The formerly-Home tab. // - `useDirects` = `isRoom && mDirects.has` → every m.direct-tagged // non-space room. **No `roomToParents` filter** — a room that is BOTH a // space child AND m.direct-tagged appears here. This is intentional and // pre-dates P3c: the m.direct flag wins over the space-child membership // for routing purposes (user sees the DM in /direct/, opening it loses // space context). The same room is hidden from the parent space's child- // room navigation list (`useChildRoomScopeFactory` excludes m.direct); // it stays reachable from space message search via // `useRecursiveChildNonSpaceRoomScopeFactory` (post-P3c universal). // // Duplicates inside the union are deduped via Set semantics below. The // product call (DM-tagged-space-child resolves to /direct/, not /space/{id}/) // is open for revision — see desired_features §21 (Channels plan). export const useDirectRooms = (): string[] => { const mx = useMatrixClient(); const mDirects = useAtomValue(mDirectAtom); const roomToParents = useAtomValue(roomToParentsAtom); const orphanRooms = useOrphanRooms(mx, allRoomsAtom, mDirects, roomToParents); const directs = useDirects(mx, allRoomsAtom, mDirects); return useMemo(() => { const seen = new Set(); const out: string[] = []; orphanRooms.forEach((id) => { if (!seen.has(id)) { seen.add(id); out.push(id); } }); directs.forEach((id) => { if (!seen.has(id)) { seen.add(id); out.push(id); } }); return out; }, [orphanRooms, directs]); };