import { useEffect } from 'react'; import { useAtomValue } from 'jotai'; import { Room } from 'matrix-js-sdk'; import { allRoomsAtom } from '../state/room-list/roomList'; import { useMatrixClient } from './useMatrixClient'; import { isTauri, invokeTauri } from './useTauri'; /** Cap the Jump List to a small, glanceable set of rooms. */ const MAX_ITEMS = 8; /** Wait for room activity to settle before re-publishing the (native) list. */ const DEBOUNCE_MS = 1500; type JumpItem = { title: string; uri: string }; /** * Build the `matrix:` deep link the desktop deep-link handler understands (see * `useDeepLinkNavigate`): `matrix:r/` for a canonical alias, otherwise * `matrix:roomid/`. The sigil is dropped and the remainder is percent-encoded * because the handler decodes each segment with `decodeURIComponent`. */ const roomToUri = (room: Room): string => { const alias = room.getCanonicalAlias(); if (alias && alias.startsWith('#')) { return `matrix:r/${encodeURIComponent(alias.slice(1))}`; } return `matrix:roomid/${encodeURIComponent(room.roomId.slice(1))}`; }; /** * P5-36 — publish a Windows taskbar Jump List of the most recently-active rooms. * Rooms come from `allRoomsAtom` (the joined-room list), sorted by * `getLastActiveTimestamp` (mirroring the sort used elsewhere, e.g. the forward * dialog), with spaces excluded. The list is pushed to the native * `set_jump_list` command, debounced so bursts of activity don't thrash the * shell. No-op outside Tauri. */ export function useTauriJumpList(): void { const mx = useMatrixClient(); const allRooms = useAtomValue(allRoomsAtom); useEffect(() => { if (!isTauri()) return undefined; const timeout = setTimeout(() => { const items: JumpItem[] = allRooms .map((roomId) => mx.getRoom(roomId)) .filter((room): room is Room => room !== null && !room.isSpaceRoom()) .sort((a, b) => (b.getLastActiveTimestamp() ?? 0) - (a.getLastActiveTimestamp() ?? 0)) .slice(0, MAX_ITEMS) .map((room) => ({ title: room.name || room.roomId, uri: roomToUri(room) })); invokeTauri('set_jump_list', { items }); }, DEBOUNCE_MS); return () => clearTimeout(timeout); }, [mx, allRooms]); }