diff --git a/frontend/src/utils/ocr.js b/frontend/src/utils/ocr.js new file mode 100644 index 0000000..4501ee4 --- /dev/null +++ b/frontend/src/utils/ocr.js @@ -0,0 +1,116 @@ +import { createAssetView, resolveDocumentAssetUrl } from '../asset_manager'; + +const BASE_FETCH_OPTIONS = { start: 1, limit: 1 }; + +const pickAsset = (doc, getDocumentAsset) => { + if (!doc || typeof getDocumentAsset !== 'function') { + return null; + } + return getDocumentAsset(doc, 'ocr-text') || null; +}; + +export async function resolveOcrTextUrl({ + document, + ensurePreviewData, + getDocumentAsset, + ensureAssetUrl, +}) { + if (!document?.id) { + return null; + } + + let docRef = document; + let asset = pickAsset(docRef, getDocumentAsset); + + if (!asset && typeof ensurePreviewData === 'function') { + try { + const refreshed = await ensurePreviewData(docRef.id); + if (refreshed) { + docRef = refreshed; + } + asset = pickAsset(docRef, getDocumentAsset); + } catch (error) { + throw error; + } + } + + if (!asset) { + return null; + } + + const baseView = createAssetView(asset); + const hasUrl = Boolean(baseView.getPrimaryUrl()); + + let entry = asset; + if (typeof ensureAssetUrl === 'function') { + const ensureOptions = { ...BASE_FETCH_OPTIONS, force: !hasUrl }; + entry = (await ensureAssetUrl(docRef.id, asset, ensureOptions)) || asset; + } + + const ensuredView = createAssetView(entry); + const directUrl = ensuredView.getPrimaryUrl(); + if (directUrl) { + return directUrl; + } + + return ( + resolveDocumentAssetUrl(docRef, 'ocr-text', { + ensureAssetUrl, + getAsset: getDocumentAsset, + ensureOptions: { ...BASE_FETCH_OPTIONS, force: true }, + objectOrdinal: 1, + }) || null + ); +} + +export async function openOcrTextInNewTab(options) { + const popup = window.open('', '_blank'); + const popupAvailable = Boolean(popup); + + if (popupAvailable) { + try { + popup.opener = null; + } catch (error) { + /* ignore */ + } + } + + try { + const url = await resolveOcrTextUrl(options); + if (!url) { + if (popupAvailable) { + popup.close(); + } + return false; + } + + if (popupAvailable) { + try { + popup.location.replace(url); + } catch (navigationError) { + try { + popup.location.href = url; + } catch (secondError) { + popup.close(); + throw secondError; + } + } + } else { + const finalWindow = window.open(url, '_blank'); + if (finalWindow) { + try { + finalWindow.opener = null; + } catch (error) { + /* ignore */ + } + } + } + + return true; + } catch (error) { + if (popupAvailable) { + popup.close(); + } + throw error; + } +}