import React, { useEffect, useRef, useState } from "react"; import { View, Text, TouchableOpacity, ActivityIndicator, Platform, } from "react-native"; import { ArrowLeft } from "lucide-react-native"; import { router } from "expo-router"; import { CameraView, useCameraPermissions, type BarcodeScanningResult, } from "expo-camera"; import ScreenWrapper from "~/components/ui/ScreenWrapper"; import { Button } from "~/components/ui/button"; import ModalToast from "~/components/ui/toast"; import { ROUTES } from "~/lib/routes"; export default function ScanProfileQR() { const [hasPermission, setHasPermission] = useState(null); const [scanned, setScanned] = useState(false); const [toastVisible, setToastVisible] = useState(false); const [toastTitle, setToastTitle] = useState(""); const [toastDescription, setToastDescription] = useState( undefined ); const [toastVariant, setToastVariant] = useState< "success" | "error" | "warning" | "info" >("info"); const toastTimeoutRef = useRef | null>(null); const [permission, requestPermission] = useCameraPermissions(); const showToast = ( title: string, description?: string, variant: "success" | "error" | "warning" | "info" = "info" ) => { if (toastTimeoutRef.current) { clearTimeout(toastTimeoutRef.current); } setToastTitle(title); setToastDescription(description); setToastVariant(variant); setToastVisible(true); toastTimeoutRef.current = setTimeout(() => { setToastVisible(false); toastTimeoutRef.current = null; }, 2500); }; useEffect(() => { return () => { if (toastTimeoutRef.current) { clearTimeout(toastTimeoutRef.current); } }; }, []); useEffect(() => { if (Platform.OS === "web") { setHasPermission(false); return; } if (!permission) { return; } setHasPermission(permission.granted); }, [permission]); const handleClose = () => { router.back(); }; const handleBarCodeScanned = ({ data }: BarcodeScanningResult) => { if (scanned) return; try { setScanned(true); const parsed = JSON.parse(data); if (!parsed || parsed.type !== "AMBA_PROFILE") { showToast( "Invalid QR", "This is not a valid Amba profile QR.", "error" ); setScanned(false); return; } const accountId: string | undefined = parsed.accountId; const name: string | undefined = parsed.name; const phoneNumber: string | undefined = parsed.phoneNumber; if (!phoneNumber) { showToast( "Invalid QR", "This profile QR does not contain a phone number.", "error" ); setScanned(false); return; } router.push({ pathname: ROUTES.SEND_OR_REQUEST_MONEY, params: { selectedContactId: accountId || phoneNumber, selectedContactName: name || "User", selectedContactPhone: phoneNumber, }, }); } catch (error) { console.warn("[ScanProfileQR] Failed to parse QR payload", error); showToast("Scan failed", "Could not read this QR code.", "error"); setScanned(false); } }; return ( {/* Top back button */} {Platform.OS === "web" ? ( QR scanning is not supported on web. Please use a mobile device. ) : hasPermission === null ? ( Requesting camera permission... ) : hasPermission === false ? ( Camera permission needed Please grant camera access to scan profile QR codes. ) : ( Scan profile QR code Align the QR code inside the frame. We will automatically select the account and take you to the amount screen. )} ); }