Skip to content

Commit b695fa4

Browse files
committed
feat: replace expo-av with expo-audio for audio handling and update related functions
1 parent b52dfe4 commit b695fa4

6 files changed

Lines changed: 55 additions & 56 deletions

File tree

app.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
},
4545
"plugins": [
4646
"expo-asset",
47-
"expo-av",
4847
[
4948
"expo-splash-screen",
5049
{

package-lock.json

Lines changed: 0 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
"eventsource": "^4.0.0",
3939
"expo": "~53.0.23",
4040
"expo-audio": "~0.4.9",
41-
"expo-av": "^15.1.7",
4241
"expo-blur": "~14.1.5",
4342
"expo-constants": "~17.1.7",
4443
"expo-crypto": "^14.1.5",

src/services/SyncManager.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
import { TaskCacheService, OfflineChange } from './TaskCacheService';
22
import StorageManager from './StorageManager';
33
import NetworkService, { NetworkState } from './NetworkService';
4-
import { getAllTasks as getTasksFromAPI, getCategories as getCategoriesFromAPI, addTask as addTaskToAPI, updateTask as updateTaskToAPI, deleteTask as deleteTaskFromAPI } from './taskService';
54
import { emitTasksSynced } from '../utils/eventEmitter';
65

6+
// Lazy import per evitare require cycle con taskService
7+
async function getTaskServiceFunctions() {
8+
const taskService = await import('./taskService');
9+
return {
10+
getTasksFromAPI: taskService.getAllTasks,
11+
getCategoriesFromAPI: taskService.getCategories,
12+
addTaskToAPI: taskService.addTask,
13+
updateTaskToAPI: taskService.updateTask,
14+
deleteTaskFromAPI: taskService.deleteTask,
15+
};
16+
}
17+
718
export interface SyncStatus {
819
isOnline: boolean;
920
isSyncing: boolean;
@@ -184,18 +195,21 @@ class SyncManager {
184195
switch (change.type) {
185196
case 'CREATE':
186197
if (change.entityType === 'TASK') {
198+
const { addTaskToAPI } = await getTaskServiceFunctions();
187199
await addTaskToAPI(change.data);
188200
}
189201
break;
190202

191203
case 'UPDATE':
192204
if (change.entityType === 'TASK') {
205+
const { updateTaskToAPI } = await getTaskServiceFunctions();
193206
await updateTaskToAPI(change.data.id || change.data.task_id, change.data);
194207
}
195208
break;
196209

197210
case 'DELETE':
198211
if (change.entityType === 'TASK') {
212+
const { deleteTaskFromAPI } = await getTaskServiceFunctions();
199213
await deleteTaskFromAPI(change.data.id || change.data.task_id);
200214
}
201215
break;
@@ -220,6 +234,7 @@ class SyncManager {
220234
console.log('[SYNC] 🔄 Aggiornamento dati dal server...');
221235

222236
// Carica tasks e categorie dal server
237+
const { getTasksFromAPI, getCategoriesFromAPI } = await getTaskServiceFunctions();
223238
const [tasks, categories] = await Promise.all([
224239
getTasksFromAPI(),
225240
getCategoriesFromAPI()
@@ -312,17 +327,23 @@ class SyncManager {
312327
await this.syncDataFromServer();
313328
break;
314329

315-
case 'CREATE_TASK':
330+
case 'CREATE_TASK': {
331+
const { addTaskToAPI } = await getTaskServiceFunctions();
316332
await addTaskToAPI(operation.data);
317333
break;
334+
}
318335

319-
case 'UPDATE_TASK':
336+
case 'UPDATE_TASK': {
337+
const { updateTaskToAPI } = await getTaskServiceFunctions();
320338
await updateTaskToAPI(operation.data.id, operation.data.task);
321339
break;
340+
}
322341

323-
case 'DELETE_TASK':
342+
case 'DELETE_TASK': {
343+
const { deleteTaskFromAPI } = await getTaskServiceFunctions();
324344
await deleteTaskFromAPI(operation.data.id);
325345
break;
346+
}
326347

327348
default:
328349
throw new Error(`Operazione non supportata: ${operation.type}`);

src/utils/audioDebug.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ export function debugAudioDependencies() {
66
console.log('=== DEBUG AUDIO DEPENDENCIES ===');
77

88
try {
9-
// Test import expo-av
10-
const Audio = require('expo-av').Audio;
11-
console.log('✅ expo-av importato correttamente');
12-
console.log('Audio object:', !!Audio);
13-
console.log('Audio.requestPermissionsAsync:', !!Audio?.requestPermissionsAsync);
14-
console.log('Audio.Recording:', !!Audio?.Recording);
15-
console.log('Audio.Sound:', !!Audio?.Sound);
9+
// Test import expo-audio
10+
const expoAudio = require('expo-audio');
11+
console.log('✅ expo-audio importato correttamente');
12+
console.log('createAudioPlayer:', !!expoAudio?.createAudioPlayer);
13+
console.log('setAudioModeAsync:', !!expoAudio?.setAudioModeAsync);
14+
console.log('requestRecordingPermissionsAsync:', !!expoAudio?.requestRecordingPermissionsAsync);
1615
} catch (error) {
17-
console.error('❌ Errore import expo-av:', error);
16+
console.error('❌ Errore import expo-audio:', error);
1817
}
1918

2019
try {
@@ -48,8 +47,8 @@ export async function debugAudioPermissions() {
4847
console.log('=== DEBUG AUDIO PERMISSIONS ===');
4948

5049
try {
51-
const { Audio } = require('expo-av');
52-
const result = await Audio.requestPermissionsAsync();
50+
const { requestRecordingPermissionsAsync } = require('expo-audio');
51+
const result = await requestRecordingPermissionsAsync();
5352
console.log('Risultato richiesta permessi:', result);
5453
console.log('Permessi concessi:', result.granted);
5554
console.log('Status:', result.status);

src/utils/audioUtils.ts

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { Audio } from 'expo-av';
1+
import { createAudioPlayer, setAudioModeAsync, requestRecordingPermissionsAsync } from 'expo-audio';
2+
import type { AudioPlayer as ExpoAudioPlayer } from 'expo-audio/build/AudioModule.types';
23
import * as FileSystem from 'expo-file-system';
34
import { VoiceProcessor } from '@picovoice/react-native-voice-processor';
45

@@ -274,10 +275,10 @@ export class AudioRecorder {
274275

275276
/**
276277
* Classe per gestire la riproduzione di chunk audio PCM16
277-
* Usa expo-av per il playback
278+
* Usa expo-audio per il playback
278279
*/
279280
export class AudioPlayer {
280-
private currentSound: Audio.Sound | null = null;
281+
private currentPlayer: ExpoAudioPlayer | null = null;
281282
private chunkBuffer: { index?: number; data: string }[] = [];
282283
private seenChunkIndexes: Set<number> = new Set();
283284
private highestIndexedChunk: number = -1;
@@ -353,7 +354,7 @@ export class AudioPlayer {
353354

354355
console.log(`AudioPlayer: ${totalChunks} chunk -> ${pcm16Data.length} bytes PCM16`);
355356

356-
// Wrappa in WAV per la riproduzione con expo-av
357+
// Wrappa in WAV per la riproduzione con expo-audio
357358
const wavData = wrapPcm16InWav(pcm16Data, AUDIO_CONFIG.SAMPLE_RATE);
358359
const wavBase64 = encodeBase64(wavData);
359360

@@ -362,25 +363,23 @@ export class AudioPlayer {
362363
encoding: FileSystem.EncodingType.Base64,
363364
});
364365

365-
await Audio.setAudioModeAsync({
366-
allowsRecordingIOS: false,
366+
await setAudioModeAsync({
367367
playsInSilentModeIOS: true,
368-
staysActiveInBackground: true,
369-
shouldDuckAndroid: true,
370-
playThroughEarpieceAndroid: false,
368+
shouldPlayInBackground: true,
369+
shouldRouteThroughEarpiece: false,
371370
});
372371

373-
const { sound } = await Audio.Sound.createAsync({ uri: tempPath });
374-
this.currentSound = sound;
372+
const player = createAudioPlayer({ uri: tempPath });
373+
this.currentPlayer = player;
375374

376-
this.currentSound.setOnPlaybackStatusUpdate(async (status) => {
377-
if (status.isLoaded && status.didJustFinish) {
375+
player.addListener('playbackStatusUpdate', async (status) => {
376+
if (status.didJustFinish) {
378377
console.log('AudioPlayer: Riproduzione completata');
379378
await this.onPlaybackComplete(onComplete, tempPath);
380379
}
381380
});
382381

383-
await this.currentSound.playAsync();
382+
player.play();
384383
this.isPlaying = true;
385384
this.clearChunks();
386385

@@ -404,13 +403,13 @@ export class AudioPlayer {
404403
}
405404

406405
private async onPlaybackComplete(onComplete?: () => void, audioFilePath?: string): Promise<void> {
407-
if (this.currentSound) {
406+
if (this.currentPlayer) {
408407
try {
409-
await this.currentSound.unloadAsync();
408+
this.currentPlayer.remove();
410409
} catch (error) {
411410
console.error('Errore cleanup audio:', error);
412411
}
413-
this.currentSound = null;
412+
this.currentPlayer = null;
414413
}
415414

416415
if (audioFilePath) {
@@ -426,14 +425,14 @@ export class AudioPlayer {
426425
}
427426

428427
async stopPlayback(): Promise<void> {
429-
if (this.currentSound) {
428+
if (this.currentPlayer) {
430429
try {
431-
await this.currentSound.stopAsync();
432-
await this.currentSound.unloadAsync();
430+
this.currentPlayer.pause();
431+
this.currentPlayer.remove();
433432
} catch (error) {
434433
console.error('Errore stop riproduzione:', error);
435434
}
436-
this.currentSound = null;
435+
this.currentPlayer = null;
437436
}
438437
this.isPlaying = false;
439438
}
@@ -473,7 +472,7 @@ export function base64ToArrayBuffer(base64: string): ArrayBuffer {
473472
*/
474473
export async function checkAudioPermissions(): Promise<boolean> {
475474
try {
476-
const { status } = await Audio.requestPermissionsAsync();
475+
const { status } = await requestRecordingPermissionsAsync();
477476
return status === 'granted';
478477
} catch (error) {
479478
console.error('Errore controllo permessi audio:', error);

0 commit comments

Comments
 (0)