diff --git a/frontend/src/components/ScanProgress.tsx b/frontend/src/components/ScanProgress.tsx index 00ee8ee..a578885 100644 --- a/frontend/src/components/ScanProgress.tsx +++ b/frontend/src/components/ScanProgress.tsx @@ -28,20 +28,20 @@ export function ScanProgress() { queryKey: ['scan-status'], queryFn: () => library.scanStatus(), refetchInterval: (query) => - query.state.data?.is_scanning ? 2000 : 10000, + query.state.data?.is_scanning ? 2000 : 30000, enabled: true, }) const isScanning = scanStatus?.is_scanning ?? false // Poll worker status to track vision queue activity. - // Fast polling (3s) while processing, slow (15s) otherwise. + // Fast polling (3s) while processing, slow (30s) otherwise. const { data: workerStatus } = useQuery({ queryKey: ['worker-status-progress'], queryFn: () => library.maintenance.workerStatus(), refetchInterval: (query) => { const q = totalQueued(query.state.data) - return q > 0 ? 3000 : 15000 + return q > 0 ? 3000 : 30000 }, enabled: true, }) diff --git a/frontend/src/hooks/usePhotosQuery.ts b/frontend/src/hooks/usePhotosQuery.ts index f3083b0..05c44bd 100644 --- a/frontend/src/hooks/usePhotosQuery.ts +++ b/frontend/src/hooks/usePhotosQuery.ts @@ -81,17 +81,19 @@ export function usePhotosQuery() { // seeks directly to the next slice via an indexed range scan, // O(1) regardless of depth (no OFFSET skipping). // - // MAX_PAGES is intentionally modest: 20 × 500 = 10 000 photos - // covers almost every browsing session up-front without burning - // through a 100k library on cold load. If a user scrolls past - // that horizon we'll add an infinite-query trigger; for now the - // cap keeps cold-load memory / network pressure sane. - const PER_PAGE = 500 + // First page is small (~one viewport) so the grid paints fast; + // background pages are larger so we still cover ~10k photos in + // a few round-trips without burning through a 100k library on + // cold load. If a user scrolls past that horizon we'll add an + // infinite-query trigger; for now the cap keeps cold-load + // memory / network pressure sane. + const PER_PAGE_INITIAL = 100 + const PER_PAGE_BACKGROUND = 500 const MAX_PAGES = 20 const INTER_PAGE_DELAY_MS = 50 const first = await fetchCursorPage( - { per_page: PER_PAGE, ...filterParams }, + { per_page: PER_PAGE_INITIAL, ...filterParams }, signal, ) const firstBatch = first.photos || [] @@ -104,7 +106,7 @@ export function usePhotosQuery() { if (signal?.aborted) return try { const page = await fetchCursorPage( - { per_page: PER_PAGE, cursor: nextCursor, ...filterParams }, + { per_page: PER_PAGE_BACKGROUND, cursor: nextCursor, ...filterParams }, signal, ) if (signal?.aborted) return @@ -114,7 +116,7 @@ export function usePhotosQuery() { ['photos', filterParams], (prev) => (prev ? [...prev, ...more] : more) ) - if (!nextCursor || more.length < PER_PAGE) return + if (!nextCursor || more.length < PER_PAGE_BACKGROUND) return // Yield a beat between pages so the main thread stays // responsive (thumbnail decode, scroll handling) while // we're back-filling in the background. diff --git a/frontend/src/hooks/useScanActivity.ts b/frontend/src/hooks/useScanActivity.ts index f74583e..84df37a 100644 --- a/frontend/src/hooks/useScanActivity.ts +++ b/frontend/src/hooks/useScanActivity.ts @@ -49,14 +49,14 @@ export function useScanActivity() { queryKey: ['scan-status'], queryFn: () => library.scanStatus(), refetchInterval: (query) => - query.state.data?.is_scanning ? 2000 : 10000, + query.state.data?.is_scanning ? 2000 : 30000, }) const { data: workerStatus } = useQuery({ queryKey: ['worker-status-progress'], queryFn: () => library.maintenance.workerStatus(), refetchInterval: (query) => { const data = query.state.data - return pendingTasks(data) + activeTasks(data) > 0 ? 3000 : 15000 + return pendingTasks(data) + activeTasks(data) > 0 ? 3000 : 30000 }, })