From 6b81401e2da8c1d1e61d297d256dc06d8f4e599b Mon Sep 17 00:00:00 2001 From: Ajay Bura <32841439+ajbura@users.noreply.github.com> Date: Fri, 11 Jul 2025 16:30:30 +0530 Subject: [PATCH 1/2] fix room not opening when two rooms has same alias (#2387) --- src/app/utils/matrix.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/utils/matrix.ts b/src/app/utils/matrix.ts index a495e8d5..4b695724 100644 --- a/src/app/utils/matrix.ts +++ b/src/app/utils/matrix.ts @@ -50,7 +50,11 @@ export const getCanonicalAliasOrRoomId = (mx: MatrixClient, roomId: string): str const room = mx.getRoom(roomId); if (!room) return roomId; if (getStateEvent(room, StateEvent.RoomTombstone) !== undefined) return roomId; - return room.getCanonicalAlias() || roomId; + const alias = room.getCanonicalAlias(); + if (alias && getCanonicalAliasRoomId(mx, alias) === roomId) { + return alias; + } + return roomId; }; export const getImageInfo = (img: HTMLImageElement, fileOrBlob: File | Blob): IImageInfo => { From fbd7e0a14b4e50c7af69815d57254f97233296a3 Mon Sep 17 00:00:00 2001 From: Ajay Bura <32841439+ajbura@users.noreply.github.com> Date: Fri, 11 Jul 2025 16:33:55 +0530 Subject: [PATCH 2/2] improve parent selection when opening a room (#2388) when a room has more than one orphan parent, we will select parent which has highest number of special users who have special powers in selected room. --- src/app/hooks/useRoomNavigate.ts | 24 +++++++++---------- src/app/utils/room.ts | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/src/app/hooks/useRoomNavigate.ts b/src/app/hooks/useRoomNavigate.ts index e626c06b..b2d7a91a 100644 --- a/src/app/hooks/useRoomNavigate.ts +++ b/src/app/hooks/useRoomNavigate.ts @@ -9,7 +9,7 @@ import { getSpaceRoomPath, } from '../pages/pathUtils'; import { useMatrixClient } from './useMatrixClient'; -import { getOrphanParents } from '../utils/room'; +import { getOrphanParents, guessPerfectParent } from '../utils/room'; import { roomToParentsAtom } from '../state/room/roomToParents'; import { mDirectAtom } from '../state/mDirectList'; import { useSelectedSpace } from './router/useSelectedSpace'; @@ -39,19 +39,19 @@ export const useRoomNavigate = () => { const orphanParents = openSpaceTimeline ? [roomId] : getOrphanParents(roomToParents, roomId); if (orphanParents.length > 0) { - const pSpaceIdOrAlias = getCanonicalAliasOrRoomId( - mx, - spaceSelectedId && orphanParents.includes(spaceSelectedId) - ? spaceSelectedId - : orphanParents[0] // TODO: better orphan parent selection. - ); - - if (openSpaceTimeline) { - navigate(getSpaceRoomPath(pSpaceIdOrAlias, roomId, eventId), opts); - return; + let parentSpace: string; + if (spaceSelectedId && orphanParents.includes(spaceSelectedId)) { + parentSpace = spaceSelectedId; + } else { + parentSpace = guessPerfectParent(mx, roomId, orphanParents) ?? orphanParents[0]; } - navigate(getSpaceRoomPath(pSpaceIdOrAlias, roomIdOrAlias, eventId), opts); + const pSpaceIdOrAlias = getCanonicalAliasOrRoomId(mx, parentSpace); + + navigate( + getSpaceRoomPath(pSpaceIdOrAlias, openSpaceTimeline ? roomId : roomIdOrAlias, eventId), + opts + ); return; } diff --git a/src/app/utils/room.ts b/src/app/utils/room.ts index 79dcff9e..cae23514 100644 --- a/src/app/utils/room.ts +++ b/src/app/utils/room.ts @@ -5,6 +5,7 @@ import { EventTimelineSet, EventType, IMentions, + IPowerLevelsContent, IPushRule, IPushRules, JoinRule, @@ -473,3 +474,43 @@ export const bannedInRooms = (mx: MatrixClient, rooms: string[], otherUserId: st const banned = room.hasMembershipState(otherUserId, Membership.Ban); return banned; }); + +export const guessPerfectParent = ( + mx: MatrixClient, + roomId: string, + parents: string[] +): string | undefined => { + if (parents.length === 1) { + return parents[0]; + } + + const getSpecialUsers = (rId: string): string[] => { + const r = mx.getRoom(rId); + const powerLevels = + r && getStateEvent(r, StateEvent.RoomPowerLevels)?.getContent(); + + const { users_default: usersDefault, users } = powerLevels ?? {}; + if (typeof users !== 'object') return []; + + const defaultPower = typeof usersDefault === 'number' ? usersDefault : 0; + return Object.keys(users).filter((userId) => users[userId] > defaultPower); + }; + + let perfectParent: string | undefined; + let score = 0; + + const roomSpecialUsers = getSpecialUsers(roomId); + parents.forEach((parentId) => { + const parentSpecialUsers = getSpecialUsers(parentId); + const matchedUsersCount = parentSpecialUsers.filter((userId) => + roomSpecialUsers.includes(userId) + ).length; + + if (matchedUsersCount > score) { + score = matchedUsersCount; + perfectParent = parentId; + } + }); + + return perfectParent; +};