import { useMemo } from 'react'; import { useParams } from 'react-router-dom'; import { useMatrixClient } from '../../../hooks/useMatrixClient'; import { getCanonicalAliasRoomId, isRoomAlias } from '../../../utils/matrix'; export const ACTIVE_SPACE_KEY = 'vojo.activeSpaceId'; const readPersisted = (): string | null => { try { return localStorage.getItem(ACTIVE_SPACE_KEY); } catch { return null; } }; const safeDecode = (raw: string): string | undefined => { try { return decodeURIComponent(raw); } catch { return undefined; } }; // Resolves the active Space for the channels segment. Priority: // 1. URL `:spaceIdOrAlias` param (if joined-orphan) // 2. localStorage['vojo.activeSpaceId'] (if joined-orphan) // 3. first joined-orphan Space // Returns undefined when the user has 0 joined orphan spaces. Persistence // (writing to localStorage) lives in `Channels.tsx`, where the inner // route already has the resolved space context — at the index `/channels/` // route, useParams().spaceIdOrAlias is always undefined. export const useActiveSpace = (orphanSpaceIds: string[]): string | undefined => { const mx = useMatrixClient(); const { spaceIdOrAlias } = useParams(); const orphanSet = useMemo(() => new Set(orphanSpaceIds), [orphanSpaceIds]); const urlSpaceId = useMemo(() => { if (!spaceIdOrAlias) return undefined; const decoded = safeDecode(spaceIdOrAlias); if (!decoded) return undefined; const resolved = isRoomAlias(decoded) ? getCanonicalAliasRoomId(mx, decoded) : decoded; return resolved && orphanSet.has(resolved) ? resolved : undefined; }, [mx, spaceIdOrAlias, orphanSet]); const persistedSpaceId = useMemo(() => { const stored = readPersisted(); return stored && orphanSet.has(stored) ? stored : undefined; }, [orphanSet]); return urlSpaceId ?? persistedSpaceId ?? orphanSpaceIds[0]; };