/** * Quick Snap capture helper — platform-aware, camera-first. * * NATIVE (Capacitor APK): uses the runtime-injected Camera plugin * (window.Capacitor.Plugins.Camera) with source:'CAMERA', which forces the * real OS camera and ships its own preview + retake UI. We read the plugin * off the runtime object rather than importing '@capacitor/camera', so no * bare specifier ends up in the bundle (that was the white-screen cause). * * WEB: there is no reliable way to force the camera from JS, so the caller * falls back to a file input with capture="environment" (a hint the browser * may honor). This module only handles the native path; isNativeCapture() * tells the caller which route to take. */ interface CapacitorCameraPlugin { getPhoto(options: { resultType: string; source: string; quality: number; correctOrientation: boolean; }): Promise<{ dataUrl?: string }>; } function getNativeCamera(): CapacitorCameraPlugin | null { const cap = (window as unknown as { Capacitor?: { isNativePlatform?: () => boolean; Plugins?: { Camera?: CapacitorCameraPlugin }; }; }).Capacitor; if (!cap?.isNativePlatform?.()) return null; return cap.Plugins?.Camera ?? null; } /** True when the native Camera plugin is available (i.e. inside the app). */ export function isNativeCapture(): boolean { return getNativeCamera() !== null; } /** * Open the native camera and return the captured photo as a File. * Returns null if the user cancels. Throws if the plugin is unavailable or * errors (caller should fall back to the web file input). */ export async function captureFromNativeCamera(): Promise { const Camera = getNativeCamera(); if (!Camera) throw new Error('Native camera unavailable'); let photo: { dataUrl?: string }; try { photo = await Camera.getPhoto({ resultType: 'dataUrl', // CameraResultType.DataUrl source: 'CAMERA', // CameraSource.Camera — forces the camera, not the gallery quality: 90, correctOrientation: true, }); } catch (err) { // Capacitor throws with a "cancel" message when the user backs out — treat // that as a benign null rather than an error. const msg = err instanceof Error ? err.message.toLowerCase() : String(err).toLowerCase(); if (msg.includes('cancel')) return null; throw err; } if (!photo.dataUrl) return null; const res = await fetch(photo.dataUrl); const blob = await res.blob(); return new File([blob], `skate-spot-${Date.now()}.jpg`, { type: 'image/jpeg' }); }