vojo/src/app/hooks/useDmCallVisible.ts

41 lines
2 KiB
TypeScript

// Single source of truth for «can the user start a Vojo DM voice call
// in this room?». Both `RoomViewHeaderDm`'s phone-icon button and the
// `Call` action inside `UserRoomProfile` consult this hook so the two
// surfaces can't drift apart — round-7 review caught a bug where the
// profile button skipped the bridged-room and bot-control gates and
// would have offered to start a Matrix-RTC call inside a
// mautrix-telegram puppet DM.
//
// Four-gate predicate, mirroring the call-lifecycle hooks
// (`useIncomingRtcNotifications`, `useCallerAutoHangup`) so the
// visibility guard matches the actual deliverability:
// • member-count = 2 (true 1:1 — read via `useIsOneOnOne`'s context
// so we follow the same reactive source the rest of the app uses)
// • `m.direct`-tagged — ring delivery still gates on this
// • not a bridged room — MSC2346 `m.bridge` exclusion keeps the
// surface hidden in mautrix-telegram puppet DMs (no Matrix-RTC
// equivalent)
// • not a bot-control room — bot DMs aren't human-callable
//
// `useIsOneOnOne` is route-context-bound; this hook is therefore only
// meaningful for the room currently rendered by `Room.tsx`. Callers
// outside that scope must compute their own member-count signal.
import { Room } from 'matrix-js-sdk';
import { useAtomValue } from 'jotai';
import { useMatrixClient } from './useMatrixClient';
import { useIsOneOnOne } from './useRoom';
import { useIsBridgedRoom } from './useIsBridgedRoom';
import { useBotPresets } from '../features/bots/catalog';
import { isCatalogBotControlRoom } from '../features/bots/room';
import { mDirectAtom } from '../state/mDirectList';
export const useDmCallVisible = (room: Room): boolean => {
const mx = useMatrixClient();
const isOneOnOne = useIsOneOnOne();
const mDirects = useAtomValue(mDirectAtom);
const isBridged = useIsBridgedRoom(room);
const bots = useBotPresets();
const isBotControlRoom = isCatalogBotControlRoom(mx, room, bots);
return isOneOnOne && mDirects.has(room.roomId) && !isBridged && !isBotControlRoom;
};