vojo/src/app/pages/client/channels/useActiveSpace.ts

51 lines
1.8 KiB
TypeScript

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];
};