diff --git a/lib/extensions/string_extensions.dart b/lib/extensions/string_extensions.dart index e1700bc5..6ba96b08 100644 --- a/lib/extensions/string_extensions.dart +++ b/lib/extensions/string_extensions.dart @@ -1,6 +1,7 @@ extension CapExtension on String { + String get toCamelCase => "${this[0].toUpperCase()}${this.substring(1)}"; String get inCaps => '${this[0].toUpperCase()}${this.substring(1)}'; String get allInCaps => this.toUpperCase(); - String get capitalizeFirstofEach => this.trim().length > 0 ? this.trim().toLowerCase().split(" ").map((str) => str.inCaps).join(" ") : ""; + String get capitalizeFirstofEach => this.trim().length > 0 ? this.trim().toLowerCase().split(" ").map((str) => str.isNotEmpty ? str.inCaps: str).join(" ") : ""; } diff --git a/lib/widgets/new_design/doctor_header.dart b/lib/widgets/new_design/doctor_header.dart index 806cbb4a..bcbd55f8 100644 --- a/lib/widgets/new_design/doctor_header.dart +++ b/lib/widgets/new_design/doctor_header.dart @@ -298,12 +298,12 @@ class DoctorHeader extends StatelessWidget { width: 100.0, margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0), child: Text(TranslationBase.of(context).excellent, style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))), - getRatingLine(doctorDetailsList[0].patientNumber, Colors.green[700]), + getRatingLine(doctorDetailsList[0].ratio, Colors.green[700]), ], ), Container( - margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), - child: Text(getRatingWidth(doctorDetailsList[0].patientNumber).round().toString() + "%", + margin: EdgeInsets.only(top: 10.0, left: 20.0, right: 20.0), + child: Text(getRatingWidth(doctorDetailsList[0].ratio).round().toString() + "%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)), ), ], @@ -319,12 +319,12 @@ class DoctorHeader extends StatelessWidget { width: 100.0, margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0), child: Text(TranslationBase.of(context).v_good, style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))), - getRatingLine(doctorDetailsList[1].patientNumber, Color(0xffB7B723)), + getRatingLine(doctorDetailsList[1].ratio, Color(0xffB7B723)), ], ), Container( - margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), - child: Text(getRatingWidth(doctorDetailsList[1].patientNumber).round().toString() + "%", + margin: EdgeInsets.only(top: 10.0, left: 20.0, right: 20.0), + child: Text(doctorDetailsList[1].ratio.round().toString() + "%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)), ), ], @@ -340,12 +340,12 @@ class DoctorHeader extends StatelessWidget { width: 100.0, margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0), child: Text(TranslationBase.of(context).good, style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))), - getRatingLine(doctorDetailsList[2].patientNumber, Color(0xffEBA727)), + getRatingLine(doctorDetailsList[2].ratio, Color(0xffEBA727)), ], ), Container( - margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), - child: Text(getRatingWidth(doctorDetailsList[2].patientNumber).round().toString() + "%", + margin: EdgeInsets.only(top: 10.0, left: 20.0, right: 20.0), + child: Text(doctorDetailsList[2].ratio.round().toString() + "%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)), ), ], @@ -361,12 +361,12 @@ class DoctorHeader extends StatelessWidget { width: 100.0, margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0), child: Text(TranslationBase.of(context).average, style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))), - getRatingLine(doctorDetailsList[3].patientNumber, Color(0xffEB7227)), + getRatingLine(doctorDetailsList[3].ratio, Color(0xffEB7227)), ], ), Container( - margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), - child: Text(getRatingWidth(doctorDetailsList[3].patientNumber).round().toString() + "%", + margin: EdgeInsets.only(top: 10.0, left: 20.0, right: 20.0), + child: Text(doctorDetailsList[3].ratio.round().toString() + "%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)), ), ], @@ -383,12 +383,12 @@ class DoctorHeader extends StatelessWidget { width: 100.0, margin: EdgeInsets.only(top: 10.0, left: 15.0, right: 15.0), child: Text(TranslationBase.of(context).below_average, style: TextStyle(fontSize: 13.0, color: Colors.black, fontWeight: FontWeight.w600))), - getRatingLine(doctorDetailsList[4].patientNumber, Color(0xffE20C0C)), + getRatingLine(doctorDetailsList[4].ratio, Color(0xffE20C0C)), ], ), Container( - margin: EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), - child: Text(getRatingWidth(doctorDetailsList[4].patientNumber).round().toString() + "%", + margin: EdgeInsets.only(top: 10.0, left: 20.0, right: 20.0), + child: Text(doctorDetailsList[4].ratio.round().toString() + "%", style: TextStyle(fontSize: 14.0, color: Colors.black, fontWeight: FontWeight.w600)), ), ], @@ -410,12 +410,12 @@ class DoctorHeader extends StatelessWidget { pageBuilder: (context, animation1, animation2) {}); } - double getRatingWidth(int patientNumber) { - var width = (patientNumber / this.headerModel.totalReviews) * 100; + double getRatingWidth(double patientNumber) { + var width = patientNumber; return width.roundToDouble(); } - Widget getRatingLine(int patientNumber, Color color) { + Widget getRatingLine(double patientNumber, Color color) { return Container( margin: EdgeInsets.only(top: 10.0), child: Stack(children: [ @@ -427,7 +427,7 @@ class DoctorHeader extends StatelessWidget { ), ), SizedBox( - width: getRatingWidth(patientNumber) * 1.35, + width: patientNumber * 1.35, height: 4.0, child: Container( color: color, diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index 5a571df8..8e5c16b5 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -66,8 +66,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_tts/flutter_tts.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; -// import 'package:speech_to_text/speech_recognition_error.dart'; -// import 'package:speech_to_text/speech_to_text.dart' as stt; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_to_text.dart' as stt; +import 'package:speech_to_text/speech_to_text.dart'; import 'package:url_launcher/url_launcher.dart'; class FloatingSearchButton extends StatefulWidget { @@ -83,7 +84,8 @@ class _FloatingSearchButton extends State with TickerProvi RobotProvider eventProvider = RobotProvider(); bool isLoading = false; bool isError = false; - // stt.SpeechToText speech = stt.SpeechToText(); + stt.SpeechToText speech = stt.SpeechToText(); + FlutterTts tts = FlutterTts(); String error = ''; String _currentLocaleId = ""; String lastError; @@ -92,7 +94,6 @@ class _FloatingSearchButton extends State with TickerProvi double minSoundLevel = 50000; double maxSoundLevel = -50000; String reconizedWord = ''; - FlutterTts flutterTts = FlutterTts(); var selectedLang; bool isSearching = false; Map results = {}; @@ -113,7 +114,7 @@ class _FloatingSearchButton extends State with TickerProvi void initState() { controller = AnimationController(vsync: this, duration: Duration(seconds: 1)); offset = Tween(begin: Offset(0.0, 1.0), end: Offset(0.0, 0.0)).animate(controller); - + startIosTts(); if (IS_VOICE_COMMAND_CLOSED == true) { controller.reverse(from: -1); } else { @@ -192,20 +193,20 @@ class _FloatingSearchButton extends State with TickerProvi : Image.asset('assets/images/gif/robot-idle.gif'), ), onTap: () async { - // if (Platform.isAndroid) { - // if (await PermissionService.isMicrophonePermissionEnabled()) { - // new RoboSearch(context: context).showAlertDialog(context); - // initSpeechState().then((value) => {startVoiceSearch()}); - // } else { - // Utils.showPermissionConsentDialog(context, TranslationBase.of(context).recordAudioPermission, () { - // new RoboSearch(context: context).showAlertDialog(context); - // initSpeechState().then((value) => {startVoiceSearch()}); - // }); - // } - // } else { - // new RoboSearch(context: context).showAlertDialog(context); - // initSpeechState().then((value) => {startVoiceSearch()}); - // } + if (Platform.isAndroid) { + if (await PermissionService.isMicrophonePermissionEnabled()) { + new RoboSearch(context: context).showAlertDialog(context); + initSpeechState().then((value) => {startVoiceSearch()}); + } else { + Utils.showPermissionConsentDialog(context, TranslationBase.of(context).recordAudioPermission, () { + new RoboSearch(context: context).showAlertDialog(context); + initSpeechState().then((value) => {startVoiceSearch()}); + }); + } + } else { + new RoboSearch(context: context).showAlertDialog(context); + initSpeechState().then((value) => {startVoiceSearch()}); + } }, ), Positioned( @@ -234,44 +235,60 @@ class _FloatingSearchButton extends State with TickerProvi ])); } - // startVoiceSearch() async { - // bool available = await speech.initialize(onStatus: statusListener, onError: errorListener); - // _currentLocaleId = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); - // - // if (available) { - // speech.listen( - // onResult: resultListener, - // //listenMode: ListenMode.confirmation, - // localeId: _currentLocaleId == 'en' ? 'en_US' : 'ar_SA', - // ); - // } else { - // print("The user has denied the use of speech recognition."); - // } - // // some time later... - // //speech.stop(); - // // speech.listen( - // // onResult: resultListener, - // // listenFor: Duration(seconds: 10), - // // localeId: _currentLocaleId == 'en' ? 'en-US' : 'ar-SA', - // // onSoundLevelChange: soundLevelListener, - // // cancelOnError: true, - // // partialResults: true, - // // onDevice: true, - // // listenMode: ListenMode.deviceDefault); - // } + + startIosTts() async{ + await tts.setSharedInstance(true); + await tts.setLanguage("en-US"); + tts.setIosAudioCategory( + IosTextToSpeechAudioCategory.playback, + [IosTextToSpeechAudioCategoryOptions.mixWithOthers], + IosTextToSpeechAudioMode.voicePrompt); + } + startVoiceSearch() async { + bool available = await speech.initialize(); + _currentLocaleId = await sharedPref.getStringWithDefaultValue(APP_LANGUAGE, 'ar'); + // + // if (available) { + // speech.listen( + // onResult: resultListener, + // //listenMode: ListenMode.confirmation, + // localeId: _currentLocaleId == 'en' ? 'en_US' : 'ar_SA', + // ); + // } else { + // print("The user has denied the use of speech recognition."); + // } + // some time later... + if(available) { + speech.stop(); + speech.listen( + onResult: resultListener, + listenFor: Duration(seconds: 10), + localeId: _currentLocaleId == 'en' ? 'en-US' : 'ar-SA', + onSoundLevelChange: soundLevelListener, + cancelOnError: true, + partialResults: true, + onDevice: true, + listenMode: ListenMode.deviceDefault); + } + } void resultListener(result) { + _stopListening(); reconizedWord = result.recognizedWords; event.setValue({"searchText": reconizedWord}); if (result.finalResult == true) { Future.delayed(const Duration(seconds: 1), () { + _speak(reconizedWord); - RoboSearch.closeAlertDialog(context); + RoboSearch.closeAlertDialog(context); //Navigator.of(context).pop(); }); } } - + void _stopListening() async { + await speech.stop(); + // setState(() {}); + } Future _speak(reconizedWord) async { getPages(reconizedWord); } @@ -315,10 +332,10 @@ class _FloatingSearchButton extends State with TickerProvi // }); } - // void errorListener(SpeechRecognitionError error) { - // event.setValue({"searchText": 'null'}); - // RoboSearch.closeAlertDialog(context); - // } + void errorListener(SpeechRecognitionError error) { + event.setValue({"searchText": 'null'}); + RoboSearch.closeAlertDialog(context); + } void statusListener(String status) { //setState(() { @@ -807,7 +824,7 @@ class _FloatingSearchButton extends State with TickerProvi ); } - speak({isInit}) async { + speak({isInit =false}) async { //if (mounted) { setState(() { this.networkImage = results['AnimationURL']; @@ -817,12 +834,18 @@ class _FloatingSearchButton extends State with TickerProvi if (isInit == true) { event.setValue({"animationEnable": 'true'}); } + + // var voice = await tts.getVoice(); + // print(voice); if (isArabic == false && results['ReturnMessage'] != null && isInit == false) { - await flutterTts.setVoice({"name": "en-au-x-aub-network", "locale": "en-AU"}); - await flutterTts.speak(results['ReturnMessage']); + // await tts.synthesizeToFile("Hello World", Platform.isAndroid ? "tts.wav" : "tts.caf"); + + await tts.setVoice({"name": "Karen", "locale": "en-AU"}); + // await tts.setVoice({"name" : voice[35]["name"],"locale": voice[35]["locale"]}); + await tts.speak(results['ReturnMessage']); } else if (results['ReturnMessage_Ar'] != null && isInit == false) { - await flutterTts.setVoice({"name": "ar-xa-x-ard-network", "locale": "ar"}); - await flutterTts.speak(results['ReturnMessage_Ar']); + //await tts.setVoice({"name" : voice[0]["name"],"locale": voice[0]["locale"]}); + await tts.speak(results['ReturnMessage_Ar']); } stopAnimation(isInit: isInit); @@ -850,7 +873,7 @@ class _FloatingSearchButton extends State with TickerProvi } initialSpeak() async { - await flutterTts.awaitSpeakCompletion(true); + // await flutterTts.awaitSpeakCompletion(true); results = { 'ReturnMessage_Ar': "هذه الخدمة تم تصميمها لتتمكن من ربط الملفات الطبية للعائلة بملفك الطبي حتى تتمكن من إدارة سجلاتهم عن طريق تسجيل الدخول إلى ملفك الطبي.", 'ReturnMessage': "Through this service, you will be able to link your family medical files to your medical file so that you can manage their records by login to your medical file." @@ -875,21 +898,21 @@ class _FloatingSearchButton extends State with TickerProvi }); }); } else { - flutterTts.setCompletionHandler(() async { - event.setValue({"animationEnable": 'false'}); - setState(() { - this.networkImage = null; - this.isAnimationEnable = false; - }); - }); + // tts.setCompletionHandler(() async { + // event.setValue({"animationEnable": 'false'}); + // setState(() { + // this.networkImage = null; + // this.isAnimationEnable = false; + // }); + // }); } - flutterTts.setCompletionHandler(() async { - event.setValue({"animationEnable": 'false'}); - setState(() { - this.networkImage = null; - this.isAnimationEnable = false; - }); - }); + // flutterTts.setCompletionHandler(() async { + // event.setValue({"animationEnable": 'false'}); + // setState(() { + // this.networkImage = null; + // this.isAnimationEnable = false; + // }); + // }); } signOut() async { diff --git a/speech_to_text/lib/speech_recognition_error.dart b/speech_to_text/lib/speech_recognition_error.dart index 2ab6cd4d..1b47b0c9 100644 --- a/speech_to_text/lib/speech_recognition_error.dart +++ b/speech_to_text/lib/speech_recognition_error.dart @@ -1,5 +1,6 @@ import 'package:json_annotation/json_annotation.dart'; + part 'speech_recognition_error.g.dart'; /// A single error returned from the underlying speech services.