Add mobile expenses and receipt OCR

This commit is contained in:
2026-06-29 01:35:00 -04:00
parent 8a3f498874
commit 8ad4210908
18 changed files with 2460 additions and 4 deletions
+50
View File
@@ -0,0 +1,50 @@
import { isSupported, recognizeText } from "expo-mlkit-ocr";
import { parseReceiptText, type ReceiptParseResult } from "@/lib/receipt-parse";
export type ReceiptOcrResult = ReceiptParseResult & {
rawText: string;
};
export function mlKitOcrAvailable(): boolean {
try {
return isSupported();
} catch {
return false;
}
}
function normalizeImageUri(uri: string): string {
if (uri.startsWith("file://") || uri.startsWith("content://")) {
return uri;
}
return `file://${uri}`;
}
/** Run on-device ML Kit OCR and parse receipt fields from recognized text. */
export async function recognizeReceiptFromImage(uri: string): Promise<ReceiptOcrResult> {
if (!mlKitOcrAvailable()) {
throw new Error("On-device OCR is not supported on this device.");
}
const result = await recognizeText(normalizeImageUri(uri));
const rawText = result.text?.trim() ?? "";
const parsed = parseReceiptText(rawText);
return {
...parsed,
rawText,
};
}
export function applyReceiptOcrToForm(
ocr: ReceiptParseResult,
current: { description: string; amountText: string; date: Date },
): { description: string; amountText: string; date: Date; ocrText: string } {
return {
description: ocr.vendor?.trim() || current.description,
amountText: ocr.amount != null ? String(ocr.amount) : current.amountText,
date: ocr.date ?? current.date,
ocrText: ocr.rawLines.join("\n"),
};
}