| .. | .. |
|---|
| 11 | 11 | durationMs: number; |
|---|
| 12 | 12 | } |
|---|
| 13 | 13 | |
|---|
| 14 | +// --- Audio mode (set once at import time) --- |
|---|
| 15 | +// Setting this on every playback causes iOS to renegotiate the audio route, |
|---|
| 16 | +// which disconnects Bluetooth/CarPlay. Set it once and leave it alone. |
|---|
| 17 | +let _audioModeReady = false; |
|---|
| 18 | +async function ensureAudioMode(): Promise<void> { |
|---|
| 19 | + if (_audioModeReady) return; |
|---|
| 20 | + _audioModeReady = true; |
|---|
| 21 | + try { |
|---|
| 22 | + await setAudioModeAsync({ playsInSilentMode: true }); |
|---|
| 23 | + } catch { |
|---|
| 24 | + _audioModeReady = false; // retry next time |
|---|
| 25 | + } |
|---|
| 26 | +} |
|---|
| 27 | +// Eagerly initialize on module load |
|---|
| 28 | +ensureAudioMode(); |
|---|
| 29 | + |
|---|
| 14 | 30 | // --- Autoplay suppression --- |
|---|
| 15 | 31 | // Don't autoplay voice messages when the app is in the background |
|---|
| 16 | 32 | // or when the user is on a phone call (detected via audio interruption). |
|---|
| .. | .. |
|---|
| 153 | 169 | let player: ReturnType<typeof createAudioPlayer> | null = null; |
|---|
| 154 | 170 | |
|---|
| 155 | 171 | try { |
|---|
| 156 | | - await setAudioModeAsync({ playsInSilentMode: true }); |
|---|
| 172 | + await ensureAudioMode(); |
|---|
| 157 | 173 | |
|---|
| 158 | 174 | player = createAudioPlayer(uri); |
|---|
| 159 | 175 | currentPlayer = player; |
|---|