diff --git a/portal/src/views/FilesView.vue b/portal/src/views/FilesView.vue index 710a9dd..1310372 100644 --- a/portal/src/views/FilesView.vue +++ b/portal/src/views/FilesView.vue @@ -220,7 +220,8 @@ function getMediaType(fileName: string): 'video' | 'photo' { } const displayFiles = computed(() => { - let result = files.value + // Start with a copy to avoid mutation issues + let result = [...files.value] // Filter by media type if (mediaType.value !== 'all') { @@ -263,7 +264,20 @@ async function fetchFiles() { try { const config = getCurrentConfig() - // Get registered files with real processing status FIRST + // Get scan results FIRST (source of truth for files on disk) + const scanResp = await httpFetch(`${config.api_base_url}/api/v1/files/scan`) + const scanFiles: any[] = (scanResp?.files || []).map((f: any) => { + const mediaType = getMediaType(f.file_name) + return { + ...f, + media_type: mediaType, + is_indexed: false, + // Use scan API's is_registered field as default status + status: f.is_registered ? 'pending' : 'unregistered' + } + }) + + // Get registered files with real processing status let regFiles: any[] = [] try { const regResp = await httpFetch(`${config.api_base_url}/api/v1/files?page=1&page_size=200`) @@ -277,38 +291,37 @@ async function fetchFiles() { } }) } catch { - // Registered files API may not be available + // Registered files API may not be available; scan data will be used as fallback + console.warn('Failed to fetch registered files, using scan data as fallback') } - // Get scan results - const scanResp = await httpFetch(`${config.api_base_url}/api/v1/files/scan`) - const scanFiles: any[] = (scanResp?.files || []).map((f: any) => { - const mediaType = getMediaType(f.file_name) - return { - ...f, - media_type: mediaType, - is_indexed: false - } - }) - - // Build a set of registered file paths for quick lookup - const registeredPaths = new Set(regFiles.map(f => f.file_path)) + // Build a map of registered files by file_path for quick lookup + const regMap = new Map() + for (const f of regFiles) { + regMap.set(f.file_path, f) + } // Merge: start with scan results, override with registered data where available const merged = new Map() // First pass: add all scan results for (const f of scanFiles) { - const isRegistered = registeredPaths.has(f.file_path) - merged.set(f.file_path, { - ...f, - status: isRegistered ? 'pending' : 'unregistered' - }) + merged.set(f.file_path, { ...f }) } - // Second pass: override with real registered data + // Second pass: override with real registered data (only for files that exist in scan) for (const f of regFiles) { - merged.set(f.file_path, f) + if (merged.has(f.file_path)) { + // File exists on disk, update with real status + const existing = merged.get(f.file_path) + merged.set(f.file_path, { + ...existing, + ...f, + media_type: f.media_type || existing.media_type, + is_indexed: f.is_indexed || existing.is_indexed + }) + } + // If file not in scan, it might have been deleted from disk - skip it } files.value = Array.from(merged.values())