52 lines
2.3 KiB
TypeScript
52 lines
2.3 KiB
TypeScript
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<string>();
|
||
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]);
|
||
};
|