This commit is contained in:
Tomáš Dvořák
2025-10-16 13:32:05 +02:00
commit 12cba639b9
663 changed files with 168914 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
import api from './api';
export interface ZoneramaPhoto {
id: string;
page_url: string;
image_1500?: string;
title?: string;
}
export interface ZoneramaAlbumResp {
album: { id?: string; title?: string; url?: string };
photos: ZoneramaPhoto[];
}
export interface ZoneramaPickPayload {
id: string;
album_id?: string;
album_url: string;
page_url?: string;
image_url: string;
title?: string;
}
export async function getZoneramaAlbum(link: string, opts: { photo_limit?: number; rendered?: boolean } = {}): Promise<ZoneramaAlbumResp> {
const params: any = { link };
if (typeof opts.photo_limit === 'number') params.photo_limit = String(opts.photo_limit);
if (typeof opts.rendered === 'boolean') params.rendered = String(opts.rendered);
const res = await api.get<ZoneramaAlbumResp>('/zonerama/album', { params });
return res.data as any;
}
export async function getZoneramaPicks(): Promise<ZoneramaPickPayload[]> {
const res = await api.get<ZoneramaPickPayload[]>('/zonerama/picks');
return Array.isArray(res.data) ? res.data : [] as any;
}
export async function putZoneramaPick(payload: ZoneramaPickPayload): Promise<{ ok: boolean; count: number }> {
const res = await api.post<{ ok: boolean; count: number }>('/admin/zonerama/pick', payload);
return res.data;
}
export interface ZoneramaAlbumData {
id: string;
title: string;
url: string;
date: string;
photos_count: number;
views_count?: number;
photos: ZoneramaPhoto[];
fetched_at?: string;
}
export async function saveAlbumToCache(albumLink: string, photoLimit: number = 50): Promise<ZoneramaAlbumData> {
const res = await api.post<ZoneramaAlbumData>('/admin/zonerama/save-album', {
link: albumLink,
photo_limit: photoLimit
});
return res.data;
}
// Helper to read the flat manifest produced by the prefetcher for fast grid rendering
export async function getZoneramaManifest(): Promise<Array<{ id: string; album_id: string; src: string; local: string; page_url: string }>> {
const apiUrl = process.env.REACT_APP_API_URL || 'http://localhost:8080/api/v1';
const origin = new URL(apiUrl).origin;
// New unified path for prefetched Zonerama items
const url = `${origin}/cache/prefetch/zonerama_flat.json`;
const res = await fetch(url, { cache: 'no-cache' });
if (!res.ok) return [];
try {
const json = await res.json();
if (Array.isArray(json)) return json as any;
return [];
} catch {
return [];
}
}
// More robust loader that tries multiple sources for prefetched items
export async function getZoneramaManifestWithFallbacks(): Promise<Array<{ id: string; album_id: string; src: string; local: string; page_url: string }>> {
// 1) Try the main manifest
const primary = await getZoneramaManifest();
if (primary && primary.length > 0) return primary;
const apiUrl = process.env.REACT_APP_API_URL || 'http://localhost:8080/api/v1';
const origin = new URL(apiUrl).origin;
// 1b) Backward-compat removed - old path no longer used to avoid 404 errors
// 2) Try unified controller JSON (one JSON to control all prefetched albums)
try {
const ctrlUrl = `${origin}/cache/prefetch/zonerama_albums.json`;
const resCtrl = await fetch(ctrlUrl, { cache: 'no-cache' });
if (resCtrl.ok) {
const json = await resCtrl.json();
// Expect shape: { albums: [{ id, page_url, cover_local, cover_src, items: [...] }], items?: [...] }
const items = Array.isArray(json?.items) ? json.items : [];
const flatFromCtrl = items.map((it: any) => ({
id: String(it.id || it.photo_id || ''),
album_id: String(it.album_id || ''),
src: String(it.src || it.image_url || ''),
local: String(it.local || it.local_url || it.image_local || ''),
page_url: String(it.page_url || it.url || ''),
}));
if (flatFromCtrl.length > 0) return flatFromCtrl;
}
} catch { /* ignore */ }
// 3) Fall back to picks endpoint if available (admin saves picks)
try {
const picks = await getZoneramaPicks();
const mapped = picks.map((p) => ({
id: String(p.id),
album_id: String(p.album_id || ''),
src: String(p.image_url),
local: String(p.image_url),
page_url: String(p.page_url || p.album_url || ''),
}));
return mapped;
} catch { /* ignore */ }
return [];
}