Make room switches instant and cut redundant client work.

Keep-alive room cache with CSS-only warm switches, nav loading feedback, and per-context members drawer prefs. Share hierarchy/call/sub-room subscriptions, demux state events, and lazy lobby power-level loading to avoid duplicate scans and listener storms.
This commit is contained in:
2026-07-22 18:00:54 +10:00
parent 821724b594
commit 30edd62d96
62 changed files with 2020 additions and 802 deletions

View File

@@ -230,62 +230,76 @@ export function useCallService(): CallContextValue {
/**
* Hook to check if a call is active in a specific room
*/
/** Persists across keep-alive remounts so room switches don't re-hit well-known. */
const roomCallSupportCache = new Map<string, boolean>();
export function useRoomCall(roomId: string) {
const { activeCall, startCall, endCall, callSupported: globalCallSupported, callSupportLoading: globalCallSupportLoading, callService } = useCall();
const mx = useMatrixClient();
const [roomCallSupported, setRoomCallSupported] = useState(false);
const [roomCallSupportLoading, setRoomCallSupportLoading] = useState(true);
const [roomCallSupported, setRoomCallSupported] = useState(
() => roomCallSupportCache.get(roomId) ?? false
);
const [roomCallSupportLoading, setRoomCallSupportLoading] = useState(
() => !roomCallSupportCache.has(roomId)
);
// Check if calls are supported for this specific room by checking all priority homeservers
useEffect(() => {
const cached = roomCallSupportCache.get(roomId);
if (cached !== undefined) {
setRoomCallSupported(cached);
setRoomCallSupportLoading(false);
return undefined;
}
let cancelled = false;
const checkRoomCallSupport = async () => {
setRoomCallSupportLoading(true);
const room = mx.getRoom(roomId);
if (!room) {
setRoomCallSupported(false);
setRoomCallSupportLoading(false);
if (!cancelled) {
setRoomCallSupported(false);
setRoomCallSupportLoading(false);
}
return;
}
// Get homeserver priority list for this room
const homeserverPriority = getLiveKitHomeserverPriority(
room,
mx.getHomeserverUrl(),
mx.getSafeUserId()
);
console.log(`Checking call support for room ${roomId}, homeserver priority:`, homeserverPriority);
// Check each homeserver in priority order
for (const homeserver of homeserverPriority) {
try {
console.log(`Fetching well-known from ${homeserver}...`);
const wellKnown = await fetchWellKnownWithRTC(homeserver);
console.log(`Well-known response from ${homeserver}:`, wellKnown);
const livekitFocus = getLiveKitFocus(wellKnown);
console.log(`LiveKit focus from ${homeserver}:`, livekitFocus);
if (livekitFocus) {
console.log(`Call support found for room ${roomId} on homeserver: ${homeserver}`);
setRoomCallSupported(true);
setRoomCallSupportLoading(false);
roomCallSupportCache.set(roomId, true);
if (!cancelled) {
setRoomCallSupported(true);
setRoomCallSupportLoading(false);
}
return;
}
} catch (error) {
console.warn(`Failed to check call support on ${homeserver}:`, error);
} catch {
// Continue to next homeserver
}
}
// No homeserver supports calls
console.log(`No call support found for room ${roomId}`);
setRoomCallSupported(false);
setRoomCallSupportLoading(false);
roomCallSupportCache.set(roomId, false);
if (!cancelled) {
setRoomCallSupported(false);
setRoomCallSupportLoading(false);
}
};
checkRoomCallSupport();
return () => {
cancelled = true;
};
}, [roomId, mx]);
const isInCall = activeCall?.roomId === roomId;