vojo/src/app/pages/client/direct/useDirectRooms.ts

52 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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]);
};