|
|
|
|
@ -24,6 +24,8 @@ class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
bool _isListening = false;
|
|
|
|
|
String _currentLocaleId = '';
|
|
|
|
|
TextEditingController? _currentController;
|
|
|
|
|
String _baseText = ''; // Text that was there when we started listening
|
|
|
|
|
String _currentSessionText = ''; // Text captured in current listening session
|
|
|
|
|
|
|
|
|
|
// Getters for speech state
|
|
|
|
|
bool get speechEnabled => _speechEnabled;
|
|
|
|
|
@ -54,8 +56,14 @@ class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
print('Speech status: $status, isListening: $_isListening');
|
|
|
|
|
// If user wants to keep listening but speech stopped, restart it
|
|
|
|
|
if ((status == 'done' || status == 'notListening') && _isListening && _currentController != null) {
|
|
|
|
|
// Save the finalized text before restarting
|
|
|
|
|
if (_currentSessionText.isNotEmpty) {
|
|
|
|
|
_baseText = _currentController!.text.trim();
|
|
|
|
|
_currentSessionText = '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Automatically restart listening after a brief pause
|
|
|
|
|
Future.delayed(const Duration(milliseconds: 200), () {
|
|
|
|
|
Future.delayed(const Duration(milliseconds: 300), () {
|
|
|
|
|
if (_isListening && _currentController != null) {
|
|
|
|
|
_startListeningInternal(_currentLocaleId, _currentController!);
|
|
|
|
|
}
|
|
|
|
|
@ -72,8 +80,15 @@ class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
|
|
|
|
|
await _speechToText.listen(
|
|
|
|
|
onResult: (SpeechRecognitionResult result) {
|
|
|
|
|
description = result.recognizedWords;
|
|
|
|
|
controller.text = result.recognizedWords;
|
|
|
|
|
_currentSessionText = result.recognizedWords;
|
|
|
|
|
|
|
|
|
|
// Combine base text with current session text
|
|
|
|
|
String combinedText = _baseText.isEmpty
|
|
|
|
|
? _currentSessionText
|
|
|
|
|
: _baseText + (_baseText.endsWith(' ') ? '' : ' ') + _currentSessionText;
|
|
|
|
|
|
|
|
|
|
description = combinedText;
|
|
|
|
|
controller.text = combinedText;
|
|
|
|
|
controller.selection = TextSelection.fromPosition(TextPosition(offset: controller.text.length));
|
|
|
|
|
notifyListeners();
|
|
|
|
|
},
|
|
|
|
|
@ -93,6 +108,8 @@ class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
_isListening = true;
|
|
|
|
|
_currentLocaleId = localeId;
|
|
|
|
|
_currentController = controller;
|
|
|
|
|
_baseText = controller.text.trim(); // Save existing text
|
|
|
|
|
_currentSessionText = '';
|
|
|
|
|
notifyListeners();
|
|
|
|
|
await _startListeningInternal(localeId, controller);
|
|
|
|
|
}
|
|
|
|
|
@ -102,6 +119,8 @@ class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
|
|
|
|
|
_isListening = false;
|
|
|
|
|
_currentLocaleId = '';
|
|
|
|
|
_currentController = null;
|
|
|
|
|
_baseText = '';
|
|
|
|
|
_currentSessionText = '';
|
|
|
|
|
await _speechToText.stop();
|
|
|
|
|
notifyListeners();
|
|
|
|
|
}
|
|
|
|
|
|