diff --git a/docker/frontend/src/Library.tsx b/docker/frontend/src/Library.tsx index d48da9c..e127cba 100644 --- a/docker/frontend/src/Library.tsx +++ b/docker/frontend/src/Library.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useReducer, useRef, useState, type CSSProperties } from 'react'; +import { useCallback, useEffect, useMemo, useReducer, useRef, useState, type CSSProperties, type RefObject } from 'react'; import { useI18n } from './i18n/I18nProvider'; import { go } from './nav'; import { api } from './api'; @@ -72,6 +72,13 @@ const COLUMN_DEFAULT = 118; // handful of ticks the thumbnail behind the preview runs out of pixels anyway. const ZOOM_MAX = 6; const ZOOM_STEP = 1.15; +// The strip's tile: `.adm-thumb` is 132px wide and `.adm-filmstrip` leaves 8px +// between tiles, so a tile takes 140px of the strip wherever it sits. +const TILE_STEP = 140; +// How many tiles past each edge of the strip are drawn. Enough that a fast drag +// meets pictures rather than placeholders, few enough that the count does not +// matter: what is drawn is this many, whatever the shelf holds. +const STRIP_KEEP = 8; // The hours a frame's own clock can read, and what the time filter offers: the // whole day in the 24-hour form a camera writes into EXIF. const HOURS = Array.from({ length: 24 }, (_, i) => i); @@ -609,7 +616,21 @@ export function Library() { }, [deep, node, photos, rootName]); const frame = shown.find((p) => p.id === up) ?? shown[0] ?? null; - const urls = useThumbUrls(shown); + // The strip draws the tiles around the one under the eye, not the whole shelf. + // A roll is thousands of frames and every tile drawn costs a ` ))} + {shown.length - strip.to > 0 ? ( +