Add paginated library JSON and dedicated still thumbs that never stream archive masters.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-09-29 19:45:22 -05:00
co-authored by Cursor
parent 845ee5bbf6
commit aa0aa871e4
10 changed files with 315 additions and 37 deletions
+10 -7
View File
@@ -802,7 +802,11 @@ function applyLibrary(data: unknown) {
}
async function loadLibrary() {
applyLibrary(await $fetch('/api/library?light=1'))
// First page of metadata only — grid paints immediately; full catalog follows for grouping/search
const first = await $fetch<any>('/api/library?limit=50')
applyLibrary(first)
const data = await $fetch<any>('/api/library?light=1')
applyLibrary(data)
}
function folderChipCount(folder: LibraryFolder) {
@@ -881,7 +885,7 @@ async function toggleFocusedHidden() {
function thumbSrc(entry: LibraryEntry) {
if (entry.kind === 'clip' && entry.group) return `/api/library/clips/${entry.group.head.id}/thumb`
if (entry.kind === 'track') return ''
if (entry.stillGroup) return `/api/library/stills/${entry.stillGroup.parts[cardImageIndex(entry)].id}?thumb=1`
if (entry.stillGroup) return `/api/library/stills/${entry.stillGroup.parts[cardImageIndex(entry)].id}/thumb`
return ''
}
@@ -907,7 +911,7 @@ function partThumb(part: LibraryClip | LibraryStill) {
// Prefer this clip’s first frame so siblings don’t all look like the Start thumb.
return `/api/library/clips/${clip.id}/first-frame?thumb=1&v=${encodeURIComponent(clip.id)}`
}
return `/api/library/stills/${part.id}?thumb=1`
return `/api/library/stills/${part.id}/thumb`
}
function focusPart(id: string) {
@@ -1309,10 +1313,9 @@ let resizeObserver: ResizeObserver | null = null
let observedScroller: HTMLElement | null = null
onMounted(async () => {
window.addEventListener('keydown', onKey)
const [me] = await Promise.all([
$fetch<{ user?: { name?: string; email?: string }; authEnabled?: boolean; authMode?: string; instanceName?: string }>('/api/auth/me').catch(() => ({ user: null })),
loadLibrary().catch(() => applyLibrary({ folders: [], clips: [], stills: [] }))
])
// Do not block chrome/grid on the full catalog — first page paints via loadLibrary's first apply
void loadLibrary().catch(() => applyLibrary({ folders: [], clips: [], stills: [] }))
const me = await $fetch<{ user?: { name?: string; email?: string }; authEnabled?: boolean; authMode?: string; instanceName?: string }>('/api/auth/me').catch(() => ({ user: null }))
instanceName.value = me.instanceName || instanceName.value
await nextTick()
measure()