import Ionicons from "@expo/vector-icons/Ionicons"; import { AsyncContent, BadgeTimer, Text } from "ayasofyazilim-mobile-ui"; import { CameraCapturedPicture, CameraView, useCameraPermissions, } from "expo-camera"; import { parse, ParseResult } from "mrz"; import React, { useRef, useState } from "react"; import { TouchableOpacity, View } from "react-native"; import MlkitOcr, { MlkitOcrResult } from "react-native-mlkit-ocr"; import { AskCameraPermission } from "./components/AskCameraPermission"; import { cropImage } from "./lib/camera"; export function PassportScanner({ handlePassportScanned, isProcessingPassport, alignMrzText, analyzingText, tryAgainText, }: { handlePassportScanned: (mrzResult: ParseResult) => void; isProcessingPassport: boolean; alignMrzText: string; analyzingText: string; tryAgainText: string; }) { const cameraRef = useRef(null); const [isImageCaptured, setIsImageCaptured] = useState(false); const [permission, requestPermission] = useCameraPermissions(); const [image, setImage] = useState(""); const [ocrFailed, setOcrFailed] = useState(false); function takeAPicture() { if (!cameraRef.current || isImageCaptured || isProcessingPassport) return; cameraRef.current .takePictureAsync({ shutterSound: false }) .then((data) => { setIsImageCaptured(true); setOcrFailed(false); handlePicture(data); }); } function prepareText(ocrResult: MlkitOcrResult) { function checkIdCard(lines: string[]) { while (lines.length > 0) { if (!lines[0].startsWith("I<")) { lines.shift(); continue; } break; } if (lines.length >= 3) { return lines[0] + "\n" + lines[1] + "\n" + lines[2]; } return null; } function checkPassport(lines: string[]) { while (lines.length > 0) { if (!lines[0].startsWith("P<")) { lines.shift(); continue; } break; } if (lines.length >= 2) { return lines[0] + "\n" + lines[1]; } return null; } const fullText = ocrResult .map((t) => t.text) .join("\n") .toUpperCase() .replaceAll(" ", "") .replaceAll("«", "<"); const lines = fullText.split(/\r?\n/); const passport = checkPassport([...lines]); if (passport) return passport; const id = checkIdCard(lines); if (id) return id; return null; } function handleNoResult() { setIsImageCaptured(false); setImage(""); setOcrFailed(true); } async function handlePicture(data: CameraCapturedPicture) { try { const croppedImageUri = await cropImage(data); const ocrResult = await MlkitOcr.detectFromUri(croppedImageUri); const recognizedText = prepareText(ocrResult); console.log(recognizedText); if (!recognizedText) { handleNoResult(); console.log("no recognized text"); return; } const result = parse(recognizedText, { autocorrect: true }); handlePassportScanned(result); setImage(croppedImageUri); } catch (error) { console.error(error); handleNoResult(); } } if (!permission) { return ; } if (!permission?.granted) { return ; } if (isImageCaptured) { return ( ); } return ( {/* Camera overlay with guidelines */} {alignMrzText} {ocrFailed && ( )} {/* Camera controls - Web-like design */} {/* Left: Captured image preview */} {/* Center: Capture button */} ); }