Wire admin studio SSR and search infrastructure

This commit is contained in:
2026-05-01 11:46:06 +02:00
parent 257b0dbef6
commit 18cea8b0f0
329 changed files with 197465 additions and 2741 deletions

View File

@@ -10,6 +10,21 @@ import { useNavContext } from '../../lib/useNavContext';
const preloadCache = new Set();
function scheduleIdleTask(callback, delay = 1200) {
if (typeof window === 'undefined') {
callback();
return () => {};
}
if (typeof window.requestIdleCallback === 'function') {
const handle = window.requestIdleCallback(callback, { timeout: delay });
return () => window.cancelIdleCallback(handle);
}
const handle = window.setTimeout(callback, delay);
return () => window.clearTimeout(handle);
}
function preloadImage(src) {
if (!src || preloadCache.has(src)) return;
preloadCache.add(src);
@@ -44,20 +59,33 @@ export default function ArtworkNavigator({ artworkId, onNavigate, onOpenViewer,
getNeighbors().then((n) => {
if (cancelled) return;
setNeighbors(n);
[n.prevId, n.nextId].forEach((id) => {
if (!id) return;
});
return () => { cancelled = true; };
}, [artworkId, getNeighbors]);
useEffect(() => {
const ids = [neighbors.prevId, neighbors.nextId].filter(Boolean);
if (ids.length === 0) return undefined;
let cancelled = false;
const cancelIdleTask = scheduleIdleTask(() => {
ids.forEach((id) => {
fetch(`/api/artworks/${id}/page`, { headers: { Accept: 'application/json' } })
.then((r) => r.ok ? r.json() : null)
.then((data) => {
if (!data) return;
if (cancelled || !data) return;
const imgUrl = data.thumbs?.lg?.url || data.thumbs?.md?.url;
if (imgUrl) preloadImage(imgUrl);
})
.catch(() => {});
});
});
return () => { cancelled = true; };
}, [artworkId, getNeighbors]);
return () => {
cancelled = true;
cancelIdleTask();
};
}, [neighbors.prevId, neighbors.nextId]);
// Stable navigate — reads state via refs, never recreated
const navigate = useCallback(async (targetId, targetUrl) => {