diff --git a/lib/api/etqan_ovr_api_client.dart b/lib/api/etqan_ovr_api_client.dart index bc68160..f7512cc 100644 --- a/lib/api/etqan_ovr_api_client.dart +++ b/lib/api/etqan_ovr_api_client.dart @@ -68,11 +68,11 @@ class EtqanApiClient { if (b.createdDate == null) return -1; try { - // Parse dates in format "15-Feb-2026 05:24 PM" - DateFormat dateFormat = DateFormat("dd-MMM-yyyy hh:mm a"); + // Parse dates in format "26-Feb-2026 12:54 PM" or "01-Mar-2026 02:45 PM" + DateFormat dateFormat = DateFormat("dd-MMM-yyyy hh:mm a", "en_US"); DateTime dateA = dateFormat.parse(a.createdDate!); DateTime dateB = dateFormat.parse(b.createdDate!); - return dateA.compareTo(dateB); + return dateB.compareTo(dateA); // Descending order (newest first) } catch (e) { return (b.createdDate ?? '').compareTo(a.createdDate ?? ''); } diff --git a/lib/provider/etqan_ovr_provider.dart b/lib/provider/etqan_ovr_provider.dart index a8128fe..4f2fe0f 100644 --- a/lib/provider/etqan_ovr_provider.dart +++ b/lib/provider/etqan_ovr_provider.dart @@ -1,6 +1,5 @@ import 'dart:io'; -import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:mohem_flutter_app/api/etqan_ovr_api_client.dart'; @@ -23,6 +22,8 @@ class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin { final SpeechToText _speechToText = SpeechToText(); bool _speechEnabled = false; bool _isListening = false; + String _currentLocaleId = ''; + TextEditingController? _currentController; // Getters for speech state bool get speechEnabled => _speechEnabled; @@ -50,18 +51,25 @@ class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Future initSpeech() async { _speechEnabled = await _speechToText.initialize( onStatus: (String status) { - // Update listening state when speech recognition status changes - if (status == 'done' || status == 'notListening') { - _isListening = false; - notifyListeners(); + 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) { + // Automatically restart listening after a brief pause + Future.delayed(const Duration(milliseconds: 200), () { + if (_isListening && _currentController != null) { + _startListeningInternal(_currentLocaleId, _currentController!); + } + }); } }, ); notifyListeners(); } - /// Start listening for speech input - Future startListening(String localeId, TextEditingController controller) async { + /// Internal method to start listening + Future _startListeningInternal(String localeId, TextEditingController controller) async { + if (!_speechEnabled) return; + await _speechToText.listen( onResult: (SpeechRecognitionResult result) { description = result.recognizedWords; @@ -70,19 +78,31 @@ class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin { notifyListeners(); }, localeId: localeId, - listenFor: const Duration(seconds: 30), - pauseFor: const Duration(seconds: 3), - partialResults: true, - listenMode: ListenMode.confirmation, + listenFor: const Duration(seconds: 60), + pauseFor: const Duration(seconds: 10), + listenOptions: SpeechListenOptions( + partialResults: true, + listenMode: ListenMode.confirmation, + cancelOnError: false, + ), ); + } + + /// Start listening for speech input + Future startListening(String localeId, TextEditingController controller) async { _isListening = true; + _currentLocaleId = localeId; + _currentController = controller; notifyListeners(); + await _startListeningInternal(localeId, controller); } /// Stop listening for speech input Future stopListening() async { - await _speechToText.stop(); _isListening = false; + _currentLocaleId = ''; + _currentController = null; + await _speechToText.stop(); notifyListeners(); } @@ -193,21 +213,7 @@ class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin { Utils.hideLoading(context); if (response != null) { getEtqanEmployeeRequestsList = await EtqanApiClient().getEmployeeEtqanRequests(); - if (getEtqanEmployeeRequestsList != null) { - getEtqanEmployeeRequestsList!.sort((EtqanGetEmployeeOvrRequestsResponse a, EtqanGetEmployeeOvrRequestsResponse b) { - if (a.createdDate == null && b.createdDate == null) return 0; - if (a.createdDate == null) return 1; - if (b.createdDate == null) return -1; - try { - DateFormat dateFormat = DateFormat("dd-MMM-yyyy hh:mm a"); - DateTime dateA = dateFormat.parse(a.createdDate!); - DateTime dateB = dateFormat.parse(b.createdDate!); - return dateA.compareTo(dateB); - } catch (e) { - return (b.createdDate ?? '').compareTo(a.createdDate ?? ''); - } - }); - } + notifyListeners(); return response; } return null; @@ -217,4 +223,12 @@ class EtqanOvrProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return null; } } + + @override + void dispose() { + if (_isListening) { + _speechToText.stop(); + } + super.dispose(); + } } diff --git a/lib/ui/etqan_ovr/etqan_create_request.dart b/lib/ui/etqan_ovr/etqan_create_request.dart index 8ade990..a1d64af 100644 --- a/lib/ui/etqan_ovr/etqan_create_request.dart +++ b/lib/ui/etqan_ovr/etqan_create_request.dart @@ -39,6 +39,8 @@ class _EtqanOvrCreateRequestState extends State { @override void dispose() { + // Stop listening if active + context.read().stopListening(); _descriptionController.dispose(); super.dispose(); } diff --git a/lib/ui/etqan_ovr/etqan_ovr_home.dart b/lib/ui/etqan_ovr/etqan_ovr_home.dart index e2493e6..80a27c6 100644 --- a/lib/ui/etqan_ovr/etqan_ovr_home.dart +++ b/lib/ui/etqan_ovr/etqan_ovr_home.dart @@ -1,4 +1,3 @@ -import 'dart:convert'; import 'package:easy_localization/easy_localization.dart' as lclize; import 'package:flutter/material.dart'; @@ -69,7 +68,7 @@ class _EtqanOvrHomeState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ (data.ticketNumber ?? "").toText14(isBold: true, color: MyColors.darkTextColor), - Directionality(textDirection: TextDirection.ltr, child: (data.createdDate! ?? "").toText12(color: MyColors.grey70Color)), + Directionality(textDirection: TextDirection.ltr, child: (data.createdDate!.split(" ").first ?? "").toText12(color: MyColors.grey70Color)), ], ), 8.height,