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.
This commit is contained in:
@@ -56,6 +56,19 @@ export const useRoomNavigate = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const orphanParents = openSpaceTimeline ? [roomId] : getOrphanParents(roomToParents, roomId);
|
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) {
|
if (orphanParents.length > 0) {
|
||||||
let parentSpace: string;
|
let parentSpace: string;
|
||||||
if (spaceSelectedId && orphanParents.includes(spaceSelectedId)) {
|
if (spaceSelectedId && orphanParents.includes(spaceSelectedId)) {
|
||||||
@@ -73,11 +86,6 @@ export const useRoomNavigate = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDirects.has(roomId)) {
|
|
||||||
navigate(getDirectRoomPath(roomIdOrAlias, eventId), opts);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
navigate(getHomeRoomPath(roomIdOrAlias, eventId), opts);
|
navigate(getHomeRoomPath(roomIdOrAlias, eventId), opts);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
import React, { ReactNode } from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { useAtomValue } from 'jotai';
|
||||||
import { decodeRouteParam } from '../../pathUtils';
|
import { decodeRouteParam } from '../../pathUtils';
|
||||||
import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom';
|
import { useSelectedRoom } from '../../../hooks/router/useSelectedRoom';
|
||||||
import { IsDirectRoomProvider, RoomProvider } from '../../../hooks/useRoom';
|
import { IsDirectRoomProvider, RoomProvider } from '../../../hooks/useRoom';
|
||||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||||
import { JoinBeforeNavigate } from '../../../features/join-before-navigate';
|
import { JoinBeforeNavigate } from '../../../features/join-before-navigate';
|
||||||
import { useDirectRooms } from './useDirectRooms';
|
import { useDirectRooms } from './useDirectRooms';
|
||||||
|
import { mDirectAtom } from '../../../state/mDirectList';
|
||||||
|
import { Membership } from '../../../../types/matrix/room';
|
||||||
|
|
||||||
export function DirectRouteRoomProvider({ children }: { children: ReactNode }) {
|
export function DirectRouteRoomProvider({ children }: { children: ReactNode }) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const rooms = useDirectRooms();
|
const rooms = useDirectRooms();
|
||||||
|
const mDirects = useAtomValue(mDirectAtom);
|
||||||
|
|
||||||
const { roomIdOrAlias: rawRoomIdOrAlias, eventId: rawEventId } = useParams();
|
const { roomIdOrAlias: rawRoomIdOrAlias, eventId: rawEventId } = useParams();
|
||||||
const roomIdOrAlias = decodeRouteParam(rawRoomIdOrAlias);
|
const roomIdOrAlias = decodeRouteParam(rawRoomIdOrAlias);
|
||||||
@@ -17,7 +21,13 @@ export function DirectRouteRoomProvider({ children }: { children: ReactNode }) {
|
|||||||
const roomId = useSelectedRoom();
|
const roomId = useSelectedRoom();
|
||||||
const room = mx.getRoom(roomId);
|
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 (
|
return (
|
||||||
<JoinBeforeNavigate
|
<JoinBeforeNavigate
|
||||||
roomIdOrAlias={roomIdOrAlias ?? rawRoomIdOrAlias!}
|
roomIdOrAlias={roomIdOrAlias ?? rawRoomIdOrAlias!}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { ReactNode } from 'react';
|
import React, { ReactNode, useEffect } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useAtom, useAtomValue } from 'jotai';
|
import { useAtom, useAtomValue } from 'jotai';
|
||||||
import { decodeRouteParam } from '../../pathUtils';
|
import { decodeRouteParam } from '../../pathUtils';
|
||||||
@@ -30,7 +30,31 @@ export function SpaceRouteRoomProvider({ children }: { children: ReactNode }) {
|
|||||||
const roomId = useSelectedRoom();
|
const roomId = useSelectedRoom();
|
||||||
const room = mx.getRoom(roomId);
|
const room = mx.getRoom(roomId);
|
||||||
|
|
||||||
if (!room || !allRooms.includes(room.roomId)) {
|
const isJoined = Boolean(room && allRooms.includes(room.roomId));
|
||||||
|
const isSpaceChild = Boolean(room && getSpaceChildren(space).includes(room.roomId));
|
||||||
|
const hasParentMapping = Boolean(
|
||||||
|
room && getAllParents(roomToParents, room.roomId).has(space.roomId)
|
||||||
|
);
|
||||||
|
|
||||||
|
// roomToParents can lag behind live space state during catch-up sync.
|
||||||
|
// If the room is clearly a child of this space, backfill the map and open it.
|
||||||
|
useEffect(() => {
|
||||||
|
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
|
// room is not joined
|
||||||
return (
|
return (
|
||||||
<JoinBeforeNavigate
|
<JoinBeforeNavigate
|
||||||
@@ -50,16 +74,7 @@ export function SpaceRouteRoomProvider({ children }: { children: ReactNode }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getAllParents(roomToParents, room.roomId).has(space.roomId)) {
|
if (!hasParentMapping && !isSpaceChild) {
|
||||||
if (getSpaceChildren(space).includes(room.roomId)) {
|
|
||||||
// fill missing roomToParent mapping
|
|
||||||
setRoomToParents({
|
|
||||||
type: 'PUT',
|
|
||||||
parent: space.roomId,
|
|
||||||
children: [room.roomId],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<JoinBeforeNavigate
|
<JoinBeforeNavigate
|
||||||
roomIdOrAlias={roomIdOrAlias ?? rawRoomIdOrAlias!}
|
roomIdOrAlias={roomIdOrAlias ?? rawRoomIdOrAlias!}
|
||||||
|
|||||||
@@ -103,6 +103,23 @@ export const useBindRoomToParentsAtom = (
|
|||||||
setRoomToParents({ type: 'DELETE', roomId: childId });
|
setRoomToParents({ type: 'DELETE', roomId: childId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create type can arrive after the room is already in the store. Without this,
|
||||||
|
// spaces are skipped on INITIALIZE (isSpace false) and children stay unmapped
|
||||||
|
// until an unrelated SpaceChild event fires — DMs/channels look listed but
|
||||||
|
// SpaceRouteRoomProvider blocks on missing roomToParents.
|
||||||
|
if (mEvent.getType() === StateEvent.RoomCreate) {
|
||||||
|
const roomId = mEvent.getRoomId();
|
||||||
|
const room = roomId ? mx.getRoom(roomId) : null;
|
||||||
|
if (room && isSpace(room) && room.getMyMembership() !== Membership.Invite) {
|
||||||
|
setRoomToParents({
|
||||||
|
type: 'PUT',
|
||||||
|
parent: room.roomId,
|
||||||
|
children: getSpaceChildren(room),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -887,6 +887,12 @@ body.stationery-dark-theme {
|
|||||||
width: calc(100% + 25px) !important;
|
width: calc(100% + 25px) !important;
|
||||||
max-width: none !important;
|
max-width: none !important;
|
||||||
box-sizing: border-box !important;
|
box-sizing: border-box !important;
|
||||||
|
/* Gutter is only for post-it overflow paint — do not steal clicks from page-nav */
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stationery [data-sidebar-scroll] > * {
|
||||||
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stationery [data-sidebar] > *,
|
.stationery [data-sidebar] > *,
|
||||||
|
|||||||
Reference in New Issue
Block a user