59 lines
2.2 KiB
TypeScript
59 lines
2.2 KiB
TypeScript
|
|
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/<alias>` for a canonical alias, otherwise
|
||
|
|
* `matrix:roomid/<id>`. 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]);
|
||
|
|
}
|