From 3f81d1a198bd30bca8a1264d143455b06db08429 Mon Sep 17 00:00:00 2001 From: McElwain Date: Sat, 9 May 2026 17:55:29 -0500 Subject: [PATCH] Add in-browser OCR overlay toggle controls --- app/routes/documents.py | 54 ++++++++++++ app/templates/documents/detail.html | 123 +++++++++++++++++++++++++++- 2 files changed, 176 insertions(+), 1 deletion(-) diff --git a/app/routes/documents.py b/app/routes/documents.py index 1f40b71..f679bac 100644 --- a/app/routes/documents.py +++ b/app/routes/documents.py @@ -1749,6 +1749,60 @@ def document_detail(document_id: str, request: Request, queue: str | None = None replica_scan_backed_output = _get_latest_replica_output(document, "scan_backed") replica_debug_overlay_output = _get_latest_replica_output(document, "debug_overlay") + overlay_page_data = [] + try: + current_text_version_for_overlay = next( + ( + tv for tv in sorted( + getattr(document, "text_versions", []), + key=lambda x: (x.version_number, x.created_at), + reverse=True, + ) + if tv.is_current + ), + None, + ) + overlay_pages = ((current_text_version_for_overlay.layout_json or {}).get("pages", []) if current_text_version_for_overlay and current_text_version_for_overlay.layout_json else []) or [] + for page in overlay_pages: + page_width = float(page.get("page_width") or page.get("image_width") or 1.0) + page_height = float(page.get("page_height") or page.get("image_height") or 1.0) + + words = [] + for word in page.get("words", []) or []: + bbox = word.get("bbox") or [0, 0, 0, 0] + if not isinstance(bbox, (list, tuple)) or len(bbox) != 4: + continue + words.append({ + "text": (word.get("text") or "").strip(), + "bbox": [float(bbox[0]), float(bbox[1]), float(bbox[2]), float(bbox[3])], + }) + + lines = [] + source_lines = [] + for region in page.get("regions", []) or []: + source_lines.extend(region.get("lines", []) or []) + if not source_lines: + source_lines = page.get("lines", []) or [] + + for line in source_lines: + bbox = line.get("bbox") or [0, 0, 0, 0] + if not isinstance(bbox, (list, tuple)) or len(bbox) != 4: + continue + lines.append({ + "text": (line.get("text") or "").strip(), + "bbox": [float(bbox[0]), float(bbox[1]), float(bbox[2]), float(bbox[3])], + }) + + overlay_page_data.append({ + "page": page.get("page"), + "page_width": page_width, + "page_height": page_height, + "words": words, + "lines": lines, + }) + except Exception: + overlay_page_data = [] + scan_path = document.current_path replica_path = replica_clean_output.file_path if replica_clean_output and replica_clean_output.file_path else None replica_scan_backed_path = replica_scan_backed_output.file_path if replica_scan_backed_output and replica_scan_backed_output.file_path else None diff --git a/app/templates/documents/detail.html b/app/templates/documents/detail.html index a1ca3b4..c2e4dbb 100644 --- a/app/templates/documents/detail.html +++ b/app/templates/documents/detail.html @@ -272,13 +272,40 @@ document.addEventListener("DOMContentLoaded", () => { Replica (Debug) {% endif %} + {% if overlay_page_data %} +
+ + + + +
+ {% endif %} + {% if not storage_available %}

Storage mount unavailable. Preview is temporarily unavailable.

{% elif file_url %} {% if document.mime_type == "application/pdf" %} - +
+ + {% if overlay_page_data %} +
+ + {% endif %} +
{% elif document.mime_type in ["image/jpeg", "image/png"] %} Document image {% else %} @@ -898,3 +925,97 @@ document.addEventListener("DOMContentLoaded", () => { {% endblock %} + + + +