Speed up timeline load with portrait thumbs, bootstrap API, and caching.

Add catalog bootstrap endpoint, portrait thumbnail pipeline, lazy queued timeline images, gzip compression, and 3D texture throttling with code-split VirtualGallery.
This commit is contained in:
Danila Khodjaef
2026-07-06 14:27:29 +03:00
parent bdddadc4d6
commit 99b8559607
117 changed files with 646 additions and 171 deletions
+25 -2
View File
@@ -1,5 +1,6 @@
import type {
TimelineData,
CatalogBootstrap,
YearBounds,
Artist,
ArtistDetail,
@@ -62,13 +63,25 @@ export function portraitUrl(path: string | null | undefined, revision?: number):
return `${base}${base.includes('?') ? '&' : '?'}v=${revision}`;
}
/** Image for 3D gallery — local cached files only (API fetch is too slow for realtime 3D) */
/** Small portrait for timeline / movement flow (~256px). Falls back to full portrait. */
export function portraitThumbUrl(
artist: {
portrait_thumb_path?: string | null;
portrait_path?: string | null;
},
revision?: number
): string {
const path = artist.portrait_thumb_path || artist.portrait_path;
return portraitUrl(path, revision);
}
/** Image for 3D gallery — prefer thumbnail for faster texture loads */
export function galleryImageUrl(painting: {
thumbnail_path?: string | null;
image_path?: string | null;
}): string | null {
if (painting.image_path) return `/images/${painting.image_path}`;
if (painting.thumbnail_path) return `/images/${painting.thumbnail_path}`;
if (painting.image_path) return `/images/${painting.image_path}`;
return null;
}
@@ -202,6 +215,14 @@ export interface PaintingCheckupData {
export const api = {
getBounds: () => fetchJson<YearBounds>(`${API}/bounds`),
getCatalogBootstrap: (start?: number, end?: number) => {
const params = new URLSearchParams();
if (start != null) params.set('start', String(start));
if (end != null) params.set('end', String(end));
const qs = params.toString();
return fetchJson<CatalogBootstrap>(`${API}/catalog/bootstrap${qs ? `?${qs}` : ''}`);
},
getTimeline: (start: number, end: number) =>
fetchJson<TimelineData>(`${API}/timeline?start=${start}&end=${end}`),
@@ -345,6 +366,8 @@ export const api = {
}
return res.json() as Promise<{ checked: boolean; fixed: boolean }>;
}),
preloadArtistImages,
};
export function debugImageProxyUrl(