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'}