From 99a294791e17073be4d491d573261fc40e44f014 Mon Sep 17 00:00:00 2001 From: litruv Date: Fri, 24 Jul 2026 16:52:34 +1000 Subject: [PATCH] Open DMs during sync catch-up instead of blocking on parent maps. Prefer the direct route for m.direct rooms and allow joined space children before roomToParents finishes backfilling. --- src/app/hooks/useRoomNavigate.ts | 18 ++++++--- src/app/pages/client/direct/RoomProvider.tsx | 12 +++++- src/app/pages/client/space/RoomProvider.tsx | 39 ++++++++++++++------ src/app/state/room/roomToParents.ts | 17 +++++++++ src/index.css | 6 +++ 5 files changed, 74 insertions(+), 18 deletions(-) diff --git a/src/app/hooks/useRoomNavigate.ts b/src/app/hooks/useRoomNavigate.ts index 1ecef1b..7b73029 100644 --- a/src/app/hooks/useRoomNavigate.ts +++ b/src/app/hooks/useRoomNavigate.ts @@ -56,6 +56,19 @@ export const useRoomNavigate = () => { } const orphanParents = openSpaceTimeline ? [roomId] : getOrphanParents(roomToParents, roomId); + + // Prefer Direct for m.direct rooms unless we are already browsing a parent space + // of this room (keep space chrome). Opening via space while roomToParents is still + // catching up used to hit JoinBeforeNavigate even though the DM was listed. + if (mDirects.has(roomId)) { + const stayInSelectedSpace = + Boolean(spaceSelectedId) && orphanParents.includes(spaceSelectedId!); + if (!stayInSelectedSpace) { + navigate(getDirectRoomPath(roomIdOrAlias, eventId), opts); + return; + } + } + if (orphanParents.length > 0) { let parentSpace: string; if (spaceSelectedId && orphanParents.includes(spaceSelectedId)) { @@ -73,11 +86,6 @@ export const useRoomNavigate = () => { return; } - if (mDirects.has(roomId)) { - navigate(getDirectRoomPath(roomIdOrAlias, eventId), opts); - return; - } - navigate(getHomeRoomPath(roomIdOrAlias, eventId), opts); }, [ diff --git a/src/app/pages/client/direct/RoomProvider.tsx b/src/app/pages/client/direct/RoomProvider.tsx index 275805d..cee2241 100644 --- a/src/app/pages/client/direct/RoomProvider.tsx +++ b/src/app/pages/client/direct/RoomProvider.tsx @@ -1,15 +1,19 @@ import React, { ReactNode } from 'react'; import { useParams } from 'react-router-dom'; +import { useAtomValue } from 'jotai'; import { decodeRouteParam } from '../../pathUtils'; import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom'; import { IsDirectRoomProvider, RoomProvider } from '../../../hooks/useRoom'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { JoinBeforeNavigate } from '../../../features/join-before-navigate'; import { useDirectRooms } from './useDirectRooms'; +import { mDirectAtom } from '../../../state/mDirectList'; +import { Membership } from '../../../../types/matrix/room'; export function DirectRouteRoomProvider({ children }: { children: ReactNode }) { const mx = useMatrixClient(); const rooms = useDirectRooms(); + const mDirects = useAtomValue(mDirectAtom); const { roomIdOrAlias: rawRoomIdOrAlias, eventId: rawEventId } = useParams(); const roomIdOrAlias = decodeRouteParam(rawRoomIdOrAlias); @@ -17,7 +21,13 @@ export function DirectRouteRoomProvider({ children }: { children: ReactNode }) { const roomId = useSelectedRoom(); const room = mx.getRoom(roomId); - if (!room || !rooms.includes(room.roomId)) { + // useDirectRooms can lag m.direct / allRooms during catch-up; allow joined m.direct rooms. + const isJoinedDirect = + Boolean(room) && + room!.getMyMembership() === Membership.Join && + (rooms.includes(room!.roomId) || mDirects.has(room!.roomId)); + + if (!room || !isJoinedDirect) { return ( { + if (!room || !isJoined || hasParentMapping || !isSpaceChild) return; + setRoomToParents({ + type: 'PUT', + parent: space.roomId, + children: [room.roomId], + }); + }, [ + room, + isJoined, + hasParentMapping, + isSpaceChild, + space.roomId, + setRoomToParents, + ]); + + if (!room || !isJoined) { // room is not joined return ( * { + pointer-events: auto; } .stationery [data-sidebar] > *,