Files
papercrate/frontend/src/utils/ocr.ts
T
2025-11-22 00:28:11 +01:00

140 lines
3.2 KiB
TypeScript

import { createAssetView, resolveDocumentAssetUrl } from '../asset_manager';
import type {
DocumentLike as AssetManagerDocumentLike,
DocumentVersionLike,
AssetLike as AssetManagerAssetLike,
GetAsset as AssetManagerGetAsset,
} from '../asset_manager';
export interface DocumentLike extends AssetManagerDocumentLike {
current_version?: DocumentVersionLike | null;
}
export type AssetLike = AssetManagerAssetLike;
export type EnsurePreviewData = (id: string | number) => Promise<DocumentLike | null>;
export type EnsureAssetUrl = (
id: string | number,
asset: AssetLike,
options?: { force?: boolean },
) => Promise<AssetLike | null>;
export type GetDocumentAsset = AssetManagerGetAsset;
interface ResolveOcrTextUrlOptions {
document: DocumentLike | null;
ensurePreviewData?: EnsurePreviewData;
getDocumentAsset?: GetDocumentAsset;
ensureAssetUrl?: EnsureAssetUrl;
}
const pickAsset = (doc?: DocumentLike | null, getDocumentAsset?: GetDocumentAsset): AssetLike | null => {
if (!doc || !getDocumentAsset) {
return null;
}
return getDocumentAsset(doc, 'ocr-text') || null;
};
export async function resolveOcrTextUrl({
document,
ensurePreviewData,
getDocumentAsset,
ensureAssetUrl,
}: ResolveOcrTextUrlOptions): Promise<string | null> {
if (!document?.id) {
return null;
}
let docRef = document;
let asset = pickAsset(docRef, getDocumentAsset);
if (!asset && ensurePreviewData) {
const refreshed = await ensurePreviewData(docRef.id);
if (refreshed) {
docRef = refreshed;
}
asset = pickAsset(docRef, getDocumentAsset);
}
if (!asset) {
return null;
}
const baseView = createAssetView(asset);
const hasUrl = Boolean(baseView.getPrimaryUrl());
let entry: AssetLike = asset;
if (ensureAssetUrl) {
const ensureOptions = { force: !hasUrl };
const ensured = await ensureAssetUrl(docRef.id!, asset, ensureOptions);
if (ensured) {
entry = ensured;
}
}
const ensuredView = createAssetView(entry);
const directUrl = ensuredView.getPrimaryUrl();
if (directUrl) {
return directUrl;
}
return (
resolveDocumentAssetUrl(docRef, 'ocr-text', {
ensureAssetUrl,
getAsset: getDocumentAsset,
ensureOptions: { force: true },
}) || null
);
}
export async function openOcrTextInNewTab(options: ResolveOcrTextUrlOptions): Promise<boolean> {
const popup = window.open('', '_blank');
const popupAvailable = Boolean(popup);
if (popupAvailable) {
try {
popup.opener = null;
} catch {
/* ignore */
}
}
try {
const url = await resolveOcrTextUrl(options);
if (!url) {
if (popupAvailable) {
popup.close();
}
return false;
}
if (popupAvailable) {
try {
popup.location.replace(url);
} catch {
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 {
/* ignore */
}
}
}
return true;
} catch (error) {
if (popupAvailable) {
popup.close();
}
throw error;
}
}