From b3e6c4efdafb6bab24fd9e5f073a2ea759299da9 Mon Sep 17 00:00:00 2001 From: Sultan Khan Date: Sun, 21 Feb 2021 13:09:24 +0300 Subject: [PATCH] voice command changes --- android/app/build.gradle | 2 +- lib/config/config.dart | 4 +- lib/config/localized_values.dart | 3 +- lib/pages/landing/landing_page.dart | 17 +- lib/pages/medical/medical_profile_page.dart | 2 +- lib/pages/settings/general_setting.dart | 276 +++++++------- lib/splashPage.dart | 26 +- lib/uitl/translations_delegate_base.dart | 1 + lib/widgets/others/app_scaffold_widget.dart | 33 +- .../others/floating_button_search.dart | 338 ++++++++++-------- lib/widgets/typewriter/typewiter.dart | 39 +- pubspec.yaml | 2 +- 12 files changed, 409 insertions(+), 334 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 7a09b3ca..11e99a2a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -94,6 +94,6 @@ dependencies { implementation 'com.github.kittinunf.fuel:fuel:2.3.0' //for JVM implementation 'com.github.kittinunf.fuel:fuel-android:2.3.0' implementation 'com.google.android.gms:play-services-location:17.1.0'//for Android - + implementation 'com.google.android.gms:play-services-basement:17.5.0' } diff --git a/lib/config/config.dart b/lib/config/config.dart index b471df55..296bbbbe 100644 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -289,7 +289,7 @@ const GET_PATIENT_HEALTH_STATS = const CHANNEL = 3; const GENERAL_ID = 'Cs2020@2016\$2958'; const IP_ADDRESS = '10.20.10.20'; -const VERSION_ID = 5.8; +const VERSION_ID = 8.4; const SETUP_ID = '91877'; const LANGUAGE = 2; const PATIENT_OUT_SA = 0; @@ -298,6 +298,8 @@ const IS_DENTAL_ALLOWED_BACKEND = false; const PATIENT_TYPE = 1; const PATIENT_TYPE_ID = 1; var DEVICE_TOKEN = ""; +var IS_VOICE_COMMAND_CLOSED = false; +var IS_TEXT_COMPLETED = false; var DeviceTypeID = Platform.isIOS ? 1 : 2; const LANGUAGE_ID = 1; const GET_PHARMCY_ITEMS = "Services/Lists.svc/REST/GetPharmcyItems_Region"; diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart index 325f2b49..b8043dc3 100644 --- a/lib/config/localized_values.dart +++ b/lib/config/localized_values.dart @@ -1784,5 +1784,6 @@ const Map localizedValues = { "en": "Select the preferred unit", "ar": "اختر الوحدة المفضلة" }, - "select-unit": {"en": "Select unit", "ar": "اختر وحدة القياس"} + "select-unit": {"en": "Select unit", "ar": "اختر وحدة القياس"}, + "try-saying": {"en": "Try saying something", "ar": 'حاول قول شيء ما'} }; diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart index 83454307..deb20bd9 100644 --- a/lib/pages/landing/landing_page.dart +++ b/lib/pages/landing/landing_page.dart @@ -86,7 +86,12 @@ class _LandingPageState extends State with WidgetsBindingObserver { _changeCurrentTab(int tab) { setState(() { currentTab = tab; - if (tab != 0) pageController.jumpToPage(tab); + if (tab != 0) + pageController.jumpToPage(tab); + else { + IS_VOICE_COMMAND_CLOSED = false; + pageController.jumpToPage(tab); + } }); } @@ -627,7 +632,7 @@ class _LandingPageState extends State with WidgetsBindingObserver { authService .selectDeviceImei(token) .then((SelectDeviceIMEIRES value) => setUserValues(value)); - if (await sharedPref.getObject(USER_PROFILE) != null) { + if (projectViewModel.isLoading == true) { var data = AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE)); if (data != null) { @@ -636,9 +641,11 @@ class _LandingPageState extends State with WidgetsBindingObserver { .then((res) => {print(res)}); authService.getDashboard().then((value) => { setState(() { - notificationCount = value['List_PatientDashboard'][0] - ['UnreadPatientNotificationCount'] - .toString(); + if (value != null) { + notificationCount = value['List_PatientDashboard'][0] + ['UnreadPatientNotificationCount'] + .toString(); + } }) }); } diff --git a/lib/pages/medical/medical_profile_page.dart b/lib/pages/medical/medical_profile_page.dart index 291a4188..58014e24 100644 --- a/lib/pages/medical/medical_profile_page.dart +++ b/lib/pages/medical/medical_profile_page.dart @@ -71,7 +71,7 @@ class _MedicalProfilePageState extends State { builder: (_, model, widget) => AppScaffold( isShowDecPage: false, baseViewModel: model, - // isHelp: true, + isHelp: true, body: Container( child: SingleChildScrollView( child: Column( diff --git a/lib/pages/settings/general_setting.dart b/lib/pages/settings/general_setting.dart index 7085150a..6ce64d15 100644 --- a/lib/pages/settings/general_setting.dart +++ b/lib/pages/settings/general_setting.dart @@ -20,10 +20,10 @@ class _GeneralSettings extends State with TickerProviderStateMixin { var themeNotifier; int blindValue = 0; - bool vibration =false; - bool accsibility =false; - bool camera =false; - bool location =false; + bool vibration = false; + bool accsibility = false; + bool camera = false; + bool location = false; var sharedPref = new AppSharedPreferences(); var permission = new PermissionService(); var mediaQueryData; @@ -33,10 +33,9 @@ class _GeneralSettings extends State super.initState(); } - Widget build(BuildContext context) { - mediaQueryData = MediaQuery.of(context); - themeNotifier = Provider.of(context); + mediaQueryData = MediaQuery.of(context); + themeNotifier = Provider.of(context); return Container( child: ListView(scrollDirection: Axis.vertical, children: [ Container( @@ -59,7 +58,6 @@ class _GeneralSettings extends State onChanged: (value) { setState(() { vibration = value; - }); setVibration(value); }, @@ -81,7 +79,7 @@ class _GeneralSettings extends State setState(() { accsibility = value; }); - //setAccisibility(value); + //setAccisibility(value); }, activeTrackColor: Colors.lightGreenAccent, activeColor: Colors.green, @@ -228,7 +226,7 @@ class _GeneralSettings extends State ])); } - setTheme(value) async{ + setTheme(value) async { switch (value) { case 0: { @@ -239,7 +237,7 @@ class _GeneralSettings extends State case 1: { themeNotifier.setTheme(ThemeData( - fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', + //fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', primarySwatch: Colors.grey, visualDensity: VisualDensity.adaptivePlatformDensity, brightness: Brightness.light, @@ -262,7 +260,8 @@ class _GeneralSettings extends State highlightColor: Colors.grey[100].withOpacity(0.4), splashColor: Colors.transparent, primaryColor: Colors.grey, - bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), + bottomSheetTheme: + BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), cursorColor: Colors.grey, iconTheme: IconThemeData(), @@ -296,139 +295,142 @@ class _GeneralSettings extends State break; } //permission.setTheme(value); - } - setVibration(value){ + + setVibration(value) { permission.setVibrationPermission(value); } - setAccisibility(){ - if(!accsibility){ - - } - // permission.setVibrationPermission(value); + setAccisibility() { + if (!accsibility) {} + // permission.setVibrationPermission(value); } - getValues() async{ - blindValue= permission.isThemeEnabled() == null ? 0 : permission.isThemeEnabled(); - vibration = permission.isVibrationEnabled() ==null ? false : permission.isVibrationEnabled(); - accsibility =mediaQueryData.accessibleNavigation; - } - getTheme(value) async{ - if(value ==1){ - return ThemeData( - fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', - primarySwatch: Colors.grey, - visualDensity: VisualDensity.adaptivePlatformDensity, - brightness: Brightness.light, - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: ZoomPageTransitionsBuilder(), - TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), - }, - ), - hintColor: Colors.grey[400], - cardColor: Colors.black, - buttonColor: Colors.grey[400], - disabledColor: Colors.grey[300], - errorColor: Color.fromRGBO(235, 80, 60, 1.0), - scaffoldBackgroundColor: Colors.grey, - textSelectionColor: Color.fromRGBO(80, 100, 253, 0.5), - textSelectionHandleColor: Colors.grey, - canvasColor: Colors.white, - backgroundColor: Colors.grey, - highlightColor: Colors.grey[100].withOpacity(0.4), - splashColor: Colors.transparent, - primaryColor: Colors.grey, - bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), - cursorColor: Colors.grey, - - iconTheme: IconThemeData(), - appBarTheme: AppBarTheme( - color: Colors.grey, - brightness: Brightness.dark, - elevation: 10.0, - actionsIconTheme: IconThemeData( - color: Colors.grey, - ), - ), - ); - }else if(value ==3){ - return ThemeData( - fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', - primarySwatch: Colors.grey, - visualDensity: VisualDensity.adaptivePlatformDensity, - brightness: Brightness.light, - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: ZoomPageTransitionsBuilder(), - TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), - }, - ), - hintColor: Colors.grey[400], - cardColor: Colors.black, - buttonColor: Colors.grey[400], - disabledColor: Colors.grey[300], - errorColor: Color.fromRGBO(235, 80, 60, 1.0), - scaffoldBackgroundColor: Colors.grey, - textSelectionColor: Color.fromRGBO(80, 100, 253, 0.5), - textSelectionHandleColor: Colors.grey, - canvasColor: Colors.white, - backgroundColor: Colors.grey, - highlightColor: Colors.grey[100].withOpacity(0.4), - splashColor: Colors.transparent, - primaryColor: Colors.grey, - bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), - cursorColor: Colors.grey, + getValues() async { + blindValue = + permission.isThemeEnabled() == null ? 0 : permission.isThemeEnabled(); + vibration = permission.isVibrationEnabled() == null + ? false + : permission.isVibrationEnabled(); + accsibility = mediaQueryData.accessibleNavigation; + } - iconTheme: IconThemeData(), - appBarTheme: AppBarTheme( - color: Colors.black45, - brightness: Brightness.dark, - elevation: 10.0, - actionsIconTheme: IconThemeData( - color: Colors.grey, - ), - ), - ); + getTheme(value) async { + if (value == 1) { + return ThemeData( + // fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', + primarySwatch: Colors.grey, + visualDensity: VisualDensity.adaptivePlatformDensity, + brightness: Brightness.light, + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: ZoomPageTransitionsBuilder(), + TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), + }, + ), + hintColor: Colors.grey[400], + cardColor: Colors.black, + buttonColor: Colors.grey[400], + disabledColor: Colors.grey[300], + errorColor: Color.fromRGBO(235, 80, 60, 1.0), + scaffoldBackgroundColor: Colors.grey, + textSelectionColor: Color.fromRGBO(80, 100, 253, 0.5), + textSelectionHandleColor: Colors.grey, + canvasColor: Colors.white, + backgroundColor: Colors.grey, + highlightColor: Colors.grey[100].withOpacity(0.4), + splashColor: Colors.transparent, + primaryColor: Colors.grey, + bottomSheetTheme: + BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), + cursorColor: Colors.grey, - }else { - return ThemeData( - fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', - primarySwatch: Colors.blue, - visualDensity: VisualDensity.adaptivePlatformDensity, - brightness: Brightness.light, - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - TargetPlatform.android: ZoomPageTransitionsBuilder(), - TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), - }, - ), - hintColor: Colors.grey[400], - disabledColor: Colors.grey[300], - errorColor: Color.fromRGBO(235, 80, 60, 1.0), - scaffoldBackgroundColor: Color(0xffEEEEEE), - textSelectionColor: Color.fromRGBO(80, 100, 253, 0.5), - textSelectionHandleColor: Colors.grey, - canvasColor: Colors.white, - backgroundColor: Colors.white, - highlightColor: Colors.grey[100].withOpacity(0.4), - splashColor: Colors.transparent, - primaryColor: Color(0xff40ACC9), - bottomSheetTheme: BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), - cursorColor: Colors.grey, - cardColor: Colors.white, - iconTheme: IconThemeData(), - appBarTheme: AppBarTheme( - color: Color(0xff40ACC9), - brightness: Brightness.dark, - elevation: 10.0, - actionsIconTheme: IconThemeData( - color: Color(0xff40ACC9), - ), - ), - ); + iconTheme: IconThemeData(), + appBarTheme: AppBarTheme( + color: Colors.grey, + brightness: Brightness.dark, + elevation: 10.0, + actionsIconTheme: IconThemeData( + color: Colors.grey, + ), + ), + ); + } else if (value == 3) { + return ThemeData( + // fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', + primarySwatch: Colors.grey, + visualDensity: VisualDensity.adaptivePlatformDensity, + brightness: Brightness.light, + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: ZoomPageTransitionsBuilder(), + TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), + }, + ), + hintColor: Colors.grey[400], + cardColor: Colors.black, + buttonColor: Colors.grey[400], + disabledColor: Colors.grey[300], + errorColor: Color.fromRGBO(235, 80, 60, 1.0), + scaffoldBackgroundColor: Colors.grey, + textSelectionColor: Color.fromRGBO(80, 100, 253, 0.5), + textSelectionHandleColor: Colors.grey, + canvasColor: Colors.white, + backgroundColor: Colors.grey, + highlightColor: Colors.grey[100].withOpacity(0.4), + splashColor: Colors.transparent, + primaryColor: Colors.grey, + bottomSheetTheme: + BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), + cursorColor: Colors.grey, - } + iconTheme: IconThemeData(), + appBarTheme: AppBarTheme( + color: Colors.black45, + brightness: Brightness.dark, + elevation: 10.0, + actionsIconTheme: IconThemeData( + color: Colors.grey, + ), + ), + ); + } else { + return ThemeData( + //fontFamily: await sharedPref.getString(APP_LANGUAGE) == 'ar' ? 'Cairo' : 'WorkSans', + primarySwatch: Colors.blue, + visualDensity: VisualDensity.adaptivePlatformDensity, + brightness: Brightness.light, + pageTransitionsTheme: const PageTransitionsTheme( + builders: { + TargetPlatform.android: ZoomPageTransitionsBuilder(), + TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), + }, + ), + hintColor: Colors.grey[400], + disabledColor: Colors.grey[300], + errorColor: Color.fromRGBO(235, 80, 60, 1.0), + scaffoldBackgroundColor: Color(0xffEEEEEE), + textSelectionColor: Color.fromRGBO(80, 100, 253, 0.5), + textSelectionHandleColor: Colors.grey, + canvasColor: Colors.white, + backgroundColor: Colors.white, + highlightColor: Colors.grey[100].withOpacity(0.4), + splashColor: Colors.transparent, + primaryColor: Color(0xff40ACC9), + bottomSheetTheme: + BottomSheetThemeData(backgroundColor: Color(0xffE0E0E0)), + cursorColor: Colors.grey, + cardColor: Colors.white, + iconTheme: IconThemeData(), + appBarTheme: AppBarTheme( + color: Color(0xff40ACC9), + brightness: Brightness.dark, + elevation: 10.0, + actionsIconTheme: IconThemeData( + color: Color(0xff40ACC9), + ), + ), + ); + } } } diff --git a/lib/splashPage.dart b/lib/splashPage.dart index 20da2ba6..ef5db7f5 100644 --- a/lib/splashPage.dart +++ b/lib/splashPage.dart @@ -31,15 +31,14 @@ class _SplashScreenState extends State { super.initState(); Timer( Duration(seconds: 1, milliseconds: 500), - () { - loadPrivilege().then((value) { - Navigator.of(context).pushReplacement( - MaterialPageRoute( - builder: (BuildContext context) => LandingPage(), - ), - ); - }); - + () { + loadPrivilege().then((value) { + Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (BuildContext context) => LandingPage(), + ), + ); + }); }, ); } @@ -47,14 +46,19 @@ class _SplashScreenState extends State { /// load the Privilege from service Future loadPrivilege() async { await _privilegeService.getPrivilege(); - Provider.of(context, listen: false).setPrivilegeModelList(privilege: _privilegeService.privilegeModelList); + Provider.of(context, listen: false) + .setPrivilegeModelList(privilege: _privilegeService.privilegeModelList); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, - body: Image.asset('assets/images/powerd-by.jpg',fit: BoxFit.fitWidth,width: MediaQuery.of(context).size.width,), + body: Image.asset( + 'assets/images/powerd-by.jpg', + fit: BoxFit.fitWidth, + width: MediaQuery.of(context).size.width, + ), ); } } diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart index 4e37317d..4003f2ba 100644 --- a/lib/uitl/translations_delegate_base.dart +++ b/lib/uitl/translations_delegate_base.dart @@ -1468,6 +1468,7 @@ class TranslationBase { String get areyousure => localizedValues["areyousure"][locale.languageCode]; String get preferredunit => localizedValues["preferredunit"][locale.languageCode]; + String get trySaying => localizedValues["try-saying"][locale.languageCode]; } class TranslationBaseDelegate extends LocalizationsDelegate { diff --git a/lib/widgets/others/app_scaffold_widget.dart b/lib/widgets/others/app_scaffold_widget.dart index c540ff56..56c7fc0c 100644 --- a/lib/widgets/others/app_scaffold_widget.dart +++ b/lib/widgets/others/app_scaffold_widget.dart @@ -51,7 +51,6 @@ class AppScaffold extends StatelessWidget { final List appBarIcons; final List imagesInfo; final bool isHelp; - bool isAnimation = false; AuthenticatedUserObject authenticatedUserObject = locator(); @@ -206,17 +205,20 @@ class _RobotIcon extends State { void initState() { event.controller.stream.listen((p) { if (p['animationEnable'] == 'false') { - //setState(() { - // if (this.mounted) { - this.isAnimation = false; - //} - // }); + if (this.mounted) { + setState(() { + this.isAnimation = false; + }); + } + } else if (p['animationEnable'] == 'true') { + if (this.mounted) { + setState(() { + this.isAnimation = true; + }); + } } }); - setState(() { - setAnimation(); - }); super.initState(); } @@ -277,13 +279,10 @@ class _RobotIcon extends State { bottom: 50); } - setAnimation() async { - //await sharedPref.getBool(IS_ROBOT_VISIBLE) || - var animation = - await sharedPref.getBool(IS_ROBOT_INIT) == null ? true : false; + // setAnimation() async { + // /// await sharedPref.getBool(IS_ROBOT_VISIBLE) || + // // var animation = + // // IS_TEXT_COMPLETED == ? true : false; - setState(() { - this.isAnimation = animation; - }); - } + // } } diff --git a/lib/widgets/others/floating_button_search.dart b/lib/widgets/others/floating_button_search.dart index cddeba51..d795fd48 100644 --- a/lib/widgets/others/floating_button_search.dart +++ b/lib/widgets/others/floating_button_search.dart @@ -59,8 +59,7 @@ 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_recognition_result.dart'; -import 'package:speech_to_text/speech_to_text.dart'; +import 'package:speech_to_text/speech_to_text.dart' as stt; import 'package:diplomaticquarterapp/pages/BookAppointment/DoctorProfile.dart'; import 'package:diplomaticquarterapp/pages/BookAppointment/Search.dart'; import 'package:flutter/cupertino.dart'; @@ -82,7 +81,7 @@ class _FloatingSearchButton extends State RobotProvider eventProvider = RobotProvider(); bool isLoading = false; bool isError = false; - final SpeechToText speech = SpeechToText(); + stt.SpeechToText speech = stt.SpeechToText(); String error = ''; String _currentLocaleId = ""; String lastError; @@ -102,28 +101,40 @@ class _FloatingSearchButton extends State var sharedPref = new AppSharedPreferences(); bool _hasSpeech = false; ProjectViewModel projectProvider; - bool isAnimationEnable = false; + bool isAnimationEnable = true; AnimationController controller; Animation offset; String networkImage; + bool isArabic; @override void initState() { controller = AnimationController(vsync: this, duration: Duration(seconds: 1)); - offset = Tween(begin: Offset.zero, end: Offset(0.0, 1.0)) + offset = Tween(begin: Offset(0.0, 1.0), end: Offset(0.0, 0.0)) .animate(controller); - initialSpeak(); - Future.delayed(const Duration(seconds: 2), () { + if (IS_VOICE_COMMAND_CLOSED == true) { + controller.reverse(from: -1); + } + if (mounted) { + //Future.delayed(const Duration(seconds: 2), () { + isArabic = Provider.of(context, listen: false).isArabic; requestPermissions(); getUserData(); - }); + initialSpeak(); + setState(() { + if (IS_TEXT_COMPLETED) { + isAnimationEnable = false; + } + }); + } event.controller.stream.listen((p) { if (p['isRobotVisible'] == 'true') { if (this.mounted) { setState(() { - sharedPref.setBool(IS_ROBOT_VISIBLE, true); - controller.reverse(); + if (IS_VOICE_COMMAND_CLOSED == false) { + controller.forward(); + } }); } } @@ -141,21 +152,25 @@ class _FloatingSearchButton extends State } @override - void didUpdateWidget(FloatingSearchButton oldWidget) { - // super.didUpdateWidget(oldWidget); - // event.controller.stream.listen((p) { - // if (p['animationEnable'] != 'false') { - // initialSpeak(); - // } - // }); + void dispose() { + controller.dispose(); + super.dispose(); } + // @override + // void didUpdateWidget(FloatingSearchButton oldWidget) { + // // super.didUpdateWidget(oldWidget); + // // event.controller.stream.listen((p) { + // // if (p['animationEnable'] != 'false') { + // // initialSpeak(); + // // } + // // }); + // } AuthenticatedUserObject authenticatedUserObject = locator(); VitalSignService _vitalSignService = locator(); @override Widget build(BuildContext context) { - projectProvider = Provider.of(context); return Container( child: SlideTransition(position: offset, child: getStack())); } @@ -180,7 +195,6 @@ class _FloatingSearchButton extends State : 'assets/images/gif/robot-idle.gif'), ), onTap: () { - RoboSearch.isClosed = false; new RoboSearch(context: context).showAlertDialog(context); initSpeechState().then((value) => {startVoiceSearch()}); }, @@ -192,8 +206,8 @@ class _FloatingSearchButton extends State onTap: () { setState(() { if (this.mounted) { - controller.forward(); - sharedPref.setBool(IS_ROBOT_VISIBLE, false); + controller.reverse(); + IS_VOICE_COMMAND_CLOSED = true; } }); }, @@ -213,25 +227,38 @@ class _FloatingSearchButton extends State startVoiceSearch() async { _currentLocaleId = TranslationBase.of(AppGlobal.context).locale.languageCode; - speech.listen( + bool available = await speech.initialize( + onStatus: statusListener, onError: errorListener); + if (available) { + speech.listen( onResult: resultListener, - listenFor: Duration(seconds: 10), + // listenMode: ListenMode.confirmation, localeId: _currentLocaleId == 'en' ? 'en-US' : 'ar-SA', - onSoundLevelChange: soundLevelListener, - cancelOnError: true, - partialResults: true, - onDevice: true, - listenMode: ListenMode.deviceDefault); + ); + } 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); } - void resultListener(SpeechRecognitionResult result) { - // lastWords = "${result.recognizedWords} - ${result.finalResult}"; + void resultListener(result) { reconizedWord = result.recognizedWords; event.setValue({"searchText": reconizedWord}); if (result.finalResult == true) { Future.delayed(const Duration(seconds: 1), () { _speak(reconizedWord); RoboSearch.closeAlertDialog(context); + //Navigator.of(context).pop(); }); } } @@ -250,9 +277,12 @@ class _FloatingSearchButton extends State } void requestPermissions() async { - Map statuses = await [ - Permission.microphone, - ].request(); + if (await Permission.microphone.isDenied || + await Permission.microphone.isUndetermined) { + Map statuses = await [ + Permission.microphone, + ].request(); + } } Future initSpeechState() async { @@ -274,9 +304,7 @@ class _FloatingSearchButton extends State void errorListener(SpeechRecognitionError error) { event.setValue({"searchText": 'null'}); - //setState(() { - // reconizedWord = "${error.errorMsg} - ${error.permanent}"; - //}); + RoboSearch.closeAlertDialog(context); } void statusListener(String status) { @@ -298,9 +326,7 @@ class _FloatingSearchButton extends State } getCommands(result) async { - print(result); results = result; - switch (result["CommandNumber"]) { case '100': { @@ -797,14 +823,16 @@ class _FloatingSearchButton extends State } speak({isInit}) async { + //if (mounted) { setState(() { this.networkImage = results['AnimationURL']; this.isAnimationEnable = true; }); - - if (Provider.of(context, listen: false).isArabic == - false && - results['ReturnMessage'] != null) { + //} + if (isInit == true) { + event.setValue({"animationEnable": 'true'}); + } + if (isArabic == false && results['ReturnMessage'] != null) { await flutterTts .setVoice({"name": "en-au-x-aub-network", "locale": "en-AU"}); await flutterTts.speak(results['ReturnMessage']); @@ -840,45 +868,33 @@ class _FloatingSearchButton extends State } initialSpeak() async { + 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." }; - if (await sharedPref.getBool(IS_ROBOT_INIT) == null) { - this.speak(isInit: true); - controller.reverse(); - } else { + if (IS_VOICE_COMMAND_CLOSED == false) { + if (IS_TEXT_COMPLETED == false) { + this.speak(isInit: true); + } + controller.forward(); } - // if (Provider.of(context, listen: false).isArabic == - // false && - // results['ReturnMessage'] != null) { - // await flutterTts - // .setVoice({"name": "en-au-x-aub-network", "locale": "en-AU"}); - // await flutterTts.speak(results['ReturnMessage']); - // } else if (results['ReturnMessage_Ar'] != null) { - // await flutterTts - // .setVoice({"name": "ar-xa-x-ard-network", "locale": "ar"}); - // await flutterTts.speak(results['ReturnMessage_Ar']); - // } - - //this.isAnimationEnable = true; - //stopAnimation(); } stopAnimation({isInit}) async { - if (isInit && (await sharedPref.getBool(IS_ROBOT_INIT) == null)) { - sharedPref.setBool(IS_ROBOT_INIT, isInit); + if (isInit == true) { + IS_TEXT_COMPLETED = true; } - flutterTts.setCompletionHandler(() => { - 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 { @@ -895,91 +911,131 @@ class _FloatingSearchButton extends State class RoboSearch { final BuildContext context; - var event = RobotProvider(); - var searchText; - static StreamSubscription streamSubscription; - static var isClosed = false; + static var dialog; RoboSearch({ @required this.context, }); showAlertDialog(BuildContext context) { - AlertDialog alert = AlertDialog( - content: StatefulBuilder( - builder: (BuildContext context, StateSetter setState) { - streamSubscription = event.controller.stream.listen((p) { - if (p['searchText'] != 'null' && - p['searchText'] != null && - p['searchText'] != "" && - isClosed == false) { - setState(() { - searchText = p['searchText']; - }); - } - }); - print(streamSubscription); - return Container( - color: Colors.white, - height: SizeConfig.realScreenHeight * 0.5, - width: SizeConfig.realScreenWidth * 0.8, - child: Container( - child: Column(children: [ - Expanded( - flex: 1, - child: Center( - child: Image.asset( - 'assets/images/habib-logo.png', - height: 75, - width: 75, - ))), - Expanded( - flex: 3, - child: Center( - child: Container( - margin: EdgeInsets.all(20), - padding: EdgeInsets.all(10), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(100), - border: Border.all(width: 2, color: Colors.red)), - child: Icon( - Icons.mic, - color: Colors.blue, - size: 48, - ), - ))), - Expanded( - flex: 1, - child: Center( - child: Text(searchText != null && searchText != 'null' - ? searchText - : 'Try saying something'))), - searchText == 'null' - ? Center( - child: RaisedButton( - child: Text('Retry'), - onPressed: () { - RoboSearch.closeAlertDialog(context); - event.setValue({'startPopUp': 'true'}); - }, - )) - : SizedBox() - ]), - )); - }), - ); + //AlertDialog alert = AlertDialog + // AlertDialog alert = AlertDialog(content: MyStatefulBuilder(dispose: () { + // print('dispose!!!!!!!!!!!!'); + // }) + // isClosed = true; + // streamSubscription.cancel(); + // }, builder: (BuildContext context, StateSetter setState) { + // //print(streamSubscription); + // }), + // ); // show the dialog showDialog( context: context, + barrierDismissible: true, builder: (BuildContext context) { - return alert; + dialog = context; + return MyStatefulBuilder( + dispose: () {}, + ); }, - ).then((value) => {}); + ); + print(dialog); } static closeAlertDialog(BuildContext context) { - isClosed = true; - streamSubscription.cancel(); - Navigator.of(context).pop(); + Navigator.of(dialog).pop(); + } +} + +typedef Disposer = void Function(); + +class MyStatefulBuilder extends StatefulWidget { + const MyStatefulBuilder({ + // @required this.builder, + @required this.dispose, + }); + + //final StatefulWidgetBuilder builder; + final Disposer dispose; + + @override + _MyStatefulBuilderState createState() => _MyStatefulBuilderState(); +} + +class _MyStatefulBuilderState extends State { + var event = RobotProvider(); + var searchText; + static StreamSubscription streamSubscription; + static var isClosed = false; + @override + void initState() { + streamSubscription = event.controller.stream.listen((p) { + if ((p['searchText'] != 'null' && + p['searchText'] != null && + p['searchText'] != "" && + isClosed == false) && + mounted) { + setState(() { + searchText = p['searchText']; + }); + } + }); + super.initState(); + } + + @override + Widget build(BuildContext context) => AlertDialog( + content: Container( + color: Colors.white, + height: SizeConfig.realScreenHeight * 0.5, + width: SizeConfig.realScreenWidth * 0.8, + child: Container( + child: Column(children: [ + Expanded( + flex: 1, + child: Center( + child: Image.asset( + 'assets/images/habib-logo.png', + height: 75, + width: 75, + ))), + Expanded( + flex: 3, + child: Center( + child: Container( + margin: EdgeInsets.all(20), + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(100), + border: Border.all(width: 2, color: Colors.red)), + child: Icon( + Icons.mic, + color: Colors.blue, + size: 48, + ), + ))), + Expanded( + flex: 1, + child: Center( + child: Text(searchText != null && searchText != 'null' + ? searchText + : TranslationBase.of(context).trySaying))), + searchText == 'null' + ? Center( + child: RaisedButton( + child: Text('Retry'), + onPressed: () { + RoboSearch.closeAlertDialog(context); + event.setValue({'startPopUp': 'true'}); + }, + )) + : SizedBox() + ]), + ))); + + @override + void dispose() { + super.dispose(); + widget.dispose(); } } diff --git a/lib/widgets/typewriter/typewiter.dart b/lib/widgets/typewriter/typewiter.dart index 97a54150..cc258251 100644 --- a/lib/widgets/typewriter/typewiter.dart +++ b/lib/widgets/typewriter/typewiter.dart @@ -15,7 +15,7 @@ class _TyperState extends State int _stringIndex; @override void initState() { - _controller = new AnimationController( + _controller = new AnimationController( duration: const Duration(seconds: 7), vsync: this, ); @@ -24,8 +24,8 @@ class _TyperState extends State setState(() { _stringIndex = _stringIndex == null ? 0 : _stringIndex + 1; _characterCount = new StepTween(begin: 0, end: widget.textLength) - .animate(new CurvedAnimation(parent: _controller, curve: Curves.easeIn)); - + .animate( + new CurvedAnimation(parent: _controller, curve: Curves.easeIn)); }); _controller.forward(); }); @@ -43,9 +43,8 @@ class _TyperState extends State setState(() { _stringIndex = _stringIndex == null ? 0 : _stringIndex + 1; - _characterCount = new StepTween(begin: 0, end: widget.textLength) - .animate(new CurvedAnimation(parent: _controller, curve: Curves.easeIn)); - + _characterCount = new StepTween(begin: 0, end: widget.textLength).animate( + new CurvedAnimation(parent: _controller, curve: Curves.easeIn)); }); _controller.forward(); } @@ -55,18 +54,22 @@ class _TyperState extends State _controller.dispose(); super.dispose(); } + @override Widget build(BuildContext context) { - - return Container( - child: _characterCount == null ? null : new AnimatedBuilder( - animation: _characterCount, - builder: (BuildContext context, Widget child) { - String text = widget.text.substring(0, _characterCount.value); - return Text(text, style: TextStyle(color:Colors.black, fontSize: 12), textAlign: TextAlign.start, - - ); - }, - )); + return Container( + child: _characterCount == null + ? null + : new AnimatedBuilder( + animation: _characterCount, + builder: (BuildContext context, Widget child) { + String text = widget.text.substring(0, _characterCount.value); + return Text( + text, + style: TextStyle(color: Colors.black, fontSize: 12), + textAlign: TextAlign.start, + ); + }, + )); } -} \ No newline at end of file +} diff --git a/pubspec.yaml b/pubspec.yaml index e9c5c00b..61838e72 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -21,7 +21,7 @@ dependencies: # http client http: ^0.12.1 connectivity: ^0.4.9+3 - + audio_wave: ^0.0.3 # State Management provider: ^4.3.2+2