/** * Hook for camera permissions. * Supports both expo-camera (Expo Go) and react-native-vision-camera (production). */ import { useState, useEffect, useRef } from "react"; import { Platform, Linking, Alert } from "react-native"; import Constants from "expo-constants"; // Detect if running in Expo Go const isExpoGo = Constants.appOwnership === "expo"; export interface CameraPermissionState { hasPermission: boolean; isLoading: boolean; error: string | null; } /** * Hook for camera permissions that works in both Expo Go and production builds. */ export function useCameraPermission(): CameraPermissionState & { requestPermission: () => Promise } { const [hasPermission, setHasPermission] = useState(false); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { checkPermission(); }, []); const checkPermission = async () => { try { if (isExpoGo) { // Use expo-camera const { Camera } = await import("expo-camera"); const { status } = await Camera.getCameraPermissionsAsync(); setHasPermission(status === "granted"); } else { // Use react-native-vision-camera const { Camera } = await import("react-native-vision-camera"); const status = await Camera.getCameraPermissionStatus(); setHasPermission(status === "granted"); } } catch (err) { setError(err instanceof Error ? err.message : "Failed to check camera permission"); } finally { setIsLoading(false); } }; const requestPermission = async () => { try { setIsLoading(true); setError(null); if (isExpoGo) { // Use expo-camera const { Camera } = await import("expo-camera"); const { status, canAskAgain } = await Camera.requestCameraPermissionsAsync(); if (status === "granted") { setHasPermission(true); } else { if (!canAskAgain) { showSettingsAlert(); } setError("Camera permission denied"); } } else { // Use react-native-vision-camera const { Camera } = await import("react-native-vision-camera"); const status = await Camera.requestCameraPermission(); if (status === "granted") { setHasPermission(true); } else if (status === "denied") { showSettingsAlert(); setError("Camera permission denied"); } } } catch (err) { setError(err instanceof Error ? err.message : "Failed to request camera permission"); } finally { setIsLoading(false); } }; return { hasPermission, isLoading, error, requestPermission }; } function showSettingsAlert() { Alert.alert( "Camera Permission Required", "Scry needs camera access to scan cards. Please enable it in Settings.", [ { text: "Cancel", style: "cancel" }, { text: "Open Settings", onPress: () => { if (Platform.OS === "ios") { Linking.openURL("app-settings:"); } else { Linking.openSettings(); } }, }, ] ); } /** * Returns true if using expo-camera (Expo Go), false for Vision Camera (production). */ export function useIsExpoGo(): boolean { return isExpoGo; }