48 lines
2.2 KiB
TypeScript
48 lines
2.2 KiB
TypeScript
import React, { ReactNode } from 'react';
|
|
import { Room } from 'matrix-js-sdk';
|
|
import { Navigate, useParams } from 'react-router-dom';
|
|
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 { isSpace } from '../../../utils/room';
|
|
import { useIsOneOnOneRoom } from '../../../hooks/useIsOneOnOneRoom';
|
|
import { Membership } from '../../../../types/matrix/room';
|
|
import { getDirectPath } from '../../pathUtils';
|
|
|
|
// Inner provider hosts the reactive 1:1 subscription. Hooks can't run inside
|
|
// the early-return path of the parent, so we split the component once `room`
|
|
// is known to exist and not be a space.
|
|
function ResolvedRoomProvider({ room, children }: { room: Room; children: ReactNode }) {
|
|
const isOneOnOne = useIsOneOnOneRoom(room);
|
|
return (
|
|
<RoomProvider key={room.roomId} value={room}>
|
|
<IsOneOnOneProvider value={isOneOnOne}>{children}</IsOneOnOneProvider>
|
|
</RoomProvider>
|
|
);
|
|
}
|
|
|
|
export function DirectRouteRoomProvider({ children }: { children: ReactNode }) {
|
|
const mx = useMatrixClient();
|
|
|
|
const { roomIdOrAlias, eventId } = useParams();
|
|
const roomId = useSelectedRoom();
|
|
const room = mx.getRoom(roomId);
|
|
|
|
// Central membership guard: invite-state rooms have no useful Room view —
|
|
// the Accept/Decline UI lives on the inline DirectInviteRow in the panel.
|
|
// Push deep links and legacy /home/{roomId}/ shim can both deliver an
|
|
// invite-room id here; bounce to the bare /direct/ list so the user lands
|
|
// on the row instead of an empty stripped-state timeline.
|
|
if (room && room.getMyMembership() === Membership.Invite) {
|
|
return <Navigate to={getDirectPath()} replace />;
|
|
}
|
|
|
|
// After P3c the Direct tab is universal — any joined non-space room renders
|
|
// here. Spaces (= future Channels) keep their own /{spaceId}/ route.
|
|
if (!room || isSpace(room)) {
|
|
return <JoinBeforeNavigate roomIdOrAlias={roomIdOrAlias!} eventId={eventId} />;
|
|
}
|
|
|
|
return <ResolvedRoomProvider room={room}>{children}</ResolvedRoomProvider>;
|
|
}
|