diff --git a/frontend/src/detail/DetailPanel.jsx b/frontend/src/detail/DetailPanel.jsx index 11cb512..1ded293 100644 --- a/frontend/src/detail/DetailPanel.jsx +++ b/frontend/src/detail/DetailPanel.jsx @@ -1106,6 +1106,69 @@ const DetailPanel = ({ return () => window.removeEventListener('keydown', handleKeyDown); }, [zoomedPreview, zoomDisplay]); + useEffect(() => { + if (typeof ensureAssetUrl !== 'function') { + return; + } + + const warmNavigator = (navigator) => { + const { + documentId, + asset, + ordinal, + canGoPrev, + canGoNext, + cardinality, + } = navigator; + if (!documentId || !asset || !Number.isFinite(ordinal)) { + return; + } + + const requests = []; + if (canGoPrev) { + const prevOrdinal = Math.max(1, ordinal - 1); + if (!cardinality || prevOrdinal <= cardinality) { + requests.push( + ensureAssetUrl(documentId, asset, { + start: prevOrdinal, + limit: 1, + objectOrdinal: prevOrdinal, + }), + ); + } + } + if (canGoNext) { + const nextOrdinal = ordinal + 1; + if (!cardinality || nextOrdinal <= cardinality) { + requests.push( + ensureAssetUrl(documentId, asset, { + start: nextOrdinal, + limit: 1, + objectOrdinal: nextOrdinal, + }), + ); + } + } + + requests.forEach((promise) => promise?.catch?.(() => {})); + }; + + warmNavigator(singlePreviewNavigator); + warmNavigator(stackPreviewNavigator); + }, [ + ensureAssetUrl, + singlePreviewNavigator.documentId, + singlePreviewNavigator.asset, + singlePreviewNavigator.ordinal, + singlePreviewNavigator.canGoPrev, + singlePreviewNavigator.canGoNext, + stackPreviewNavigator.documentId, + stackPreviewNavigator.asset, + stackPreviewNavigator.ordinal, + stackPreviewNavigator.canGoPrev, + stackPreviewNavigator.canGoNext, + ]); + const zoomImageStyle = useMemo(() => { if (!zoomNative) { return {