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:
147
em2rp/lib/views/widgets/common/audio_diagnostic_button.dart
Normal file
147
em2rp/lib/views/widgets/common/audio_diagnostic_button.dart
Normal 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'),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user