feat: Mise à jour à la version 1.1.14 et refonte du support Audio/TTS pour le Web

- Mise à jour de la version de l'application à `1.1.14` dans `app_version.dart` et `version.json`.
- Migration de `AudioFeedbackService` vers l'API Web native (`dart:js_interop`, `package:web`) pour corriger les problèmes d'autoplay et supprimer la dépendance `audioplayers`.
- Réécriture de `TextToSpeechService` utilisant `window.speechSynthesis` en remplacement de `flutter_tts` pour une meilleure compatibilité Web (notamment sous Linux).
- Suppression des dépendances obsolètes `audioplayers` et `flutter_tts` du `pubspec.yaml`.
- Ajout d'une gestion de file d'attente (`_scanQueue`) dans `EventPreparationPage` pour traiter les scans de codes-barres de manière séquentielle.
- Intégration d'un bouton de diagnostic (`AudioDiagnosticButton`) pour tester manuellement l'audio et la synthèse vocale.
- Ajout d'un script de test JavaScript `test_audio_tts.js` pour faciliter le débogage dans la console du navigateur.
- Ajout de directives de style et d'architecture Dart/Flutter dans `.github/agents/`.
This commit is contained in:
ElPoyo
2026-03-08 19:51:13 +01:00
parent 6d320bedc9
commit bc93f3fa9a
10 changed files with 1027 additions and 108 deletions

View File

@@ -0,0 +1,147 @@
import 'package:flutter/material.dart';
import 'package:web/web.dart' as web;
import 'package:em2rp/services/audio_feedback_service.dart';
import 'package:em2rp/services/text_to_speech_service.dart';
import 'package:em2rp/utils/debug_log.dart';
/// Bouton de diagnostic pour tester l'audio et le TTS
class AudioDiagnosticButton extends StatelessWidget {
const AudioDiagnosticButton({super.key});
Future<void> _testAudio(BuildContext context) async {
try {
DebugLog.info('[AudioDiagnostic] ========== AUDIO TEST START ==========');
DebugLog.info('[AudioDiagnostic] User Agent: ${web.window.navigator.userAgent}');
DebugLog.info('[AudioDiagnostic] Platform: ${web.window.navigator.platform}');
// Débloquer l'audio
DebugLog.info('[AudioDiagnostic] Step 1: Unlocking audio...');
await AudioFeedbackService.unlockAudio();
await Future.delayed(const Duration(milliseconds: 500));
// Tester le son de succès
DebugLog.info('[AudioDiagnostic] Step 2: Playing success beep...');
await AudioFeedbackService.playSuccessBeep();
await Future.delayed(const Duration(milliseconds: 1000));
// Tester le son d'erreur
DebugLog.info('[AudioDiagnostic] Step 3: Playing error beep...');
await AudioFeedbackService.playErrorBeep();
DebugLog.info('[AudioDiagnostic] ========== AUDIO TEST END ==========');
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Test audio terminé - Vérifiez la console (F12)'),
backgroundColor: Colors.green,
duration: Duration(seconds: 3),
),
);
}
} catch (e) {
DebugLog.error('[AudioDiagnostic] Error during audio test', e);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Erreur audio: $e'),
backgroundColor: Colors.red,
),
);
}
}
}
Future<void> _testTTS(BuildContext context) async {
try {
DebugLog.info('[AudioDiagnostic] ========== TTS TEST START ==========');
DebugLog.info('[AudioDiagnostic] User Agent: ${web.window.navigator.userAgent}');
DebugLog.info('[AudioDiagnostic] Platform: ${web.window.navigator.platform}');
DebugLog.info('[AudioDiagnostic] Language: ${web.window.navigator.language}');
await TextToSpeechService.initialize();
await Future.delayed(const Duration(milliseconds: 500));
DebugLog.info('[AudioDiagnostic] Speaking test phrase...');
await TextToSpeechService.speak('Test de synthèse vocale. Un, deux, trois.');
DebugLog.info('[AudioDiagnostic] ========== TTS TEST END ==========');
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Test TTS terminé - Vérifiez la console (F12)'),
backgroundColor: Colors.green,
duration: Duration(seconds: 3),
),
);
}
} catch (e) {
DebugLog.error('[AudioDiagnostic] Error during TTS test', e);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Erreur TTS: $e'),
backgroundColor: Colors.red,
),
);
}
}
}
@override
Widget build(BuildContext context) {
return PopupMenuButton<String>(
icon: const Icon(Icons.bug_report, color: Colors.grey),
tooltip: 'Diagnostic Audio/TTS',
onSelected: (value) async {
switch (value) {
case 'audio':
await _testAudio(context);
break;
case 'tts':
await _testTTS(context);
break;
case 'both':
await _testAudio(context);
await Future.delayed(const Duration(milliseconds: 1000));
await _testTTS(context);
break;
}
},
itemBuilder: (context) => [
const PopupMenuItem(
value: 'audio',
child: Row(
children: [
Icon(Icons.volume_up, size: 20),
SizedBox(width: 8),
Text('Test Audio'),
],
),
),
const PopupMenuItem(
value: 'tts',
child: Row(
children: [
Icon(Icons.record_voice_over, size: 20),
SizedBox(width: 8),
Text('Test TTS'),
],
),
),
const PopupMenuItem(
value: 'both',
child: Row(
children: [
Icon(Icons.play_circle, size: 20),
SizedBox(width: 8),
Text('Test Audio + TTS'),
],
),
),
],
);
}
}