UI polish: live job polling, panel layout, pending button states
- Poll /api/ai-tagging/fields every 2s after any 202 (queued) response in ImageLightbox and DoomScrollView so extraction, translation, and description results appear automatically without a page refresh - DoomScrollView extract button now turns accent-coloured while a job is queued instead of flashing red; red is reserved for genuine errors - Kebab menu "Translate" option is now gated on entry.hasExtractedText (populated via a batch DB query in the browse API) so it only appears when there is text to translate - Tag panel redesigned: toolbar collapses to just the filename when open; panel header holds hide (›), AI Tagger (✨), and Close (✕) buttons; sections ordered Description → Text Extraction → Tags; description state and generate handler moved from TagSelector into ImageLightbox - VideoPlayerModal receives the same toolbar/panel restructure - TagSelector gains hideDescription prop so the parent can own description Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getLibrary, resolveLibraryRoot, resolveAndJail } from '@/lib/libraries'
|
||||
import { scanDirectory, scanDirectoryRecursive } from '@/lib/files'
|
||||
@@ -31,6 +32,21 @@ export async function GET(request: NextRequest) {
|
||||
const listing = recursive
|
||||
? scanDirectoryRecursive(root, libraryId, subpath)
|
||||
: scanDirectory(root, libraryId, subpath)
|
||||
|
||||
// Annotate image entries with whether they have extracted text
|
||||
const db = getDb()
|
||||
const rows = db
|
||||
.prepare('SELECT item_key FROM media_items WHERE library_id = ? AND extracted_text IS NOT NULL')
|
||||
.all(libraryId) as { item_key: string }[]
|
||||
const withText = new Set(rows.map((r) => r.item_key))
|
||||
|
||||
listing.entries = listing.entries.map((e) => {
|
||||
if (e.type !== 'file' || e.mediaType !== 'image') return e
|
||||
const relPath = subpath ? path.join(subpath, e.name) : e.name
|
||||
const itemKey = `${libraryId}:mixed_file:${encodeURIComponent(relPath)}`
|
||||
return { ...e, hasExtractedText: withText.has(itemKey) }
|
||||
})
|
||||
|
||||
return NextResponse.json(listing)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user