import { Platform } from "react-native"; import { createAudioPlayer, setAudioModeAsync, type AudioPlayer } from "expo-audio"; import * as Haptics from "expo-haptics"; // Preloaded one-shot players. Created on first prime() call, which must happen // in response to a user gesture (the PIN login tap) so web autoplay policies // allow later programmatic playback. let successPlayer: AudioPlayer | null = null; let errorPlayer: AudioPlayer | null = null; let primed = false; export async function primeFeedback(): Promise { if (primed) return; primed = true; try { await setAudioModeAsync({ playsInSilentMode: true }); } catch { /* not fatal */ } try { successPlayer = createAudioPlayer(require("../assets/sounds/success.wav")); errorPlayer = createAudioPlayer(require("../assets/sounds/error.wav")); // Nudge the web audio context alive with a muted play/pause. if (Platform.OS === "web") { for (const p of [successPlayer, errorPlayer]) { try { p.volume = 0; p.play(); p.pause(); p.seekTo(0); p.volume = 1; } catch { /* ignore */ } } } } catch { /* audio unavailable; feedback falls back to haptics/visual only */ } } function replay(player: AudioPlayer | null): void { if (!player) return; try { player.seekTo(0); player.play(); } catch { /* ignore */ } } export function feedbackSuccess(): void { replay(successPlayer); if (Platform.OS !== "web") { Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success).catch(() => {}); } } export function feedbackError(): void { replay(errorPlayer); if (Platform.OS !== "web") { Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error).catch(() => {}); } }