import { useState, useCallback } from "react"; import { Platform, Alert } from "react-native"; import type { WallpaperConfig } from "@/types/wallpaper"; type ExportStatus = "idle" | "preparing" | "exporting" | "success" | "error"; interface ExportResult { status: ExportStatus; progress: number; error: string | null; exportAsWallpaper: (config: WallpaperConfig) => Promise; } export function useWallpaperExport(): ExportResult { const [status, setStatus] = useState("idle"); const [progress, setProgress] = useState(0); const [error, setError] = useState(null); const exportAsWallpaper = useCallback(async (config: WallpaperConfig) => { try { setStatus("preparing"); setProgress(0); setError(null); if (Platform.OS === "android") { await exportAndroid(config, setProgress, setStatus); } else if (Platform.OS === "ios") { await exportIOS(config, setProgress, setStatus); } else { throw new Error("Platform non supportée. Utilisez Android ou iOS."); } setStatus("success"); setProgress(1); } catch (err) { const message = err instanceof Error ? err.message : "Échec de l'export"; setError(message); setStatus("error"); Alert.alert("Erreur d'export", message); } }, []); return { status, progress, error, exportAsWallpaper }; } async function exportAndroid( config: WallpaperConfig, onProgress: (p: number) => void, onStatus: (s: ExportStatus) => void ) { // Lazy-load native module (only available on Android device builds) let WallpaperAndroid: typeof import("../../modules/wallpaper-android/src/WallpaperAndroidModule").WallpaperAndroid; try { WallpaperAndroid = require("../../modules/wallpaper-android/src/WallpaperAndroidModule").WallpaperAndroid; } catch { Alert.alert( "Module non disponible", "Le module natif Android n'est pas disponible dans Expo Go. Créez un development build avec `npx expo run:android`.", ); return; } // Check support const supported = WallpaperAndroid.isLiveWallpaperSupported(); if (!supported) { throw new Error("Les live wallpapers ne sont pas supportés sur cet appareil."); } onProgress(0.2); onStatus("exporting"); // Save config to SharedPreferences (read by LiveWallpaperService) const configJson = JSON.stringify({ sourceUri: config.sourceUri, depthMapUri: config.depthMapUri ?? "", animation: config.animation, uniforms: config.uniforms, fps: config.fps, }); await WallpaperAndroid.saveConfig(configJson); onProgress(0.6); // Launch system wallpaper picker await WallpaperAndroid.setLiveWallpaper(); onProgress(1.0); } async function exportIOS( config: WallpaperConfig, onProgress: (p: number) => void, onStatus: (s: ExportStatus) => void ) { let LivePhoto: typeof import("../../modules/livephoto-ios/src/LivePhotoModule").LivePhoto; try { LivePhoto = require("../../modules/livephoto-ios/src/LivePhotoModule").LivePhoto; } catch { Alert.alert( "Module non disponible", "Le module natif iOS n'est pas disponible dans Expo Go. Créez un development build avec `npx expo run:ios`.", ); return; } // Check/request photo library permission let permission = await LivePhoto.checkPermission(); if (permission === "undetermined") { permission = await LivePhoto.requestPermission(); } if (permission !== "granted") { throw new Error( "Accès à la photothèque refusé. Activez-le dans Réglages > Lively > Photos." ); } onProgress(0.1); onStatus("exporting"); const configJson = JSON.stringify({ sourceUri: config.sourceUri, depthMapUri: config.depthMapUri ?? "", animation: config.animation, uniforms: config.uniforms, fps: config.fps, }); onProgress(0.3); // Generate Live Photo (HEIC + MOV) and save to photo library await LivePhoto.exportLivePhoto(configJson); onProgress(0.9); // Guide user to apply the wallpaper Alert.alert( "Live Photo sauvegardée", "Pour l'appliquer comme fond d'écran :\n\n" + "Réglages > Fond d'écran > Ajouter\n" + "> Photos > Sélectionnez votre Live Photo\n" + "> Activez « Live Photo »", [{ text: "OK" }] ); onProgress(1.0); }