From cd04625b13bc1b5505a390a3e3e551b5af8cbcd4 Mon Sep 17 00:00:00 2001 From: 7w1 Date: Fri, 15 May 2026 20:49:16 -0500 Subject: [PATCH] support stable mutual rooms endpoint --- .changeset/stable-mutual-rooms-endpoint.md | 5 ++ src/app/components/user-profile/UserChips.tsx | 9 ++- src/app/hooks/useMutualRooms.ts | 58 +++++++++++++++++-- 3 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 .changeset/stable-mutual-rooms-endpoint.md diff --git a/.changeset/stable-mutual-rooms-endpoint.md b/.changeset/stable-mutual-rooms-endpoint.md new file mode 100644 index 000000000..4c19da8db --- /dev/null +++ b/.changeset/stable-mutual-rooms-endpoint.md @@ -0,0 +1,5 @@ +--- +default: patch +--- + +Add support for stable mutual rooms endpoint. diff --git a/src/app/components/user-profile/UserChips.tsx b/src/app/components/user-profile/UserChips.tsx index 168a973e5..2adeb5fbe 100644 --- a/src/app/components/user-profile/UserChips.tsx +++ b/src/app/components/user-profile/UserChips.tsx @@ -30,7 +30,11 @@ import { copyToClipboard } from '$utils/dom'; import { getExploreServerPath } from '$pages/pathUtils'; import { AsyncStatus, useAsyncCallback } from '$hooks/useAsyncCallback'; import { factoryRoomIdByAtoZ } from '$utils/sort'; -import { useMutualRooms, useMutualRoomsSupport } from '$hooks/useMutualRooms'; +import { + useMutualRooms, + useMutualRoomsSupport, + useUnstableMutualRoomsSupport, +} from '$hooks/useMutualRooms'; import { useRoomNavigate } from '$hooks/useRoomNavigate'; import { useDirectRooms } from '$pages/client/direct/useDirectRooms'; import { useMediaAuthentication } from '$hooks/useMediaAuthentication'; @@ -352,6 +356,7 @@ export function MutualRoomsChip({ const menuItemBg = chipFillColor ?? cardColor; const mx = useMatrixClient(); const mutualRoomSupported = useMutualRoomsSupport(); + const mutualRoomUnstable = useUnstableMutualRoomsSupport(); const mutualRoomsState = useMutualRooms(userId); const { navigateRoom, navigateSpace } = useRoomNavigate(); const closeUserRoomProfile = useCloseUserRoomProfile(); @@ -398,7 +403,7 @@ export function MutualRoomsChip({ if ( userId === mx.getSafeUserId() || - !mutualRoomSupported || + (!mutualRoomSupported && !mutualRoomUnstable) || mutualRoomsState.status === AsyncStatus.Error ) { return null; diff --git a/src/app/hooks/useMutualRooms.ts b/src/app/hooks/useMutualRooms.ts index fe464ba57..7d95d7b2a 100644 --- a/src/app/hooks/useMutualRooms.ts +++ b/src/app/hooks/useMutualRooms.ts @@ -1,10 +1,12 @@ import { useCallback } from 'react'; +import type { MatrixClient } from '$types/matrix-sdk'; +import { Method } from '$types/matrix-sdk'; import { useMatrixClient } from './useMatrixClient'; import type { AsyncState } from './useAsyncCallback'; import { useAsyncCallbackValue } from './useAsyncCallback'; import { useSpecVersions } from './useSpecVersions'; -export const useMutualRoomsSupport = (): boolean => { +export const useUnstableMutualRoomsSupport = (): boolean => { const { unstable_features: unstableFeatures } = useSpecVersions(); const supported = @@ -15,16 +17,60 @@ export const useMutualRoomsSupport = (): boolean => { return !!supported; }; +export const useMutualRoomsSupport = (): boolean => { + const { unstable_features: unstableFeatures, versions } = useSpecVersions(); + + const supported = + versions.includes('v1.19') || + !!unstableFeatures?.['uk.half-shot.msc2666.query_mutual_rooms.stable']; + + return supported; +}; + +type MutualRoomsOK = { + joined: string[]; + next_batch?: string; + count: number; +}; + +const fetchAllMutualRooms = async (mx: MatrixClient, userId: string): Promise => { + const mutualRooms: Set = new Set(); + + const collectFrom = async (nextBatch?: string): Promise => { + const result = await mx.http.authedRequest( + Method.Get, + '/mutual_rooms', + { + user_id: userId, + from: nextBatch, + }, + undefined, + { + prefix: '/_matrix/client/v1', + } + ); + result.joined.forEach((r) => mutualRooms.add(r)); + if (typeof result.next_batch === 'string') { + await collectFrom(result.next_batch); + } + }; + + await collectFrom(); + return Array.from(mutualRooms); +}; + export const useMutualRooms = (userId: string): AsyncState => { const mx = useMatrixClient(); - const supported = useMutualRoomsSupport(); + const unstableSupport = useUnstableMutualRoomsSupport(); + const support = useMutualRoomsSupport(); const [mutualRoomsState] = useAsyncCallbackValue( - useCallback( - () => (supported ? mx._unstable_getSharedRooms(userId) : Promise.resolve([])), - [mx, userId, supported] - ) + useCallback(() => { + if (support) return fetchAllMutualRooms(mx, userId); + if (unstableSupport) return mx._unstable_getSharedRooms(userId); + return Promise.resolve([]); + }, [mx, userId, unstableSupport, support]) ); return mutualRoomsState;