From bac67706b9ac56bd812c3acf6f8f63591f92afe5 Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 13 Apr 2026 10:15:55 +0200 Subject: [PATCH] feat(ocr): integrate progress bar and streaming progress into document page Replace inline translateOcrProgress with the extracted module. Add OcrProgressBar below the spinner during OCR. Parse page numbers from ANALYZING_PAGE progress codes and feed them to the bar. On Done, fill bar to 100% briefly before clearing the overlay. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/routes/documents/[id]/+page.svelte | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/frontend/src/routes/documents/[id]/+page.svelte b/frontend/src/routes/documents/[id]/+page.svelte index 5a524328..067b494c 100644 --- a/frontend/src/routes/documents/[id]/+page.svelte +++ b/frontend/src/routes/documents/[id]/+page.svelte @@ -8,6 +8,8 @@ import TranscriptionReadView from '$lib/components/TranscriptionReadView.svelte' import TranscriptionPanelHeader from '$lib/components/TranscriptionPanelHeader.svelte'; import type { TranscriptionBlockData } from '$lib/types'; import { getErrorMessage } from '$lib/errors'; +import { translateOcrProgress } from '$lib/ocr/translateOcrProgress'; +import OcrProgressBar from '$lib/components/OcrProgressBar.svelte'; let { data } = $props(); @@ -132,27 +134,9 @@ let ocrRunning = $state(false); let ocrProgressMessage = $state(''); let ocrErrorMessage = $state(''); let ocrPollTimer = $state | null>(null); - -function translateOcrProgress(code: string): string { - if (!code) return m.ocr_progress_heading(); - const [key, param] = code.split(':'); - switch (key) { - case 'PREPARING': - return m.ocr_status_preparing(); - case 'LOADING': - return m.ocr_status_loading(); - case 'ANALYZING': - return m.ocr_status_analyzing(); - case 'CREATING_BLOCKS': - return m.ocr_status_creating_blocks({ count: param ?? '0' }); - case 'DONE': - return m.ocr_status_done_blocks({ count: param ?? '0' }); - case 'ERROR': - return m.ocr_status_error(); - default: - return code; - } -} +let ocrCurrentPage = $state(0); +let ocrTotalPages = $state(0); +let ocrSkippedPages = $state(0); async function triggerOcr(scriptType: string) { ocrRunning = true; @@ -186,12 +170,23 @@ function pollOcrJob(jobId: string) { const res = await fetch(`/api/ocr/jobs/${jobId}`); if (!res.ok) return; const job = await res.json(); - ocrProgressMessage = job.progressMessage ?? ''; + const rawCode = job.progressMessage ?? ''; + const progress = translateOcrProgress(rawCode); + ocrProgressMessage = progress.message; + if (progress.currentPage !== undefined) ocrCurrentPage = progress.currentPage; + if (progress.totalPages !== undefined) ocrTotalPages = progress.totalPages; + if (progress.skippedPages !== undefined) ocrSkippedPages = progress.skippedPages; if (job.status === 'DONE' || job.status === 'FAILED') { + ocrCurrentPage = ocrTotalPages; if (ocrPollTimer) clearInterval(ocrPollTimer); ocrPollTimer = null; - ocrRunning = false; - ocrProgressMessage = ''; + setTimeout(() => { + ocrRunning = false; + ocrProgressMessage = ''; + ocrCurrentPage = 0; + ocrTotalPages = 0; + ocrSkippedPages = 0; + }, 1000); if (job.status === 'FAILED') { ocrErrorMessage = m.ocr_status_error(); } @@ -439,8 +434,13 @@ onMount(() => { {m.ocr_progress_heading()}

- {translateOcrProgress(ocrProgressMessage)} + {ocrProgressMessage}

+ {:else if panelMode === 'read'}