Files
lanspread/crates/lanspread-tauri-deno-ts/src/hooks/useThumbnails.ts
T
ddidderr 71dbf27d8b feat(app): expose local sharing and verified transfers
Add a durable, acknowledged Local network sharing switch with fail-closed
hydration, serialized mutation, and redacted ephemeral-identity diagnostics.
Keep local Call-to-Play state available while gating every network action on the
effective sharing generation.

Render revisioned verification, invalid-source retry, and sticky source
exhaustion states. Preserve opaque attempt IDs through progress delivery so
out-of-order webview events cannot attach stale bytes to a successor transfer,
and keep terminal exhaustion visible after the last source departs.

Own listeners, native invokes, persistence, dialogs, and companion-window
creation through webview close. Late creation is settled and cleaned before the
parent realm is destroyed.

Test Plan:
- `just frontend-test` -- passed (91/91)
- `just build` -- passed with TypeScript, Vite, and release Tauri compilation
- `just test` -- passed on the completed stack (708 workspace tests)
- `just clippy` -- passed on the completed stack
- `git diff --cached --check` -- passed
2026-08-10 13:59:40 +02:00

44 lines
1.6 KiB
TypeScript

import { useCallback, useEffect, useRef, useState } from 'react';
import { invoke } from '@tauri-apps/api/core';
import {
createThumbnailRequestKey,
startOwnedThumbnailGeneration,
ThumbnailRequestGeneration,
thumbnailIdsFromRequestKey,
} from '../lib/thumbnailRequests';
import { windowAsyncScope } from '../lib/asyncOwnership';
/**
* Per-id cache for cover thumbnails belonging to the supplied game ids.
* Returns `null` until the value is known; returns the empty string when the
* backend has nothing for the id, so callers can use the placeholder cover.
*/
export const useThumbnails = (ids: readonly string[]) => {
const [thumbnails, setThumbnails] = useState<Map<string, string>>(new Map());
const thumbnailsRef = useRef(thumbnails);
const requestKey = createThumbnailRequestKey(ids);
useEffect(() => {
const generation = new ThumbnailRequestGeneration(
id => invoke<string>('get_game_thumbnail', { gameId: id }),
(id, url) => {
const next = new Map(thumbnailsRef.current).set(id, url);
thumbnailsRef.current = next;
setThumbnails(next);
},
);
const missingIds = thumbnailIdsFromRequestKey(requestKey)
.filter(id => !thumbnailsRef.current.has(id));
return startOwnedThumbnailGeneration(windowAsyncScope, generation, missingIds);
}, [requestKey]);
const get = useCallback((id: string): string | null => {
if (thumbnails.has(id)) return thumbnails.get(id) ?? '';
return null;
}, [thumbnails]);
return { get };
};