Make library hide/show instant on the grid and skip disk checks on browse.

The details pane keeps the real file so inspection is not delayed.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Towsty
2026-08-30 18:37:29 -05:00
co-authored by Cursor
parent e89b47b5f9
commit 845a037949
5 changed files with 122 additions and 52 deletions
+26 -11
View File
@@ -453,14 +453,25 @@ export function publicFolder(event: H3Event, folder: LibraryFolder, clipCount =
}
}
export function publicLibrary(event: H3Event) {
export function publicLibrary(event: H3Event, opts?: { light?: boolean }) {
const light = opts?.light === true
const owner = libraryOwnerKey(event)
const catalog = readCatalog(owner)
const clipIds = new Set(catalog.clips.map(clip => clip.id.toLowerCase()))
const clipCounts = new Map<string, number>()
const imageCounts = new Map<string, number>()
for (const clip of catalog.clips) {
clipCounts.set(clip.folderId, (clipCounts.get(clip.folderId) || 0) + 1)
}
for (const still of catalog.stills) {
if (isPipelineStill(catalog, still, clipIds) || stillRole(still) !== 'output') continue
imageCounts.set(still.folderId, (imageCounts.get(still.folderId) || 0) + 1)
}
const folders = catalog.folders.map(folder => publicFolder(
event,
folder,
catalog.clips.filter(clip => clip.folderId === folder.id).length,
catalog.stills.filter(still => still.folderId === folder.id && !isPipelineStill(catalog, still) && stillRole(still) === 'output').length
clipCounts.get(folder.id) || 0,
imageCounts.get(folder.id) || 0
))
const unlockedIds = new Set(folders.filter(folder => folder.unlocked).map(folder => folder.id))
return {
@@ -468,11 +479,11 @@ export function publicLibrary(event: H3Event) {
clips: catalog.clips.filter(clip => unlockedIds.has(clip.folderId)).map(clip => ({
...clip,
name: clipTitle(clip),
hasThumbnail: !clip.hideThumbnail && existsSync(clipThumbPath(owner, clip.id)),
hasVideo: existsSync(clipVideoPath(owner, clip.id))
hasThumbnail: light ? !clip.hideThumbnail : !clip.hideThumbnail && existsSync(clipThumbPath(owner, clip.id)),
hasVideo: light ? true : existsSync(clipVideoPath(owner, clip.id))
})),
stills: catalog.stills
.filter(still => unlockedIds.has(still.folderId) && !isPipelineStill(catalog, still))
.filter(still => unlockedIds.has(still.folderId) && !isPipelineStill(catalog, still, clipIds))
.map(still => ({ ...still, role: stillRole(still) })),
drafts: catalog.drafts,
loraAliases: catalog.loraAliases || {}
@@ -1057,10 +1068,11 @@ function clipIdFromStillFilename(name: string) {
return match ? match[1].toLowerCase() : ''
}
function isPipelineStill(catalog: Catalog, still: LibraryStill) {
function isPipelineStill(catalog: Catalog, still: LibraryStill, clipIds?: Set<string>) {
if (lastFrameStillName(still.filename)) return true
const clipId = clipIdFromStillFilename(still.filename)
if (!clipId) return false
if (clipIds) return clipIds.has(clipId)
return catalog.clips.some(clip => clip.id.toLowerCase() === clipId)
}
@@ -1391,11 +1403,13 @@ export function moveStillFamily(owner: string, id: string, folderId: string) {
})
}
export function setStillHidden(owner: string, id: string, hide: boolean) {
export function setStillHidden(owner: string, id: string, hide: boolean, family = false) {
return mutate(owner, (catalog) => {
const still = catalog.stills.find(item => item.id === id)
if (!still) throw createError({ statusCode: 404, statusMessage: 'Image not found' })
still.hideInput = hide === true
const targets = family ? stillsInSameFamily(catalog, still) : [still]
if (!targets.some(item => item.id === still.id)) targets.push(still)
for (const item of targets) item.hideInput = hide === true
return still
})
}
@@ -1603,11 +1617,12 @@ export function moveClipFamily(owner: string, id: string, folderId: string) {
})
}
export function setClipHidden(owner: string, id: string, hide: boolean) {
export function setClipHidden(owner: string, id: string, hide: boolean, family = false) {
return mutate(owner, (catalog) => {
const clip = catalog.clips.find(item => item.id === id)
if (!clip) throw createError({ statusCode: 404, statusMessage: 'Clip not found' })
clip.hideThumbnail = hide === true
const targets = family ? clipsInSameFamily(catalog, clip) : [clip]
for (const item of targets) item.hideThumbnail = hide === true
return clip
})
}