import React, { ReactNode } from 'react'; import { Room } from 'matrix-js-sdk'; import { Navigate, useParams } from 'react-router-dom'; import { useAtom, useAtomValue } from 'jotai'; import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom'; import { IsOneOnOneProvider, RoomProvider } from '../../../hooks/useRoom'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { JoinBeforeNavigate } from '../../../features/join-before-navigate'; import { useSpace } from '../../../hooks/useSpace'; import { getAllParents, getSpaceChildren } from '../../../utils/room'; import { roomToParentsAtom } from '../../../state/room/roomToParents'; import { allRoomsAtom } from '../../../state/room-list/roomList'; import { useSearchParamsViaServers } from '../../../hooks/router/useSearchParamsViaServers'; import { settingsAtom } from '../../../state/settings'; import { useSetting } from '../../../state/hooks/settings'; import { useIsOneOnOneRoom } from '../../../hooks/useIsOneOnOneRoom'; // Inner provider hosts the reactive 1:1 subscription. Mirrors // direct/RoomProvider.tsx — the hook can't run before the early-return // guards, so we split the component once we know the room exists. function ResolvedRoomProvider({ room, children }: { room: Room; children: ReactNode }) { const isOneOnOne = useIsOneOnOneRoom(room); return ( {children} ); } export function SpaceRouteRoomProvider({ children }: { children: ReactNode }) { const mx = useMatrixClient(); const space = useSpace(); const [developerTools] = useSetting(settingsAtom, 'developerTools'); const [roomToParents, setRoomToParents] = useAtom(roomToParentsAtom); const allRooms = useAtomValue(allRoomsAtom); const { roomIdOrAlias, eventId } = useParams(); const viaServers = useSearchParamsViaServers(); const roomId = useSelectedRoom(); const room = mx.getRoom(roomId); if (!room || !allRooms.includes(room.roomId)) { // room is not joined if (!roomIdOrAlias) return ; return ( ); } if (developerTools && room.isSpaceRoom() && room.roomId === space.roomId) { // Allow viewing the space's own timeline. `isOneOnOneRoom` already guards // spaces (it returns false for `isSpace(room)`), so the value is stable // here regardless of member count. return {children}; } if (!getAllParents(roomToParents, room.roomId).has(space.roomId)) { if (getSpaceChildren(space).includes(room.roomId)) { // fill missing roomToParent mapping setRoomToParents({ type: 'PUT', parent: space.roomId, children: [room.roomId], }); } if (!roomIdOrAlias) return ; return ( ); } return {children}; }