From 889ae24f0799088c4d2f8430b61fe364159da881 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 9 Aug 2021 11:25:46 +0300 Subject: [PATCH] merge changes-3 --- assets/images/powerd-by.jpg | Bin 150482 -> 23220 bytes assets/payment_options/payment_options.png | Bin 0 -> 22119 bytes .../prescriptions/prescription_report.dart | 2 +- .../prescription_report_enh.dart | 68 +-- .../medical/prescriptions_service.dart | 112 ++-- .../medical/prescriptions_view_model.dart | 36 +- .../new_e_referral_step_one_page.dart | 4 +- .../AlHabibMedicalService/h2o/month_page.dart | 7 +- .../ovulation_result_page.dart | 11 +- .../AlHabibMedicalService/my_web_view.dart | 14 +- .../AlHabibMedicalService/parking_page.dart | 9 +- lib/pages/DrawerPages/family/my-family.dart | 30 +- lib/pages/ErService/NearestEr.dart | 1 + .../medical/balance/my_balance_page.dart | 5 +- lib/pages/medical/balance/new_text_Field.dart | 82 +-- .../medical/my_trackers/my_trackers.dart | 61 ++- .../widget/MonthCurvedChartBloodPressure.dart | 20 +- .../widget/MonthLineChartCurved.dart | 38 +- .../pharmacy_for_prescriptions_page.dart | 144 ++--- .../prescription_details_page.dart | 29 +- .../prescription_items_page.dart | 88 +-- .../medical/reports/monthly_reports.dart | 62 +-- lib/pages/vaccine/my_vaccines_screen.dart | 323 +++++------ .../permission/permission_service.dart | 63 ++- .../pharmacyAddress_service.dart | 2 +- lib/widgets/nfc/nfc_reader_sheet.dart | 196 +++++++ lib/widgets/others/not_auh_page.dart | 28 + pubspec.yaml | 12 +- .../assets/sounds/speech_to_text_cancel.m4r | Bin 0 -> 14006 bytes .../sounds/speech_to_text_listening.m4r | Bin 0 -> 16416 bytes .../assets/sounds/speech_to_text_stop.m4r | Bin 0 -> 17128 bytes speech_to_text_/example/pubspec.yaml | 33 ++ .../lib/speech_recognition_error.dart | 44 ++ .../lib/speech_recognition_error.g.dart | 22 + .../lib/speech_recognition_event.dart | 30 + .../lib/speech_recognition_result.dart | 140 +++++ .../lib/speech_recognition_result.g.dart | 41 ++ speech_to_text_/lib/speech_to_text.dart | 511 ++++++++++++++++++ .../lib/speech_to_text_provider.dart | 201 +++++++ speech_to_text_/pubspec.yaml | 31 ++ .../test/speech_recognition_error_test.dart | 65 +++ .../test/speech_recognition_event_test.dart | 42 ++ .../test/speech_recognition_result_test.dart | 134 +++++ .../test/speech_recognitions_words_test.dart | 86 +++ .../test/speech_to_text_provider_test.dart | 196 +++++++ speech_to_text_/test/speech_to_text_test.dart | 425 +++++++++++++++ 46 files changed, 2897 insertions(+), 551 deletions(-) create mode 100644 assets/payment_options/payment_options.png create mode 100644 lib/widgets/nfc/nfc_reader_sheet.dart create mode 100644 speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r create mode 100644 speech_to_text_/example/assets/sounds/speech_to_text_listening.m4r create mode 100644 speech_to_text_/example/assets/sounds/speech_to_text_stop.m4r create mode 100644 speech_to_text_/example/pubspec.yaml create mode 100644 speech_to_text_/lib/speech_recognition_error.dart create mode 100644 speech_to_text_/lib/speech_recognition_error.g.dart create mode 100644 speech_to_text_/lib/speech_recognition_event.dart create mode 100644 speech_to_text_/lib/speech_recognition_result.dart create mode 100644 speech_to_text_/lib/speech_recognition_result.g.dart create mode 100644 speech_to_text_/lib/speech_to_text.dart create mode 100644 speech_to_text_/lib/speech_to_text_provider.dart create mode 100644 speech_to_text_/pubspec.yaml create mode 100644 speech_to_text_/test/speech_recognition_error_test.dart create mode 100644 speech_to_text_/test/speech_recognition_event_test.dart create mode 100644 speech_to_text_/test/speech_recognition_result_test.dart create mode 100644 speech_to_text_/test/speech_recognitions_words_test.dart create mode 100644 speech_to_text_/test/speech_to_text_provider_test.dart create mode 100644 speech_to_text_/test/speech_to_text_test.dart diff --git a/assets/images/powerd-by.jpg b/assets/images/powerd-by.jpg index 93bdbb1881c65b9ad9e8463f2d0d251f1e0e64a1..eda1688c1e4aacec49b57985026b92e9e31c9c0f 100644 GIT binary patch literal 23220 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 F{|9iKfB*mh diff --git a/assets/payment_options/payment_options.png b/assets/payment_options/payment_options.png new file mode 100644 index 0000000000000000000000000000000000000000..4bb83fec564f0ee729423d991b449e9849e9bf5a GIT binary patch literal 22119 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 json) { address = json['Address']; @@ -85,6 +87,7 @@ class PrescriptionReportEnh { imageThumbUrl = json['ImageThumbUrl']; isCovered = json['IsCovered']; itemDescription = json['ItemDescription']; + itemDescriptionN = json['ItemDescriptionN']; itemID = json['ItemID']; orderDate = json['OrderDate']; patientID = json['PatientID']; @@ -122,6 +125,7 @@ class PrescriptionReportEnh { data['ImageThumbUrl'] = this.imageThumbUrl; data['IsCovered'] = this.isCovered; data['ItemDescription'] = this.itemDescription; + data['ItemDescriptionN'] = this.itemDescriptionN; data['ItemID'] = this.itemID; data['OrderDate'] = this.orderDate; data['PatientID'] = this.patientID; diff --git a/lib/core/service/medical/prescriptions_service.dart b/lib/core/service/medical/prescriptions_service.dart index e9741a7f..af34f2ba 100644 --- a/lib/core/service/medical/prescriptions_service.dart +++ b/lib/core/service/medical/prescriptions_service.dart @@ -2,6 +2,7 @@ import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/Prescriptions.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/perscription_pharmacy.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report.dart'; +import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report_inp.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report_enh.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/prescriptions_order.dart'; import 'package:diplomaticquarterapp/core/model/prescriptions/request_get_list_pharmacy_for_prescriptions.dart'; @@ -15,7 +16,7 @@ import 'package:flutter/cupertino.dart'; class PrescriptionsService extends BaseService { List prescriptionsList = List(); - + List prescriptionReportListINP = List(); List prescriptionsOrderList = List(); Future getPrescriptions() async { @@ -56,32 +57,40 @@ class PrescriptionsService extends BaseService { appointmentNo: 0, isDentalAllowedBackend: false); List prescriptionReportList = List(); - Future getPrescriptionReport( - {Prescriptions prescriptions}) async { + Future getPrescriptionReport({Prescriptions prescriptions}) async { hasError = false; - _requestPrescriptionReport.dischargeNo = prescriptions.dischargeNo; + if (prescriptions.isInOutPatient == false) { + _requestPrescriptionReport.dischargeNo = prescriptions.dischargeNo; + } else { + _requestPrescriptionReport.dischargeNo = 0; + } _requestPrescriptionReport.projectID = prescriptions.projectID; _requestPrescriptionReport.clinicID = prescriptions.clinicID; _requestPrescriptionReport.setupID = prescriptions.setupID; _requestPrescriptionReport.episodeID = prescriptions.episodeID; _requestPrescriptionReport.appointmentNo = prescriptions.appointmentNo; - await baseAppClient.post(prescriptions.isInOutPatient? GET_PRESCRIPTION_REPORT_ENH : GET_PRESCRIPTION_REPORT, + await baseAppClient.post( + prescriptions.isInOutPatient + ? GET_PRESCRIPTION_REPORT_ENH + : GET_PRESCRIPTION_REPORT, onSuccess: (dynamic response, int statusCode) { prescriptionReportList.clear(); prescriptionReportEnhList.clear(); - if(prescriptions.isInOutPatient){ + if (prescriptions.isInOutPatient) { response['ListPRM'].forEach((prescriptions) { - prescriptionReportList.add(PrescriptionReport.fromJson(prescriptions)); - prescriptionReportEnhList.add(PrescriptionReportEnh.fromJson(prescriptions)); + prescriptionReportList + .add(PrescriptionReport.fromJson(prescriptions)); + prescriptionReportEnhList + .add(PrescriptionReportEnh.fromJson(prescriptions)); }); - }else{ + } else { + prescriptionReportListINP.clear(); response['INP_GetPrescriptionReport_List'].forEach((prescriptions) { - prescriptionReportList.add(PrescriptionReport.fromJson(prescriptions)); + prescriptionReportListINP + .add(PrescriptionReportINP.fromJson(prescriptions)); }); } - - }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; @@ -90,35 +99,42 @@ class PrescriptionsService extends BaseService { RequestSendPrescriptionEmail _requestSendPrescriptionEmail = RequestSendPrescriptionEmail( - isDentalAllowedBackend: false,); + isDentalAllowedBackend: false, + ); Future sendPrescriptionEmail(String appointmentDate, int patientID, - String clinicName, String doctorName, int projectID) async { + String clinicName, String doctorName, int doctorID, int projectID) async { _requestSendPrescriptionEmail.listPrescriptions = prescriptionReportList; _requestSendPrescriptionEmail.appointmentDate = appointmentDate; _requestSendPrescriptionEmail.patientID = patientID; _requestSendPrescriptionEmail.clinicName = clinicName; _requestSendPrescriptionEmail.doctorName = doctorName; _requestSendPrescriptionEmail.projectID = projectID; - _requestSendPrescriptionEmail.to = user.emailAddress; - _requestSendPrescriptionEmail.dateofBirth = user.dateofBirth; - _requestSendPrescriptionEmail.patientIditificationNum = user.patientIdentificationNo; - _requestSendPrescriptionEmail.patientMobileNumber = user.mobileNumber; - _requestSendPrescriptionEmail.patientName = user.firstName +" "+ user.lastName; - _requestSendPrescriptionEmail.setupID = user.setupID; + _requestSendPrescriptionEmail.to = user.emailAddress; + _requestSendPrescriptionEmail.dateofBirth = user.dateofBirth; + _requestSendPrescriptionEmail.patientIditificationNum = + user.patientIdentificationNo; + _requestSendPrescriptionEmail.patientMobileNumber = user.mobileNumber; + _requestSendPrescriptionEmail.doctorID = doctorID; + _requestSendPrescriptionEmail.patientName = + user.firstName + " " + user.lastName; + _requestSendPrescriptionEmail.setupID = user.setupID; + _requestSendPrescriptionEmail.to = user.emailAddress; hasError = false; - await baseAppClient.post(SEND_PRESCRIPTION_EMAIL, onSuccess: (response, statusCode) {}, + await baseAppClient + .post(SEND_PRESCRIPTION_EMAIL, onSuccess: (response, statusCode) {}, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: _requestSendPrescriptionEmail.toJson()); } - RequestGetListPharmacyForPrescriptions requestGetListPharmacyForPrescriptions = RequestGetListPharmacyForPrescriptions( + RequestGetListPharmacyForPrescriptions + requestGetListPharmacyForPrescriptions = + RequestGetListPharmacyForPrescriptions( latitude: 0, longitude: 0, isDentalAllowedBackend: false, - ); List pharmacyPrescriptionsList = List(); @@ -139,18 +155,19 @@ class PrescriptionsService extends BaseService { } RequestPrescriptionReportEnh _requestPrescriptionReportEnh = - RequestPrescriptionReportEnh(isDentalAllowedBackend: false,); + RequestPrescriptionReportEnh( + isDentalAllowedBackend: false, + ); List prescriptionReportEnhList = List(); - Future getPrescriptionReportEnh({PrescriptionsOrder prescriptionsOrder}) async { - + Future getPrescriptionReportEnh( + {PrescriptionsOrder prescriptionsOrder}) async { ///This logic copy from the old app from class [order-history.component.ts] in line 45 bool isInPatient = false; prescriptionsList.forEach((element) { if (prescriptionsOrder.appointmentNo == "0") { if (element.dischargeNo == int.parse(prescriptionsOrder.dischargeID)) { - _requestPrescriptionReportEnh.appointmentNo = element.appointmentNo; _requestPrescriptionReportEnh.clinicID = element.clinicID; _requestPrescriptionReportEnh.projectID = element.projectID; @@ -160,46 +177,45 @@ class PrescriptionsService extends BaseService { isInPatient = element.isInOutPatient; } } else { - if (int.parse(prescriptionsOrder.appointmentNo) == element.appointmentNo) { + if (int.parse(prescriptionsOrder.appointmentNo) == + element.appointmentNo) { _requestPrescriptionReportEnh.appointmentNo = element.appointmentNo; _requestPrescriptionReportEnh.clinicID = element.clinicID; _requestPrescriptionReportEnh.projectID = element.projectID; _requestPrescriptionReportEnh.episodeID = element.episodeID; _requestPrescriptionReportEnh.setupID = element.setupID; _requestPrescriptionReportEnh.dischargeNo = element.dischargeNo; - isInPatient = element.isInOutPatient;///call inpGetPrescriptionReport + isInPatient = element.isInOutPatient; + + ///call inpGetPrescriptionReport } } }); hasError = false; - await baseAppClient.post(isInPatient? GET_PRESCRIPTION_REPORT_ENH : GET_PRESCRIPTION_REPORT, + await baseAppClient.post( + isInPatient ? GET_PRESCRIPTION_REPORT_ENH : GET_PRESCRIPTION_REPORT, onSuccess: (dynamic response, int statusCode) { prescriptionReportEnhList.clear(); - if(isInPatient){ + if (isInPatient) { response['ListPRM'].forEach((prescriptions) { - prescriptionReportEnhList.add(PrescriptionReportEnh.fromJson(prescriptions)); + prescriptionReportEnhList + .add(PrescriptionReportEnh.fromJson(prescriptions)); }); - }else{ + } else { response['INP_GetPrescriptionReport_List'].forEach((prescriptions) { - - PrescriptionReportEnh reportEnh = PrescriptionReportEnh.fromJson(prescriptions); - reportEnh.itemDescription = prescriptions['ItemDescriptionN']; + PrescriptionReportEnh reportEnh = + PrescriptionReportEnh.fromJson(prescriptions); + reportEnh.itemDescription = prescriptions['ItemDescriptionN']; prescriptionReportEnhList.add(reportEnh); - }); - } - - }, onFailure: (String error, int statusCode) { hasError = true; super.error = error; }, body: _requestPrescriptionReportEnh.toJson()); - - } Future updatePressOrder({@required int presOrderID}) async { @@ -211,12 +227,10 @@ class PrescriptionsService extends BaseService { body['PresOrderStatus'] = 4; body['isDentalAllowedBackend'] = false; await baseAppClient.post(UPDATE_PRESS_ORDER, - onSuccess: (dynamic response, int statusCode) { - - }, onFailure: (String error, int statusCode) { - hasError = true; - super.error = error; - }, body: body); + onSuccess: (dynamic response, int statusCode) {}, + onFailure: (String error, int statusCode) { + hasError = true; + super.error = error; + }, body: body); } - } diff --git a/lib/core/viewModels/medical/prescriptions_view_model.dart b/lib/core/viewModels/medical/prescriptions_view_model.dart index 2c32a081..3ad9df99 100644 --- a/lib/core/viewModels/medical/prescriptions_view_model.dart +++ b/lib/core/viewModels/medical/prescriptions_view_model.dart @@ -4,7 +4,7 @@ import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_repor import 'package:diplomaticquarterapp/core/model/prescriptions/prescriptions_order.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:flutter/cupertino.dart'; - +import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_report_inp.dart'; import '../../../core/enum/filter_type.dart'; import '../../../core/enum/viewstate.dart'; import '../../../core/model/prescriptions/Prescriptions.dart'; @@ -19,17 +19,20 @@ class PrescriptionsViewModel extends BaseViewModel { List _prescriptionsOrderListClinic = List(); List _prescriptionsOrderListHospital = List(); - List get prescriptionReportList => _prescriptionsService.prescriptionReportList; + List get prescriptionReportListINP => + _prescriptionsService.prescriptionReportListINP; + List get prescriptionsList => _prescriptionsService.prescriptionsList; - List get prescriptionsHistory => _prescriptionsService.prescriptionsOrderList; - - List get pharmacyPrescriptionsList => _prescriptionsService.pharmacyPrescriptionsList ; + List get prescriptionsHistory => + _prescriptionsService.prescriptionsOrderList; + List get pharmacyPrescriptionsList => + _prescriptionsService.pharmacyPrescriptionsList; List get prescriptionsOrderList => filterType == FilterType.Clinic @@ -105,7 +108,8 @@ class PrescriptionsViewModel extends BaseViewModel { getPrescriptionReport({Prescriptions prescriptions}) async { setState(ViewState.Busy); - await _prescriptionsService.getPrescriptionReport(prescriptions: prescriptions); + await _prescriptionsService.getPrescriptionReport( + prescriptions: prescriptions); if (_prescriptionsService.hasError) { error = _prescriptionsService.error; setState(ViewState.ErrorLocal); @@ -119,11 +123,12 @@ class PrescriptionsViewModel extends BaseViewModel { int patientID, String clinicName, String doctorName, - String mes, + int doctorID, + String mes, int projectID}) async { setState(ViewState.BusyLocal); - await _prescriptionsService.sendPrescriptionEmail( - appointmentDate, patientID, clinicName, doctorName, projectID); + await _prescriptionsService.sendPrescriptionEmail(appointmentDate, + patientID, clinicName, doctorName, doctorID, projectID); if (_prescriptionsService.hasError) { error = _prescriptionsService.error; setState(ViewState.ErrorLocal); @@ -145,12 +150,13 @@ class PrescriptionsViewModel extends BaseViewModel { } } - - List get prescriptionReportEnhList => _prescriptionsService.prescriptionReportEnhList; + List get prescriptionReportEnhList => + _prescriptionsService.prescriptionReportEnhList; getPrescriptionReportEnh({PrescriptionsOrder prescriptionsOrder}) async { setState(ViewState.Busy); - await _prescriptionsService.getPrescriptionReportEnh(prescriptionsOrder: prescriptionsOrder); + await _prescriptionsService.getPrescriptionReportEnh( + prescriptionsOrder: prescriptionsOrder); if (_prescriptionsService.hasError) { error = _prescriptionsService.error; setState(ViewState.Error); @@ -159,16 +165,14 @@ class PrescriptionsViewModel extends BaseViewModel { } } - - Future updatePressOrder({@required int presOrderID}) async { + Future updatePressOrder({@required int presOrderID}) async { setState(ViewState.Busy); await _prescriptionsService.updatePressOrder(presOrderID: presOrderID); if (_prescriptionsService.hasError) { error = _prescriptionsService.error; setState(ViewState.Error); } else { - await getPrescriptions(); + await getPrescriptions(); } } - } diff --git a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart index b6cddf18..5a3271f2 100644 --- a/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart +++ b/lib/pages/AlHabibMedicalService/E-Referral/New_E_Referral/new_e_referral_step_one_page.dart @@ -292,7 +292,9 @@ class MobileNumberTextFiled extends StatelessWidget { padding: EdgeInsets.all(5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.white), - child: Row(children: [ + child: Row( + textDirection: TextDirection.ltr, + children: [ Expanded( flex: 1, child: Icon( diff --git a/lib/pages/AlHabibMedicalService/h2o/month_page.dart b/lib/pages/AlHabibMedicalService/h2o/month_page.dart index e0118495..8867fb77 100644 --- a/lib/pages/AlHabibMedicalService/h2o/month_page.dart +++ b/lib/pages/AlHabibMedicalService/h2o/month_page.dart @@ -1,5 +1,6 @@ import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/viewModels/AlHabibMedicalService/H2O_view_model.dart'; +import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/charts/app_bar_chart.dart'; @@ -8,15 +9,17 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/progress_indicator/app_circular_progress_Indeicator.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MonthPage extends StatelessWidget { @override Widget build(BuildContext context) { + ProjectViewModel projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => model.getUserProgressForMonthData(), builder: (_, model, widget) => AppScaffold( isShowAppBar: false, - appBarTitle: TranslationBase.of(context).h2o, + appBarTitle: TranslationBase.of(context).h2o, baseViewModel: model, body: Padding( padding: EdgeInsets.all(8.0), @@ -46,7 +49,7 @@ class MonthPage extends StatelessWidget { ], ), // SizedBox(height: 8), - AppBarChart(seriesList: model.userProgressForMonthDataSeries), + AppBarChart(seriesList: model.userProgressForMonthDataSeries, isArabic: projectViewModel.isArabic), ], ), ), diff --git a/lib/pages/AlHabibMedicalService/health_calculator/ovulation_period/ovulation_result_page.dart b/lib/pages/AlHabibMedicalService/health_calculator/ovulation_period/ovulation_result_page.dart index 6669bf75..6ced14b2 100644 --- a/lib/pages/AlHabibMedicalService/health_calculator/ovulation_period/ovulation_result_page.dart +++ b/lib/pages/AlHabibMedicalService/health_calculator/ovulation_period/ovulation_result_page.dart @@ -1,6 +1,8 @@ +import 'package:diplomaticquarterapp/pages/AlHabibMedicalService/health_calculator/doctor_list.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; @@ -9,8 +11,7 @@ class OvulationResult extends StatelessWidget { var dateTo; var conceivedDate; var deliveryDue; - OvulationResult( - {this.dateFrom, this.dateTo, this.deliveryDue, this.conceivedDate}); + OvulationResult({this.dateFrom, this.dateTo, this.deliveryDue, this.conceivedDate}); //var newFormat = DateFormat("yy-MM-dd"); @override @@ -84,6 +85,12 @@ class OvulationResult extends StatelessWidget { width: 350, child: Button( label: 'See List Of Doctors', + onTap: () { + Navigator.push( + context, + FadePage(page: DoctorList()), + ); + }, ), ), ], diff --git a/lib/pages/AlHabibMedicalService/my_web_view.dart b/lib/pages/AlHabibMedicalService/my_web_view.dart index 59163c15..c4841a24 100644 --- a/lib/pages/AlHabibMedicalService/my_web_view.dart +++ b/lib/pages/AlHabibMedicalService/my_web_view.dart @@ -8,8 +8,7 @@ class MyWebView extends StatelessWidget { final String title; final String selectedUrl; - final Completer _controller = - Completer(); + final Completer _controller = Completer(); MyWebView({ @required this.title, @@ -21,17 +20,12 @@ class MyWebView extends StatelessWidget { return AppScaffold( isShowAppBar: true, appBarTitle: title, - - body: - WebView( + body: WebView( initialUrl: selectedUrl, javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (WebViewController webViewController) { _controller.complete(webViewController); }, - ) - - - ); + )); } -} \ No newline at end of file +} diff --git a/lib/pages/AlHabibMedicalService/parking_page.dart b/lib/pages/AlHabibMedicalService/parking_page.dart index 82c390ea..19f06a56 100644 --- a/lib/pages/AlHabibMedicalService/parking_page.dart +++ b/lib/pages/AlHabibMedicalService/parking_page.dart @@ -8,7 +8,7 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:maps_launcher/maps_launcher.dart'; - +import 'package:diplomaticquarterapp/core/model/ImagesInfo.dart'; import '../../d_q_icons_icons.dart'; class ParkingPage extends StatelessWidget { @@ -19,6 +19,13 @@ class ParkingPage extends StatelessWidget { builder: (_, model, widget) => AppScaffold( isShowAppBar: true, appBarTitle: TranslationBase.of(context).parking, + description: TranslationBase.of(context).parkingDescription, + imagesInfo: [ + ImagesInfo( + imageAr: 'assets/images/bc_parking.png', + imageEn: 'assets/images/bc_parking.png', + isAsset: true) + ], body: SingleChildScrollView( padding: EdgeInsets.all(12), child: !model.isSavePark diff --git a/lib/pages/DrawerPages/family/my-family.dart b/lib/pages/DrawerPages/family/my-family.dart index baac5c63..e4e582bb 100644 --- a/lib/pages/DrawerPages/family/my-family.dart +++ b/lib/pages/DrawerPages/family/my-family.dart @@ -351,9 +351,21 @@ class _MyFamily extends State with TickerProviderStateMixin { Padding( padding: EdgeInsets.only(left: 10, right: 10), child: Row(children: [ - Expanded(flex: 3, child: AppText('Name')), - Expanded(flex: 1, child: AppText('Allow')), - Expanded(flex: 1, child: AppText('Reject')), + Expanded( + flex: 3, + child: AppText( + TranslationBase.of(context) + .name)), + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context) + .allow)), + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context) + .reject)), ])), Column( children: familyFileProvider.allSharedRecordsByStatusResponse.getAllSharedRecordsByStatusList.map((result) { @@ -487,8 +499,16 @@ class _MyFamily extends State with TickerProviderStateMixin { Padding( padding: EdgeInsets.only(left: 10, right: 10), child: Row(children: [ - Expanded(flex: 3, child: AppText('Name')), - Expanded(flex: 1, child: AppText('Delete')), + Expanded( + flex: 3, + child: AppText( + TranslationBase.of(context) + .name)), + Expanded( + flex: 1, + child: AppText( + TranslationBase.of(context) + .delete)), ])), Column( children: familyFileProvider.allSharedRecordsByStatusResponse.getAllSharedRecordsByStatusList.map((result) { diff --git a/lib/pages/ErService/NearestEr.dart b/lib/pages/ErService/NearestEr.dart index eaf0d4ef..cbafacce 100644 --- a/lib/pages/ErService/NearestEr.dart +++ b/lib/pages/ErService/NearestEr.dart @@ -31,6 +31,7 @@ class NearestEr extends StatelessWidget { : (model) => model.getProjectAvgERWaitingTimeOrders(), builder: (_, mode, widget) => AppScaffold( isShowAppBar: true, + isShowDecPage: false, appBarTitle: TranslationBase.of(context).NearestEr, baseViewModel: mode, body: mode.ProjectAvgERWaitingTimeModeList.length > 0 diff --git a/lib/pages/medical/balance/my_balance_page.dart b/lib/pages/medical/balance/my_balance_page.dart index 7639bb2f..f097bda5 100644 --- a/lib/pages/medical/balance/my_balance_page.dart +++ b/lib/pages/medical/balance/my_balance_page.dart @@ -8,7 +8,6 @@ import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:hexcolor/hexcolor.dart'; import 'advance_payment_page.dart'; @@ -105,12 +104,12 @@ class MyBalancePage extends StatelessWidget { ), ), bottomSheet: Container( - height: MediaQuery.of(context).size.height * 0.12, + // height: MediaQuery.of(context).size.height * 0.12, + height: 70.0, color: Colors.white, width: double.infinity, padding: EdgeInsets.all(12), child: SecondaryButton( - // color: Colors.grey[900], textColor: Colors.white, label: TranslationBase.of(context).createAdvancedPayment, onTap: () { diff --git a/lib/pages/medical/balance/new_text_Field.dart b/lib/pages/medical/balance/new_text_Field.dart index 3e20dc00..ec3eaf3b 100644 --- a/lib/pages/medical/balance/new_text_Field.dart +++ b/lib/pages/medical/balance/new_text_Field.dart @@ -42,39 +42,39 @@ final _mobileFormatter = NumberTextInputFormatter(); class NewTextFields extends StatefulWidget { NewTextFields( {Key key, - this.type, - this.hintText, - this.suffixIcon, - this.autoFocus, - this.onChanged, - this.initialValue, - this.minLines, - this.maxLines, - this.inputFormatters, - this.padding, - this.focus = false, - this.maxLengthEnforced = true, - this.suffixIconColor, - this.inputAction, - this.onSubmit, - this.keepPadding = true, - this.textCapitalization = TextCapitalization.none, - this.controller, - this.keyboardType, - this.validator, - this.borderOnlyError = false, - this.onSaved, - this.onSuffixTap, - this.readOnly: false, - this.maxLength, - this.prefixIcon, - this.bare = false, - this.onTap, - this.fontSize = 16.0, - this.fontWeight = FontWeight.w700, - this.autoValidate = false, - this.hintColor, - this.isEnabled = true,this.counterText=""}) + this.type, + this.hintText, + this.suffixIcon, + this.autoFocus, + this.onChanged, + this.initialValue, + this.minLines, + this.maxLines, + this.inputFormatters, + this.padding, + this.focus = false, + this.maxLengthEnforced = true, + this.suffixIconColor, + this.inputAction, + this.onSubmit, + this.keepPadding = true, + this.textCapitalization = TextCapitalization.none, + this.controller, + this.keyboardType, + this.validator, + this.borderOnlyError = false, + this.onSaved, + this.onSuffixTap, + this.readOnly: false, + this.maxLength, + this.prefixIcon, + this.bare = false, + this.onTap, + this.fontSize = 16.0, + this.fontWeight = FontWeight.w700, + this.autoValidate = false, + this.hintColor, + this.isEnabled = true,this.counterText=""}) : super(key: key); final String hintText; @@ -171,10 +171,10 @@ class _NewTextFieldsState extends State { textCapitalization: widget.textCapitalization, onFieldSubmitted: widget.inputAction == TextInputAction.next ? (widget.onSubmit != null - ? widget.onSubmit - : (val) { - _focusNode.nextFocus(); - }) + ? widget.onSubmit + : (val) { + _focusNode.nextFocus(); + }) : widget.onSubmit, textInputAction: widget.inputAction, minLines: widget.minLines ?? 1, @@ -194,15 +194,15 @@ class _NewTextFieldsState extends State { fontSize: widget.fontSize, fontWeight: widget.fontWeight), inputFormatters: widget.keyboardType == TextInputType.phone ? [ - WhitelistingTextInputFormatter.digitsOnly, - _mobileFormatter, - ] + WhitelistingTextInputFormatter.digitsOnly, + _mobileFormatter, + ] : widget.inputFormatters, decoration: InputDecoration( labelText: widget.hintText, counterText: widget.counterText, labelStyle: - TextStyle(color: Theme.of(context).textTheme.bodyText1.color), + TextStyle(color: Theme.of(context).textTheme.bodyText1.color), errorBorder: OutlineInputBorder( borderSide: BorderSide( color: Theme.of(context).errorColor.withOpacity(0.5), diff --git a/lib/pages/medical/my_trackers/my_trackers.dart b/lib/pages/medical/my_trackers/my_trackers.dart index 5e5c4527..c133c67a 100644 --- a/lib/pages/medical/my_trackers/my_trackers.dart +++ b/lib/pages/medical/my_trackers/my_trackers.dart @@ -15,6 +15,7 @@ class MyTrackers extends StatelessWidget { return AppScaffold( appBarTitle: TranslationBase.of(context).myTracker, isShowAppBar: true, + isShowDecPage: false, body: SingleChildScrollView( child: Container( padding: EdgeInsets.all(12), @@ -27,22 +28,24 @@ class MyTrackers extends StatelessWidget { children: [ Expanded( child: InkWell( - onTap: ()=> Navigator.push(context, FadePage(page: BloodSugarHomePage())), + onTap: () => Navigator.push(context, FadePage(page: BloodSugarHomePage())), child: Container( margin: EdgeInsets.all(5), - width: MediaQuery.of(context).size.width*0.35, - height:MediaQuery.of(context).size.width*0.35 , + width: MediaQuery.of(context).size.width * 0.35, + height: MediaQuery.of(context).size.width * 0.35, decoration: BoxDecoration( - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(8), - color: Colors.white - ), + shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(8), color: Colors.white), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.asset('assets/tracker/blood-suger.png',width: 60.0,), - SizedBox(height: 15,), + Image.asset( + 'assets/tracker/blood-suger.png', + width: 60.0, + ), + SizedBox( + height: 15, + ), Texts(TranslationBase.of(context).bloodSugar), ], ), @@ -51,22 +54,24 @@ class MyTrackers extends StatelessWidget { ), Expanded( child: InkWell( - onTap: ()=> Navigator.push(context, FadePage(page: BloodPressureHomePage())), + onTap: () => Navigator.push(context, FadePage(page: BloodPressureHomePage())), child: Container( margin: EdgeInsets.all(5), - width: MediaQuery.of(context).size.width*0.35, - height:MediaQuery.of(context).size.width*0.35 , + width: MediaQuery.of(context).size.width * 0.35, + height: MediaQuery.of(context).size.width * 0.35, decoration: BoxDecoration( - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(8), - color: Colors.white - ), + shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(8), color: Colors.white), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.asset('assets/tracker/blood-pressure.png',width: 60.0,), - SizedBox(height: 15,), + Image.asset( + 'assets/tracker/blood-pressure.png', + width: 60.0, + ), + SizedBox( + height: 15, + ), Texts(TranslationBase.of(context).bloodPressure), ], ), @@ -80,22 +85,24 @@ class MyTrackers extends StatelessWidget { children: [ Expanded( child: InkWell( - onTap: ()=> Navigator.push(context, FadePage(page: WeightHomePage())), + onTap: () => Navigator.push(context, FadePage(page: WeightHomePage())), child: Container( margin: EdgeInsets.all(5), - width: MediaQuery.of(context).size.width*0.35, - height:MediaQuery.of(context).size.width*0.35 , + width: MediaQuery.of(context).size.width * 0.35, + height: MediaQuery.of(context).size.width * 0.35, decoration: BoxDecoration( - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(8), - color: Colors.white - ), + shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(8), color: Colors.white), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Image.asset('assets/tracker/weight.png',width: 60.0,), - SizedBox(height: 15,), + Image.asset( + 'assets/tracker/weight.png', + width: 60.0, + ), + SizedBox( + height: 15, + ), Texts(TranslationBase.of(context).weight), ], ), diff --git a/lib/pages/medical/my_trackers/widget/MonthCurvedChartBloodPressure.dart b/lib/pages/medical/my_trackers/widget/MonthCurvedChartBloodPressure.dart index 135d0a95..ee7e00af 100644 --- a/lib/pages/medical/my_trackers/widget/MonthCurvedChartBloodPressure.dart +++ b/lib/pages/medical/my_trackers/widget/MonthCurvedChartBloodPressure.dart @@ -21,7 +21,7 @@ class MonthCurvedChartBloodPressure extends StatelessWidget { Widget build(BuildContext context) { getXaxix(); return AspectRatio( - aspectRatio: 1.1, + aspectRatio: 1.0, child: Container( decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(18)), @@ -137,19 +137,21 @@ class MonthCurvedChartBloodPressure extends StatelessWidget { ), leftTitles: SideTitles( showTitles: true, + interval:getMaxY() - getMinY() <=500?50:getMaxY() - getMinY() <=1000?100:200, + getTextStyles: (value) => const TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: 10, ), - getTitles: (value) { - if (value.toInt() == 0) - return '${value.toInt()}'; - else if (value.toInt() % horizontalInterval == 0) - return '${value.toInt()}'; - else - return ''; - }, + // getTitles: (value) { + // // if (value.toInt() == 0) + // // return '${value.toInt()}'; + // // else if (value.toInt() % horizontalInterval == 0) + // // return '${value.toInt()}'; + // // else + // return '${value.toInt()}'; + // }, margin: 12, ), ), diff --git a/lib/pages/medical/my_trackers/widget/MonthLineChartCurved.dart b/lib/pages/medical/my_trackers/widget/MonthLineChartCurved.dart index 607f3ab0..5ef71f5b 100644 --- a/lib/pages/medical/my_trackers/widget/MonthLineChartCurved.dart +++ b/lib/pages/medical/my_trackers/widget/MonthLineChartCurved.dart @@ -10,11 +10,7 @@ class MonthLineChartCurved extends StatelessWidget { final int indexes; final double horizontalInterval; - MonthLineChartCurved( - {this.title, - this.timeSeries, - this.indexes, - this.horizontalInterval = 15.0}); + MonthLineChartCurved({this.title, this.timeSeries, this.indexes, this.horizontalInterval = 15.0}); List xAxixs = List(); List yAxixs = List(); @@ -40,8 +36,7 @@ class MonthLineChartCurved extends StatelessWidget { ), Text( title, - style: TextStyle( - color: Colors.black, fontSize: 15, letterSpacing: 2), + style: TextStyle(color: Colors.black, fontSize: 15, letterSpacing: 2), textAlign: TextAlign.center, ), SizedBox( @@ -49,8 +44,7 @@ class MonthLineChartCurved extends StatelessWidget { ), Expanded( child: Padding( - padding: const EdgeInsets.only( - right: 18.0, left: 16.0, top: 15, bottom: 15), + padding: const EdgeInsets.only(right: 18.0, left: 16.0, top: 15, bottom: 15), child: LineChart( sampleData1(context), swapAnimationDuration: const Duration(milliseconds: 250), @@ -97,10 +91,7 @@ class MonthLineChartCurved extends StatelessWidget { handleBuiltInTouches: true, ), gridData: FlGridData( - horizontalInterval: horizontalInterval, - show: true, - drawVerticalLine: true, - drawHorizontalLine: true), + horizontalInterval: horizontalInterval, show: true, drawVerticalLine: true, drawHorizontalLine: true), titlesData: FlTitlesData( bottomTitles: SideTitles( showTitles: true, @@ -120,14 +111,16 @@ class MonthLineChartCurved extends StatelessWidget { fontWeight: FontWeight.bold, fontSize: 10, ), - getTitles: (value) { - if (value.toInt() == 0) - return '${value.toInt()}'; - else if (value.toInt() % horizontalInterval == 0) - return '${value.toInt()}'; - else - return ''; - }, + interval:getMaxY() - getMinY() <=500?50:getMaxY() - getMinY() <=1000?100:200, + + // getTitles: (value) { + // if (value.toInt() == 0) + // return '${value.toInt()}'; + // else if (value.toInt() % horizontalInterval == 0) + // return '${value.toInt()}'; + // else + // return ''; + // }, margin: 12, ), ), @@ -180,6 +173,9 @@ class MonthLineChartCurved extends StatelessWidget { List getData(context) { List spots = List(); + if (timeSeries.length == 0) { + spots.add(FlSpot(0, 0)); + } for (int index = 0; index < timeSeries.length; index++) { spots.add(FlSpot(index.toDouble(), timeSeries[index].sales)); } diff --git a/lib/pages/medical/prescriptions/pharmacy_for_prescriptions_page.dart b/lib/pages/medical/prescriptions/pharmacy_for_prescriptions_page.dart index 96227fba..8224e61d 100644 --- a/lib/pages/medical/prescriptions/pharmacy_for_prescriptions_page.dart +++ b/lib/pages/medical/prescriptions/pharmacy_for_prescriptions_page.dart @@ -10,92 +10,94 @@ import 'package:maps_launcher/maps_launcher.dart'; import 'package:url_launcher/url_launcher.dart'; class PharmacyForPrescriptionsPage extends StatelessWidget { - final PrescriptionReport prescriptionReport; + final itemID; - PharmacyForPrescriptionsPage({Key key, this.prescriptionReport}); + PharmacyForPrescriptionsPage({Key key, this.itemID}); @override Widget build(BuildContext context) { - return BaseView( - onModelReady: (model) => model.getListPharmacyForPrescriptions(itemId: prescriptionReport.itemID), - builder: (_, model, widget) => AppScaffold( - isShowAppBar: true, - appBarTitle: TranslationBase.of(context).availability, - baseViewModel: model, - body: ListView.builder( - itemBuilder: (context, index) => Container( - width: double.infinity, - margin: EdgeInsets.only(top: 10, left: 10, right: 10), - padding: EdgeInsets.all(8.0), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all( - Radius.circular(10.0), - ), - border: Border.all(color: Colors.grey[200], width: 0.5), + return BaseView( + onModelReady: (model) => + model.getListPharmacyForPrescriptions(itemId: itemID), + builder: (_, model, widget) => AppScaffold( + isShowAppBar: true, + appBarTitle: TranslationBase.of(context).availability, + baseViewModel: model, + body: ListView.builder( + itemBuilder: (context, index) => Container( + width: double.infinity, + margin: EdgeInsets.only(top: 10, left: 10, right: 10), + padding: EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all( + Radius.circular(10.0), ), - child: Row( - children: [ - ClipRRect( - borderRadius: BorderRadius.all(Radius.circular(5)), - child: Image.network( - model.pharmacyPrescriptionsList[index].projectImageURL, - fit: BoxFit.cover, - width: 60, - height: 70, - ), + border: Border.all(color: Colors.grey[200], width: 0.5), + ), + child: Row( + children: [ + ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(5)), + child: Image.network( + model.pharmacyPrescriptionsList[index].projectImageURL, + fit: BoxFit.cover, + width: 60, + height: 70, ), - Expanded( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Texts(model.pharmacyPrescriptionsList[index] - .locationDescription), - SizedBox( - height: 5, - ), - Texts(model.pharmacyPrescriptionsList[index].cityName), - ], - ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Texts(model.pharmacyPrescriptionsList[index] + .locationDescription), + SizedBox( + height: 5, + ), + Texts(model.pharmacyPrescriptionsList[index].cityName), + ], ), ), - InkWell( - onTap: () { - MapsLauncher.launchCoordinates( - double.parse( - model.pharmacyPrescriptionsList[index].latitude), - double.parse( - model.pharmacyPrescriptionsList[index].longitude)); - }, + ), + InkWell( + onTap: () { + MapsLauncher.launchCoordinates( + double.parse( + model.pharmacyPrescriptionsList[index].latitude), + double.parse( + model.pharmacyPrescriptionsList[index].longitude)); + }, + child: Icon( + Icons.pin_drop, + size: 18, + color: Colors.red[900], + ), + ), + SizedBox( + width: 15, + ), + InkWell( + onTap: Feedback.wrapForTap(() { + launch( + "tel://${model.pharmacyPrescriptionsList[index].phoneNumber}"); + }, context), + child: Container( child: Icon( - Icons.pin_drop, + Icons.call, size: 18, color: Colors.red[900], ), ), - SizedBox( - width: 15, - ), - InkWell( - onTap: Feedback.wrapForTap((){ - launch("tel://${model.pharmacyPrescriptionsList[index].phoneNumber}"); - },context), - child: Container( - child: Icon( - Icons.call, - size: 18, - color: Colors.red[900], - ), - ), - ) - ], - ), + ) + ], ), - itemCount: model.pharmacyPrescriptionsList.length, ), + itemCount: model.pharmacyPrescriptionsList.length, ), - ); + ), + ); } } diff --git a/lib/pages/medical/prescriptions/prescription_details_page.dart b/lib/pages/medical/prescriptions/prescription_details_page.dart index 72e830cf..218d7ac6 100644 --- a/lib/pages/medical/prescriptions/prescription_details_page.dart +++ b/lib/pages/medical/prescriptions/prescription_details_page.dart @@ -53,7 +53,7 @@ class PrescriptionDetailsPage extends StatelessWidget { child: Texts( prescriptionReport.itemDescription.isNotEmpty ? prescriptionReport.itemDescription - : prescriptionReport.itemDescriptionN), + : prescriptionReport.itemDescriptionN ?? ''), ), ), ) @@ -70,7 +70,7 @@ class PrescriptionDetailsPage extends StatelessWidget { context, FadePage( page: PharmacyForPrescriptionsPage( - prescriptionReport: prescriptionReport), + itemID: prescriptionReport.itemID), ), ), child: Center( @@ -118,14 +118,19 @@ class PrescriptionDetailsPage extends StatelessWidget { height: 40, width: double.infinity, child: Center( - child: Texts(TranslationBase.of(context).route, fontSize: 14,))), + child: Texts( + TranslationBase.of(context).route, + fontSize: 14, + ))), Container( color: Colors.white, height: 40, width: double.infinity, child: Center( - child: - Texts(TranslationBase.of(context).frequency, fontSize: 14,))), + child: Texts( + TranslationBase.of(context).frequency, + fontSize: 14, + ))), Container( color: Colors.white, height: 40, @@ -133,14 +138,18 @@ class PrescriptionDetailsPage extends StatelessWidget { padding: EdgeInsets.symmetric(horizontal: 4), child: Center( child: Texts( - "${TranslationBase.of(context).dailyDoses}", fontSize: 14,))), + "${TranslationBase.of(context).dailyDoses}", + fontSize: 14, + ))), Container( color: Colors.white, height: 40, width: double.infinity, child: Center( - child: - Texts(TranslationBase.of(context).duration, fontSize: 14,))), + child: Texts( + TranslationBase.of(context).duration, + fontSize: 14, + ))), ], ), TableRow( @@ -149,8 +158,8 @@ class PrescriptionDetailsPage extends StatelessWidget { color: Colors.white, height: 50, width: double.infinity, - child: - Center(child: Text(prescriptionReport.routeN))), + child: Center( + child: Text(prescriptionReport.routeN ?? ''))), Container( color: Colors.white, height: 50, diff --git a/lib/pages/medical/prescriptions/prescription_items_page.dart b/lib/pages/medical/prescriptions/prescription_items_page.dart index c6581493..e47b8ea7 100644 --- a/lib/pages/medical/prescriptions/prescription_items_page.dart +++ b/lib/pages/medical/prescriptions/prescription_items_page.dart @@ -4,6 +4,7 @@ import 'package:diplomaticquarterapp/core/model/prescriptions/prescription_repor import 'package:diplomaticquarterapp/core/viewModels/medical/prescriptions_view_model.dart'; import 'package:diplomaticquarterapp/core/viewModels/project_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/pages/medical/prescriptions/prescription_details_inp.dart'; import 'package:diplomaticquarterapp/pages/medical/prescriptions/prescription_details_page.dart'; import 'package:diplomaticquarterapp/uitl/translations_delegate_base.dart'; import 'package:diplomaticquarterapp/widgets/buttons/button.dart'; @@ -24,7 +25,7 @@ class PrescriptionItemsPage extends StatelessWidget { //TODO @override Widget build(BuildContext context) { - ProjectViewModel projectViewModel = Provider.of(context); + ProjectViewModel projectViewModel = Provider.of(context); return BaseView( onModelReady: (model) => model.getPrescriptionReport(prescriptions: prescriptions), @@ -38,14 +39,14 @@ class PrescriptionItemsPage extends StatelessWidget { children: [ if (!prescriptions.isInOutPatient) ...List.generate( - model.prescriptionReportList.length, + model.prescriptionReportListINP.length, (index) => InkWell( onTap: () => Navigator.push( context, FadePage( - page: PrescriptionDetailsPage( + page: PrescriptionDetailsPageINP( prescriptionReport: - model.prescriptionReportList[index], + model.prescriptionReportListINP[index], ), ), ), @@ -68,7 +69,7 @@ class PrescriptionItemsPage extends StatelessWidget { borderRadius: BorderRadius.all(Radius.circular(5)), child: Image.network( - model.prescriptionReportList[index] + model.prescriptionReportListINP[index] .imageSRCUrl, fit: BoxFit.cover, width: 60, @@ -83,13 +84,17 @@ class PrescriptionItemsPage extends StatelessWidget { padding: const EdgeInsets.all(8.0), child: Center( child: Texts(model - .prescriptionReportList[index] + .prescriptionReportListINP[index] .itemDescription .isNotEmpty - ? model.prescriptionReportList[index] + ? model + .prescriptionReportListINP[index] .itemDescription - : model.prescriptionReportList[index] - .itemDescriptionN)), + : model + .prescriptionReportListINP[ + index] + .itemDescriptionN ?? + '')), )), Icon( Icons.arrow_forward_ios, @@ -163,7 +168,12 @@ class PrescriptionItemsPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Texts(model.prescriptionReportEnhList[index] - .itemDescription), + .itemDescription.isNotEmpty + ? model.prescriptionReportEnhList[index] + .itemDescription + : model.prescriptionReportEnhList[index] + .itemDescriptionN ?? + ''), ], ), ), @@ -188,36 +198,37 @@ class PrescriptionItemsPage extends StatelessWidget { child: Column( children: [ Divider(), - if(projectViewModel.havePrivilege(13)) - Container( - width: MediaQuery.of(context).size.width * 0.8, - child: Button( - label: TranslationBase.of(context).sendCopy, - onTap: () { - showConfirmMessage(context,model); - }, - loading: model.state == ViewState.BusyLocal, - ), - ), + if (projectViewModel.havePrivilege(13)) Container( - width: MediaQuery.of(context).size.width * 0.8, - child: Button( - label: TranslationBase.of(context).resendOrder, - backgroundColor: Colors.green[800], - onTap: (){ - - Navigator.push( - context, - FadePage( - page: PrescriptionDeliveryAddressPage( - prescriptions: prescriptions, - prescriptionReportList: model.prescriptionReportList, - prescriptionReportEnhList: model.prescriptionReportEnhList, - ), + width: MediaQuery.of(context).size.width * 0.8, + child: Button( + label: TranslationBase.of(context).sendCopy, + onTap: () { + showConfirmMessage(context, model); + }, + loading: model.state == ViewState.BusyLocal, + ), + ), + Container( + width: MediaQuery.of(context).size.width * 0.8, + child: Button( + label: TranslationBase.of(context).resendOrder, + backgroundColor: Colors.green[800], + onTap: () { + Navigator.push( + context, + FadePage( + page: PrescriptionDeliveryAddressPage( + prescriptions: prescriptions, + prescriptionReportList: + model.prescriptionReportList, + prescriptionReportEnhList: + model.prescriptionReportEnhList, ), - ); - }, - )) + ), + ); + }, + )) ], ), ), @@ -236,6 +247,7 @@ class PrescriptionItemsPage extends StatelessWidget { patientID: prescriptions.patientID, clinicName: prescriptions.companyName, doctorName: prescriptions.doctorName, + doctorID: prescriptions.doctorID, mes: TranslationBase.of(context).sendSuc, projectID: prescriptions.projectID); }, diff --git a/lib/pages/medical/reports/monthly_reports.dart b/lib/pages/medical/reports/monthly_reports.dart index 4484bd5f..80f6ac76 100644 --- a/lib/pages/medical/reports/monthly_reports.dart +++ b/lib/pages/medical/reports/monthly_reports.dart @@ -19,15 +19,24 @@ class MonthlyReportsPage extends StatefulWidget { } class _MonthlyReportsPageState extends State { - bool isAgree = false; - bool isSummary = false; - String email = ""; + bool isAgree; + bool isSummary; + String email; final formKey = GlobalKey(); @override Widget build(BuildContext context) { - return BaseView( - builder: (_, model, w) => AppScaffold( + return BaseView(builder: (_, model, w) { + if (isSummary == null) { + isSummary = model.receiveHealthSummaryReport; + } + if (isAgree == null) { + isAgree = model.receiveHealthSummaryReport; + } + if (email == null) { + email = model?.user?.emailAddress ?? ""; + } + return AppScaffold( isShowAppBar: true, appBarTitle: TranslationBase.of(context).monthlyReports, body: SingleChildScrollView( @@ -41,15 +50,10 @@ class _MonthlyReportsPageState extends State { Container( padding: EdgeInsets.all(9), height: 55, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(8)), - shape: BoxShape.rectangle, - border: Border.all(color: Colors.grey)), + decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(8)), shape: BoxShape.rectangle, border: Border.all(color: Colors.grey)), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Texts( TranslationBase.of(context).patientHealthSummaryReport, bold: true, @@ -62,12 +66,12 @@ class _MonthlyReportsPageState extends State { setState(() { isSummary = !isSummary; }); - if(!isSummary) { + if (!isSummary) { GifLoaderDialogUtils.showMyDialog(context); - await model.updatePatientHealthSummaryReport( - message: TranslationBase - .of(context) - .updateSuccessfully, isSummary: isSummary); + await model.updatePatientHealthSummaryReport(message: TranslationBase.of(context).updateSuccessfully, isSummary: isSummary); + model.receiveHealthSummaryReport = isSummary; + isAgree = isSummary; + model.user.emailAddress = ""; GifLoaderDialogUtils.hideDialog(context); } }, @@ -80,11 +84,11 @@ class _MonthlyReportsPageState extends State { ), Container( margin: EdgeInsets.all(8), - child: TextFields( + child: TextFields( fillColor: Colors.red, hintText: 'email@email.com', fontSize: 20, - initialValue: model.user.emailAddress, + initialValue: email, fontWeight: FontWeight.w600, onChanged: (text) { email = text; @@ -111,8 +115,7 @@ class _MonthlyReportsPageState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( - child: Texts(TranslationBase.of(context) - .toViewTheTermsAndConditions), + child: Texts(TranslationBase.of(context).toViewTheTermsAndConditions), ), InkWell( onTap: () { @@ -156,19 +159,15 @@ class _MonthlyReportsPageState extends State { child: SecondaryButton( textColor: Colors.white, label: TranslationBase.of(context).save, - disabled: (!isAgree || !isSummary ), + disabled: (!isAgree || !isSummary), onTap: () async { final form = formKey.currentState; if (form.validate()) { GifLoaderDialogUtils.showMyDialog(context); await model.updatePatientHealthSummaryReport( - message: TranslationBase - .of(context) - .updateSuccessfully, - isSummary: isSummary, - isUpdateEmail: true, - email: email.isNotEmpty ? email : model.user - .emailAddress); + message: TranslationBase.of(context).updateSuccessfully, isSummary: isSummary, isUpdateEmail: true, email: email.isNotEmpty ? email : model.user.emailAddress); + model.receiveHealthSummaryReport = isSummary; + model.user.emailAddress = email.isNotEmpty ? email : model.user.emailAddress; GifLoaderDialogUtils.hideDialog(context); } }, @@ -177,8 +176,7 @@ class _MonthlyReportsPageState extends State { Padding( padding: const EdgeInsets.all(5.0), child: Texts( - TranslationBase.of(context) - .instructionAgree, + TranslationBase.of(context).instructionAgree, fontWeight: FontWeight.normal, ), ), @@ -191,7 +189,7 @@ class _MonthlyReportsPageState extends State { ), ), ), - ), - ); + ); + }); } } diff --git a/lib/pages/vaccine/my_vaccines_screen.dart b/lib/pages/vaccine/my_vaccines_screen.dart index fb723a1f..27ce8399 100644 --- a/lib/pages/vaccine/my_vaccines_screen.dart +++ b/lib/pages/vaccine/my_vaccines_screen.dart @@ -30,173 +30,190 @@ class _MyVaccinesState extends State { onModelReady: (model) => model.getVaccine(), builder: (BuildContext context, VaccineViewModel model, Widget child) => AppScaffold( - isShowAppBar: true, - appBarTitle: TranslationBase.of(context).myVaccines, - baseViewModel: model, - body: Container( - margin: EdgeInsets.only( - left: SizeConfig.screenWidth * 0.004, - right: SizeConfig.screenWidth * 0.004, - top: SizeConfig.screenWidth * 0.04, - ), - child: Column( - children: [ - RoundedContainer( - backgroundColor: Colors.white, - child: ExpansionTile( - title: Container( - height: 65.0, - child: Text('2018'), - ), - children: [ - Container( - child: ListView.builder( - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: model.vaccineList == null - ? 0 - : model.vaccineList.length, - itemBuilder: (BuildContext context, int index) { - return Column( - children: [ - RoundedContainer( - child: Column( - children: [ - Row( + isShowAppBar: true, + baseViewModel: model, + appBarTitle: TranslationBase.of(context).myVaccines, + body: Container( + margin: EdgeInsets.only( + left: SizeConfig.screenWidth * 0.004, + right: SizeConfig.screenWidth * 0.004, + top: SizeConfig.screenWidth * 0.04, + ), + child: Column( + children: [ + RoundedContainer( + backgroundColor: Colors.white, + child: ExpansionTile( + title: Container( + height: 65.0, + child: Text('2018'), + ), + children: [ + Container( + child: ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: model.vaccineList == null + ? 0 + : model.vaccineList.length, + itemBuilder: (BuildContext context, int index) { + return Column( + children: [ + RoundedContainer( + child: Column( children: [ - Expanded( - child: Column( - children: [ - Padding( - padding: EdgeInsets.symmetric( - horizontal: 20.0, - vertical: 20.0), - child: Image.network( - model.vaccineList[index] - .doctorImageURL, - height: SizeConfig + Row( + children: [ + Expanded( + child: Column( + children: [ + Padding( + padding: EdgeInsets + .symmetric( + horizontal: + 20.0, + vertical: 20.0), + child: Image.network( + model + .vaccineList[ + index] + .doctorImageURL, + height: SizeConfig .imageSizeMultiplier * - 23, - width: SizeConfig + 23, + width: SizeConfig .imageSizeMultiplier * - 20, - fit: BoxFit.fill, - ), + 20, + fit: BoxFit.fill, + ), + ), + ], ), - ], - ), - flex: 2, - ), - Expanded( - child: Container( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - model.vaccineList[index] + flex: 2, + ), + Expanded( + child: Container( + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .start, + children: [ + Text( + model + .vaccineList[ + index] .doctorTitle + - model.vaccineList[index] - .doctorName, - style: TextStyle( - fontWeight: + model + .vaccineList[ + index] + .doctorName, + style: TextStyle( + fontWeight: FontWeight.w900, - fontSize: 16.6, - ), - ), - SizedBox(height: 7.0), - Text( - model.vaccineList[index] - .projectName, - style: TextStyle( - fontSize: 17.0, - letterSpacing: 0.5, - ), - ), - SizedBox(height: 7.0), - Text( - model.vaccineList[index] - .vaccineName, - style: TextStyle( - fontSize: 17.0, - ), - ), - SizedBox(height: 7.0), - Text( - 'Date Taken ' + - convertDateFormat(model - .vaccineList[index] - .invoiceDate), - style: TextStyle( - fontSize: 17.0), + fontSize: 16.6, + ), + ), + SizedBox(height: 7.0), + Text( + model + .vaccineList[ + index] + .projectName, + style: TextStyle( + fontSize: 17.0, + letterSpacing: 0.5, + ), + ), + SizedBox(height: 7.0), + Text( + model + .vaccineList[ + index] + .vaccineName, + style: TextStyle( + fontSize: 17.0, + ), + ), + SizedBox(height: 7.0), + Text( + 'Date Taken ' + + convertDateFormat(model + .vaccineList[ + index] + .invoiceDate), + style: TextStyle( + fontSize: 17.0), + ), + ], ), - ], + ), + flex: 5, ), - ), - flex: 5, + ], ), ], ), - ], - ), - ), - ], - ); - }), - ) - ], - ), - ), - // SpaceBetweenTexts(space: 165.0), - ], - ), - ), - bottomSheet: Container( - color: Theme.of(context).scaffoldBackgroundColor, - padding: EdgeInsets.all(12), - height: MediaQuery.of(context).size.height * 0.25, - width: double.infinity, - child: Column( - children: [ - Divider( - height: 2, - thickness: 1, - ), - SizedBox( - height: 6, - ), - Container( - width: double.infinity, - // height: 80.0, - child: Button( - disabled: true, - label: TranslationBase.of(context).checkVaccineAvailability, - backgroundColor: Color(0xff9EA3A4), - onTap: () => Navigator.push( - context, FadePage(page: MyVaccinesItemPage())), - ), + ), + ], + ); + }), + ) + ], + ), + ), + // SpaceBetweenTexts(space: 165.0), + ], ), - if (projectViewModel.havePrivilege(27)) - Container( - width: double.infinity, - // height: 80.0, - child: SecondaryButton( - label: TranslationBase.of(context).sendEmail, - color: Color(0xffF62426), - textColor: Colors.white, - disabled: model.vaccineList.length == 0, - loading: model.state == ViewState.BusyLocal, - onTap: () async { - model.sendEmail( - message: TranslationBase.of(context) - .emailSentSuccessfully); - }, + ), + bottomSheet: model.state == ViewState.Busy?Container(height: 0,): model.vaccineList.length > 0 + ? Container( + color: Theme.of(context).scaffoldBackgroundColor, + padding: EdgeInsets.all(12), + height: MediaQuery.of(context).size.height * 0.25, + width: double.infinity, + child: Column( + children: [ + Divider( + height: 2, + thickness: 1, + ), + SizedBox( + height: 6, ), - ), - ], + Container( + width: double.infinity, + // height: 80.0, + child: Button( + disabled: true, + label: TranslationBase.of(context) + .checkVaccineAvailability, + backgroundColor: Color(0xff9EA3A4), + onTap: () => Navigator.push( + context, FadePage(page: MyVaccinesItemPage())), + ), + ), + if (projectViewModel.havePrivilege(27)) + Container( + width: double.infinity, + // height: 80.0, + child: SecondaryButton( + label: TranslationBase.of(context).sendEmail, + color: Color(0xffF62426), + textColor: Colors.white, + disabled: model.vaccineList.length == 0, + loading: model.state == ViewState.BusyLocal, + onTap: () async { + model.sendEmail( + message: TranslationBase.of(context) + .emailSentSuccessfully); + }, + ), + ), + ], + ), + ) + : Container(height: 0,), ), - ), - ), ); } diff --git a/lib/services/permission/permission_service.dart b/lib/services/permission/permission_service.dart index ea408ce2..d88ec599 100644 --- a/lib/services/permission/permission_service.dart +++ b/lib/services/permission/permission_service.dart @@ -10,9 +10,12 @@ import 'package:flutter/services.dart'; import 'package:localstorage/localstorage.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:vibration/vibration.dart'; +import 'package:geolocator/geolocator.dart' as geo; +// import 'package:open_settings/open_settings.dart'; + class PermissionService extends BaseService { final LocalStorage storage = new LocalStorage("permission"); - + geo.LocationPermission locationPermission; AppGlobal appGlobal = new AppGlobal(); setVibrationPermission(flag) async { @@ -20,23 +23,24 @@ class PermissionService extends BaseService { } isVibrationEnabled() { - return (storage.getItem('isVibration') ==null) || (storage.getItem('isVibration')) ==false ? false :true; + return (storage.getItem('isVibration') == null) || + (storage.getItem('isVibration')) == false + ? false + : true; } - vibrate(callback, context) async{ - if (callback == null) - return null; - if(isVibrationEnabled() ==true){ - if (await Vibration.hasVibrator()) { - Vibration.vibrate(duration: 100); - callback(); + vibrate(callback, context) async { + if (callback == null) return null; + if (isVibrationEnabled() == true) { + if (await Vibration.hasVibrator()) { + Vibration.vibrate(duration: 100); + callback(); } - }else{ + } else { callback(); } } - setTheme(flag) async { storage.setItem('isTheme', flag); } @@ -44,23 +48,36 @@ class PermissionService extends BaseService { isThemeEnabled() { return storage.getItem('isTheme'); } - cameraPermission() async{ - Map statuses = await [ - Permission.camera, - ].request(); - } - isCameraEnabled() async{ - print(await Permission.camera.status); - return await Permission.camera.status == PermissionStatus.granted ? true : false; + + cameraPermission() async { + Map statuses = await [ + Permission.camera, + ].request(); + } + + isCameraEnabled() async { + return await Permission.camera.isGranted; } - setCameraLocationPermission(context) async{ + + setCameraLocationPermission(context) async { Navigator.pop(context); openAppSettings(); } - isLocationEnabled() async{ - return await Permission.location.status == PermissionStatus.granted ? true : false; + + isLocationEnabled() async { + var permission = await geo.Geolocator.checkPermission(); + if (permission == geo.LocationPermission.denied) { + return false; + } else { + return true; + } } - openSettings() async{ + + openSettings() async { openAppSettings(); } + + openAccessbility() { + // OpenSettings.openAppSetting(); + } } diff --git a/lib/services/pharmacy_services/pharmacyAddress_service.dart b/lib/services/pharmacy_services/pharmacyAddress_service.dart index 592359ca..2909f18d 100644 --- a/lib/services/pharmacy_services/pharmacyAddress_service.dart +++ b/lib/services/pharmacy_services/pharmacyAddress_service.dart @@ -89,7 +89,7 @@ class PharmacyAddressService extends BaseService { Map body = Map(); body["customer"] = customerObject; - await baseAppClient.post("$url", onSuccess: (response, statusCode) async { + await baseAppClient.postPharmacy("$url", onSuccess: (response, statusCode) async { addresses.clear(); response['customers'][0]['addresses'].forEach((item) { addresses.add(Addresses.fromJson(item)); diff --git a/lib/widgets/nfc/nfc_reader_sheet.dart b/lib/widgets/nfc/nfc_reader_sheet.dart new file mode 100644 index 00000000..067c0c9a --- /dev/null +++ b/lib/widgets/nfc/nfc_reader_sheet.dart @@ -0,0 +1,196 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:nfc_in_flutter/nfc_in_flutter.dart'; + +void showNfcReader(BuildContext context, {Function onNcfScan}) { + showModalBottomSheet( + context: context, + enableDrag: false, + isDismissible: false, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(12), topRight: Radius.circular(12)), + ), + backgroundColor: Colors.white, + builder: (context) { + return NfcLayout( + onNcfScan: onNcfScan, + ); + }); +} + +class NfcLayout extends StatefulWidget { + Function onNcfScan; + + NfcLayout({this.onNcfScan}); + + @override + _NfcLayoutState createState() => _NfcLayoutState(); +} + +class _NfcLayoutState extends State { + StreamSubscription _stream; + bool _reading = false; + Widget mainWidget; + String nfcId; + + @override + void initState() { + super.initState(); + + setState(() { + // _reading = true; + // Start reading using NFC.readNDEF() + _stream = NFC + .readNDEF( + once: false, + throwOnUserCancel: false, + readerMode: NFCDispatchReaderMode()) + .listen((NDEFMessage message) { + setState(() { + _reading = true; + mainWidget = doneNfc(); + }); + Future.delayed(const Duration(milliseconds: 500), () { + _stream?.cancel(); + widget.onNcfScan(nfcId); + Navigator.pop(context); + }); + print("read NDEF id: ${message.id}"); + // widget.onNcfScan(message.id); + nfcId = message.id; + }, onError: (e) { + // Check error handling guide below + }); + }); + } + + @override + Widget build(BuildContext context) { + (mainWidget == null && !_reading) + ? mainWidget = scanNfc() + : mainWidget = doneNfc(); + return AnimatedSwitcher( + duration: Duration(milliseconds: 500), child: mainWidget); + } + + Widget scanNfc() { + return Container( + key: ValueKey(1), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 30, + ), + Text( + "Ready To Scan", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + ), + ), + SizedBox( + height: 30, + ), + Image.asset( + "assets/images/nfc/ic_nfc.png", + height: MediaQuery.of(context).size.width / 3, + ), + SizedBox( + height: 30, + ), + Text( + "Approach an NFC Tag", + style: TextStyle( + fontSize: 18, + ), + ), + SizedBox( + height: 30, + ), + ButtonTheme( + minWidth: MediaQuery.of(context).size.width / 1.2, + height: 45.0, + buttonColor: Colors.grey[300], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + child: RaisedButton( + onPressed: () { + _stream?.cancel(); + Navigator.pop(context); + }, + child: Text("CANCEL"), + ), + ), + SizedBox( + height: 30, + ), + ], + ), + ); + } + + Widget doneNfc() { + return Container( + key: ValueKey(2), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 30, + ), + Text( + "Successfully Scanned", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 24, + ), + ), + SizedBox( + height: 30, + ), + Image.asset( + "assets/images/nfc/ic_done.png", + height: MediaQuery.of(context).size.width / 3, + ), + SizedBox( + height: 30, + ), + Text( + "Approach an NFC Tag", + style: TextStyle( + fontSize: 18, + ), + ), + SizedBox( + height: 30, + ), + ButtonTheme( + minWidth: MediaQuery.of(context).size.width / 1.2, + height: 45.0, + buttonColor: Colors.grey[300], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(6), + ), + child: RaisedButton( + // onPressed: () { + // _stream?.cancel(); + // widget.onNcfScan(nfcId); + // Navigator.pop(context); + // }, + onPressed: null, + + child: Text("DONE"), + ), + ), + SizedBox( + height: 30, + ), + ], + ), + ); + } +} diff --git a/lib/widgets/others/not_auh_page.dart b/lib/widgets/others/not_auh_page.dart index d247c9f5..9bef623b 100644 --- a/lib/widgets/others/not_auh_page.dart +++ b/lib/widgets/others/not_auh_page.dart @@ -71,6 +71,34 @@ class _NotAutPageState extends State { widget.description, style: TextStyle(fontSize: 14, fontFamily: "Poppins", fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.56, height: 21 / 14), ), + SizedBox( + height: 14, + ), + if (!projectViewModel.isInternetConnection) + Center( + child: SizedBox( + height: MediaQuery.of(context).size.height * 0.55, + width: MediaQuery.of(context).size.width * 0.50, + child: Image.asset(projectViewModel.isArabic ? 'assets/images/Wifi-AR.png' : 'assets/images/wifi-EN.png'), + ), + ), + if (projectViewModel.isInternetConnection && widget.imagesInfo != null) + CarouselSlider( + items: widget.imagesInfo.map((image) { + return Builder( + builder: (BuildContext context) { + return SizedBox( + width: MediaQuery.of(context).size.width * 0.50, + child: image.isAsset ? Image.asset(projectViewModel.isArabic ? image.imageAr : image.imageEn) : Image.network(projectViewModel.isArabic ? image.imageAr : image.imageEn)); + }, + ); + }).toList(), + options: CarouselOptions( + height: MediaQuery.of(context).size.height * 0.55, + autoPlay: widget.imagesInfo.length > 1, + viewportFraction: 1.0, + ), + ), ], ), ), diff --git a/pubspec.yaml b/pubspec.yaml index f7064e86..9c1d1042 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,7 +15,7 @@ dependencies: # Localizations flutter_localizations: sdk: flutter - intl: ^0.16.1 + intl: ^0.16.0 # web view webview_flutter: ^0.3.24 # http client @@ -52,6 +52,7 @@ dependencies: shared_preferences: ^0.5.8 flutter_flexible_toast: ^0.1.4 firebase_messaging: ^7.0.3 + firebase_analytics: ^6.3.0 cloud_firestore: ^0.14.3 android_intent: ^0.3.7+7 # Progress bar @@ -162,7 +163,7 @@ dependencies: # recase: ^3.0.0 wakelock: ^0.1.4 after_layout: ^1.0.7 - twilio_programmable_video: ^0.5.0+3 + twilio_programmable_video: ^0.6.2 cached_network_image: ^2.4.1 flutter_tts: path: flutter_tts-voice_enhancement @@ -171,12 +172,13 @@ dependencies: wifi: ^0.1.5 vibration: ^1.7.3 + nfc_in_flutter: ^2.0.5 speech_to_text: path: speech_to_text badges: ^1.1.4 - +# open_settings: ^2.0.1 # Dep by Zohaib shimmer: ^1.1.2 carousel_slider: ^2.3.1 @@ -217,10 +219,14 @@ flutter: - assets/images/svg/ - assets/tracker/ - assets/images/AlHabibMedicalService/ + - assets/images/AlHabibMedicalService/health_calculator/ - assets/images/pharmacy_module/ - assets/images/gif/ - assets/images/pharmacy_module/payment/ - assets/images/pharmacy_module/lakum/ + - assets/images/nfc/ + - assets/payment_options/ + - assets/images/new/ - assets/images/new/bottom_nav/ - assets/images/new/services/ diff --git a/speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r b/speech_to_text_/example/assets/sounds/speech_to_text_cancel.m4r new file mode 100644 index 0000000000000000000000000000000000000000..ccb3afe392f563a0c8205265f8953c5cb801794a GIT binary patch literal 14006 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 F{x65=vylJ* literal 0 HcmV?d00001 diff --git a/speech_to_text_/example/pubspec.yaml b/speech_to_text_/example/pubspec.yaml new file mode 100644 index 00000000..d2bfcff7 --- /dev/null +++ b/speech_to_text_/example/pubspec.yaml @@ -0,0 +1,33 @@ +name: speech_to_text_example +description: Demonstrates how to use the speech_to_text plugin. +version: 1.1.0 +publish_to: 'none' + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + + cupertino_icons: ^0.1.2 + permission_handler: ^5.0.1+1 + + provider: + +dev_dependencies: + flutter_test: + sdk: flutter + + speech_to_text: + path: ../ + +# The following section is specific to Flutter. +flutter: + + uses-material-design: true + + assets: + - assets/sounds/speech_to_text_listening.m4r + - assets/sounds/speech_to_text_cancel.m4r + - assets/sounds/speech_to_text_stop.m4r diff --git a/speech_to_text_/lib/speech_recognition_error.dart b/speech_to_text_/lib/speech_recognition_error.dart new file mode 100644 index 00000000..2ab6cd4d --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_error.dart @@ -0,0 +1,44 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'speech_recognition_error.g.dart'; + +/// A single error returned from the underlying speech services. +/// +/// Errors are either transient or permanent. Permanent errors +/// block speech recognition from continuing and must be +/// addressed before recogntion will work. Transient errors +/// cause individual recognition sessions to fail but subsequent +/// attempts may well succeed. +@JsonSerializable() +class SpeechRecognitionError { + /// Use this to differentiate the various error conditions. + /// + /// Not meant for display to the user. + final String errorMsg; + + /// True means that recognition cannot continue until + /// the error is resolved. + final bool permanent; + + SpeechRecognitionError(this.errorMsg, this.permanent); + + factory SpeechRecognitionError.fromJson(Map json) => + _$SpeechRecognitionErrorFromJson(json); + Map toJson() => _$SpeechRecognitionErrorToJson(this); + + @override + String toString() { + return "SpeechRecognitionError msg: $errorMsg, permanent: $permanent"; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is SpeechRecognitionError && + errorMsg == other.errorMsg && + permanent == other.permanent; + } + + @override + int get hashCode => errorMsg.hashCode; +} diff --git a/speech_to_text_/lib/speech_recognition_error.g.dart b/speech_to_text_/lib/speech_recognition_error.g.dart new file mode 100644 index 00000000..65299f6d --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_error.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'speech_recognition_error.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +SpeechRecognitionError _$SpeechRecognitionErrorFromJson( + Map json) { + return SpeechRecognitionError( + json['errorMsg'] as String, + json['permanent'] as bool, + ); +} + +Map _$SpeechRecognitionErrorToJson( + SpeechRecognitionError instance) => + { + 'errorMsg': instance.errorMsg, + 'permanent': instance.permanent, + }; diff --git a/speech_to_text_/lib/speech_recognition_event.dart b/speech_to_text_/lib/speech_recognition_event.dart new file mode 100644 index 00000000..71729365 --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_event.dart @@ -0,0 +1,30 @@ +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +enum SpeechRecognitionEventType { + finalRecognitionEvent, + partialRecognitionEvent, + errorEvent, + statusChangeEvent, + soundLevelChangeEvent, +} + +/// A single event in a stream of speech recognition events. +/// +/// Use [eventType] to determine what type of event it is and depending on that +/// use the other properties to get information about it. +class SpeechRecognitionEvent { + final SpeechRecognitionEventType eventType; + final SpeechRecognitionError _error; + final SpeechRecognitionResult _result; + final bool _listening; + final double _level; + + SpeechRecognitionEvent( + this.eventType, this._result, this._error, this._listening, this._level); + + bool get isListening => _listening; + double get level => _level; + SpeechRecognitionResult get recognitionResult => _result; + SpeechRecognitionError get error => _error; +} diff --git a/speech_to_text_/lib/speech_recognition_result.dart b/speech_to_text_/lib/speech_recognition_result.dart new file mode 100644 index 00000000..38509f65 --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_result.dart @@ -0,0 +1,140 @@ +import 'dart:collection'; + +import 'package:json_annotation/json_annotation.dart'; + +part 'speech_recognition_result.g.dart'; + +/// A sequence of recognized words from the speech recognition +/// service. +/// +/// Depending on the platform behaviour the words may come in all +/// at once at the end or as partial results as each word is +/// recognized. Use the [finalResult] flag to determine if the +/// result is considered final by the platform. +@JsonSerializable(explicitToJson: true) +class SpeechRecognitionResult { + List _alternates; + + /// Returns a list of possible transcriptions of the speech. + /// + /// The first value is always the same as the [recognizedWords] + /// value. Use the confidence for each alternate transcription + /// to determine how likely it is. Note that not all platforms + /// do a good job with confidence, there are convenience methods + /// on [SpeechRecogntionWords] to work with possibly missing + /// confidence values. + List get alternates => + UnmodifiableListView(_alternates); + + /// The sequence of words that is the best transcription of + /// what was said. + /// + /// This is the same as the first value of [alternates]. + String get recognizedWords => + _alternates.isNotEmpty ? _alternates.first.recognizedWords : ""; + + /// False means the words are an interim result, true means + /// they are the final recognition. + final bool finalResult; + + /// The confidence that the [recognizedWords] are correct. + /// + /// Confidence is expressed as a value between 0 and 1. -1 + /// means that the confidence value was not available. + double get confidence => + _alternates.isNotEmpty ? _alternates.first.confidence : 0; + + /// true if there is confidence in this recognition, false otherwise. + /// + /// There are two separate ways for there to be confidence, the first + /// is if the confidence is missing, which is indicated by a value of + /// -1. The second is if the confidence is greater than or equal + /// [threshold]. If [threshold] is not provided it defaults to 0.8. + bool isConfident( + {double threshold = SpeechRecognitionWords.confidenceThreshold}) => + _alternates.isNotEmpty + ? _alternates.first.isConfident(threshold: threshold) + : false; + + /// true if [confidence] is not the [missingConfidence] value, false + /// otherwise. + bool get hasConfidenceRating => + _alternates.isNotEmpty ? _alternates.first.hasConfidenceRating : false; + + SpeechRecognitionResult(this._alternates, this.finalResult); + + @override + String toString() { + return "SpeechRecognitionResult words: $_alternates, final: $finalResult"; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is SpeechRecognitionResult && + recognizedWords == other.recognizedWords && + finalResult == other.finalResult; + } + + @override + int get hashCode => recognizedWords.hashCode; + + factory SpeechRecognitionResult.fromJson(Map json) => + _$SpeechRecognitionResultFromJson(json); + Map toJson() => _$SpeechRecognitionResultToJson(this); +} + +/// A set of words recognized in a [SpeechRecognitionResult]. +/// +/// Each result will have one or more [SpeechRecognitionWords] +/// with a varying degree of confidence about each set of words. +@JsonSerializable() +class SpeechRecognitionWords { + /// The sequence of words recognized + final String recognizedWords; + + /// The confidence that the [recognizedWords] are correct. + /// + /// Confidence is expressed as a value between 0 and 1. 0 + /// means that the confidence value was not available. Use + /// [isConfident] which will ignore 0 values automatically. + final double confidence; + + static const double confidenceThreshold = 0.8; + static const double missingConfidence = -1; + + const SpeechRecognitionWords(this.recognizedWords, this.confidence); + + /// true if there is confidence in this recognition, false otherwise. + /// + /// There are two separate ways for there to be confidence, the first + /// is if the confidence is missing, which is indicated by a value of + /// -1. The second is if the confidence is greater than or equal + /// [threshold]. If [threshold] is not provided it defaults to 0.8. + bool isConfident({double threshold = confidenceThreshold}) => + confidence == missingConfidence || confidence >= threshold; + + /// true if [confidence] is not the [missingConfidence] value, false + /// otherwise. + bool get hasConfidenceRating => confidence != missingConfidence; + + @override + String toString() { + return "SpeechRecognitionWords words: $recognizedWords, confidence: $confidence"; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + other is SpeechRecognitionWords && + recognizedWords == other.recognizedWords && + confidence == other.confidence; + } + + @override + int get hashCode => recognizedWords.hashCode; + + factory SpeechRecognitionWords.fromJson(Map json) => + _$SpeechRecognitionWordsFromJson(json); + Map toJson() => _$SpeechRecognitionWordsToJson(this); +} diff --git a/speech_to_text_/lib/speech_recognition_result.g.dart b/speech_to_text_/lib/speech_recognition_result.g.dart new file mode 100644 index 00000000..023e5485 --- /dev/null +++ b/speech_to_text_/lib/speech_recognition_result.g.dart @@ -0,0 +1,41 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'speech_recognition_result.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +SpeechRecognitionResult _$SpeechRecognitionResultFromJson( + Map json) { + return SpeechRecognitionResult( + (json['alternates'] as List) + ?.map((e) => e == null + ? null + : SpeechRecognitionWords.fromJson(e as Map)) + ?.toList(), + json['finalResult'] as bool, + ); +} + +Map _$SpeechRecognitionResultToJson( + SpeechRecognitionResult instance) => + { + 'alternates': instance.alternates?.map((e) => e?.toJson())?.toList(), + 'finalResult': instance.finalResult, + }; + +SpeechRecognitionWords _$SpeechRecognitionWordsFromJson( + Map json) { + return SpeechRecognitionWords( + json['recognizedWords'] as String, + (json['confidence'] as num)?.toDouble(), + ); +} + +Map _$SpeechRecognitionWordsToJson( + SpeechRecognitionWords instance) => + { + 'recognizedWords': instance.recognizedWords, + 'confidence': instance.confidence, + }; diff --git a/speech_to_text_/lib/speech_to_text.dart b/speech_to_text_/lib/speech_to_text.dart new file mode 100644 index 00000000..343706e6 --- /dev/null +++ b/speech_to_text_/lib/speech_to_text.dart @@ -0,0 +1,511 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:math'; + +import 'package:clock/clock.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +enum ListenMode { + deviceDefault, + dictation, + search, + confirmation, +} + +/// Notified as words are recognized with the current set of recognized words. +/// +/// See the [onResult] argument on the [listen] method for use. +typedef SpeechResultListener = void Function(SpeechRecognitionResult result); + +/// Notified if errors occur during recognition or intialization. +/// +/// Possible errors per the Android docs are described here: +/// https://developer.android.com/reference/android/speech/SpeechRecognizer +/// "error_audio_error" +/// "error_client" +/// "error_permission" +/// "error_network" +/// "error_network_timeout" +/// "error_no_match" +/// "error_busy" +/// "error_server" +/// "error_speech_timeout" +/// See the [onError] argument on the [initialize] method for use. +typedef SpeechErrorListener = void Function( + SpeechRecognitionError errorNotification); + +/// Notified when recognition status changes. +/// +/// See the [onStatus] argument on the [initialize] method for use. +typedef SpeechStatusListener = void Function(String status); + +/// Notified when the sound level changes during a listen method. +/// +/// [level] is a measure of the decibels of the current sound on +/// the recognition input. See the [onSoundLevelChange] argument on +/// the [listen] method for use. +typedef SpeechSoundLevelChange = Function(double level); + +/// An interface to device specific speech recognition services. +/// +/// The general flow of a speech recognition session is as follows: +/// ```Dart +/// SpeechToText speech = SpeechToText(); +/// bool isReady = await speech.initialize(); +/// if ( isReady ) { +/// await speech.listen( resultListener: resultListener ); +/// } +/// ... +/// // At some point later +/// speech.stop(); +/// ``` +class SpeechToText { + static const String listenMethod = 'listen'; + static const String textRecognitionMethod = 'textRecognition'; + static const String notifyErrorMethod = 'notifyError'; + static const String notifyStatusMethod = 'notifyStatus'; + static const String soundLevelChangeMethod = "soundLevelChange"; + static const String notListeningStatus = "notListening"; + static const String listeningStatus = "listening"; + + static const MethodChannel speechChannel = + const MethodChannel('plugin.csdcorp.com/speech_to_text'); + static final SpeechToText _instance = + SpeechToText.withMethodChannel(speechChannel); + bool _initWorked = false; + bool _recognized = false; + bool _listening = false; + bool _cancelOnError = false; + bool _partialResults = false; + int _listenStartedAt = 0; + int _lastSpeechEventAt = 0; + Duration _pauseFor; + Duration _listenFor; + + /// True if not listening or the user called cancel / stop, false + /// if cancel/stop were invoked by timeout or error condition. + bool _userEnded = false; + String _lastRecognized = ""; + String _lastStatus = ""; + double _lastSoundLevel = 0; + Timer _listenTimer; + LocaleName _systemLocale; + SpeechRecognitionError _lastError; + SpeechResultListener _resultListener; + SpeechErrorListener errorListener; + SpeechStatusListener statusListener; + SpeechSoundLevelChange _soundLevelChange; + + final MethodChannel channel; + factory SpeechToText() => _instance; + + @visibleForTesting + SpeechToText.withMethodChannel(this.channel); + + /// True if words have been recognized during the current [listen] call. + /// + /// Goes false as soon as [cancel] is called. + bool get hasRecognized => _recognized; + + /// The last set of recognized words received. + /// + /// This is maintained across [cancel] calls but cleared on the next + /// [listen]. + String get lastRecognizedWords => _lastRecognized; + + /// The last status update received, see [initialize] to register + /// an optional listener to be notified when this changes. + String get lastStatus => _lastStatus; + + /// The last sound level received during a listen event. + /// + /// The sound level is a measure of how loud the current + /// input is during listening. Use the [onSoundLevelChange] + /// argument in the [listen] method to get notified of + /// changes. + double get lastSoundLevel => _lastSoundLevel; + + /// True if [initialize] succeeded + bool get isAvailable => _initWorked; + + /// True if [listen] succeeded and [stop] or [cancel] has not been called. + /// + /// Also goes false when listening times out if listenFor was set. + bool get isListening => _listening; + bool get isNotListening => !isListening; + + /// The last error received or null if none, see [initialize] to + /// register an optional listener to be notified of errors. + SpeechRecognitionError get lastError => _lastError; + + /// True if an error has been received, see [lastError] for details + bool get hasError => null != lastError; + + /// Returns true if the user has already granted permission to access the + /// microphone, does not prompt the user. + /// + /// This method can be called before [initialize] to check if permission + /// has already been granted. If this returns false then the [initialize] + /// call will prompt the user for permission if it is allowed to do so. + /// Note that applications cannot ask for permission again if the user has + /// denied them permission in the past. + Future get hasPermission async { + bool hasPermission = await channel.invokeMethod('has_permission'); + return hasPermission; + } + + /// Initialize speech recognition services, returns true if + /// successful, false if failed. + /// + /// This method must be called before any other speech functions. + /// If this method returns false no further [SpeechToText] methods + /// should be used. Should only be called once if successful but does protect + /// itself if called repeatedly. False usually means that the user has denied + /// permission to use speech. The usual option in that case is to give them + /// instructions on how to open system settings and grant permission. + /// + /// [onError] is an optional listener for errors like + /// timeout, or failure of the device speech recognition. + /// [onStatus] is an optional listener for status changes from + /// listening to not listening. + /// [debugLogging] controls whether there is detailed logging from the underlying + /// plugins. It is off by default, usually only useful for troubleshooting issues + /// with a paritcular OS version or device, fairly verbose + Future initialize( + {SpeechErrorListener onError, + SpeechStatusListener onStatus, + debugLogging = false}) async { + if (_initWorked) { + return Future.value(_initWorked); + } + errorListener = onError; + statusListener = onStatus; + channel.setMethodCallHandler(_handleCallbacks); + _initWorked = await channel + .invokeMethod('initialize', {"debugLogging": debugLogging}); + return _initWorked; + } + + /// Stops the current listen for speech if active, does nothing if not. + /// + /// Stopping a listen session will cause a final result to be sent. Each + /// listen session should be ended with either [stop] or [cancel], for + /// example in the dispose method of a Widget. [cancel] is automatically + /// invoked by a permanent error if [cancelOnError] is set to true in the + /// [listen] call. + /// + /// *Note:* Cannot be used until a successful [initialize] call. Should + /// only be used after a successful [listen] call. + Future stop() async { + _userEnded = true; + return _stop(); + } + + Future _stop() async { + if (!_initWorked) { + return; + } + _shutdownListener(); + await channel.invokeMethod('stop'); + } + + /// Cancels the current listen for speech if active, does nothing if not. + /// + /// Canceling means that there will be no final result returned from the + /// recognizer. Each listen session should be ended with either [stop] or + /// [cancel], for example in the dispose method of a Widget. [cancel] is + /// automatically invoked by a permanent error if [cancelOnError] is set + /// to true in the [listen] call. + /// + /// *Note* Cannot be used until a successful [initialize] call. Should only + /// be used after a successful [listen] call. + Future cancel() async { + _userEnded = true; + return _cancel(); + } + + Future _cancel() async { + if (!_initWorked) { + return; + } + _shutdownListener(); + await channel.invokeMethod('cancel'); + } + + /// Starts a listening session for speech and converts it to text, + /// invoking the provided [onResult] method as words are recognized. + /// + /// Cannot be used until a successful [initialize] call. There is a + /// time limit on listening imposed by both Android and iOS. The time + /// depends on the device, network, etc. Android is usually quite short, + /// especially if there is no active speech event detected, on the order + /// of ten seconds or so. + /// + /// When listening is done always invoke either [cancel] or [stop] to + /// end the session, even if it times out. [cancelOnError] provides an + /// automatic way to ensure this happens. + /// + /// [onResult] is an optional listener that is notified when words + /// are recognized. + /// + /// [listenFor] sets the maximum duration that it will listen for, after + /// that it automatically stops the listen for you. + /// + /// [pauseFor] sets the maximum duration of a pause in speech with no words + /// detected, after that it automatically stops the listen for you. + /// + /// [localeId] is an optional locale that can be used to listen in a language + /// other than the current system default. See [locales] to find the list of + /// supported languages for listening. + /// + /// [onSoundLevelChange] is an optional listener that is notified when the + /// sound level of the input changes. Use this to update the UI in response to + /// more or less input. The values currently differ between Ancroid and iOS, + /// haven't yet been able to determine from the Android documentation what the + /// value means. On iOS the value returned is in decibels. + /// + /// [cancelOnError] if true then listening is automatically canceled on a + /// permanent error. This defaults to false. When false cancel should be + /// called from the error handler. + /// + /// [partialResults] if true the listen reports results as they are recognized, + /// when false only final results are reported. Defaults to true. + /// + /// [onDevice] if true the listen attempts to recognize locally with speech never + /// leaving the device. If it cannot do this the listen attempt will fail. This is + /// usually only needed for sensitive content where privacy or security is a concern. + Future listen( + {SpeechResultListener onResult, + Duration listenFor, + Duration pauseFor, + String localeId, + SpeechSoundLevelChange onSoundLevelChange, + cancelOnError = false, + partialResults = true, + onDevice = false, + ListenMode listenMode = ListenMode.confirmation}) async { + if (!_initWorked) { + throw SpeechToTextNotInitializedException(); + } + _userEnded = false; + _cancelOnError = cancelOnError; + _recognized = false; + _resultListener = onResult; + _soundLevelChange = onSoundLevelChange; + _partialResults = partialResults; + Map listenParams = { + "partialResults": partialResults || null != pauseFor, + "onDevice": onDevice, + "listenMode": listenMode.index, + }; + if (null != localeId) { + listenParams["localeId"] = localeId; + } + try { + bool started = await channel.invokeMethod(listenMethod, listenParams); + if (started) { + _listenStartedAt = clock.now().millisecondsSinceEpoch; + _setupListenAndPause(pauseFor, listenFor); + } + } on PlatformException catch (e) { + throw ListenFailedException(e.details); + } + } + + void _setupListenAndPause(Duration pauseFor, Duration listenFor) { + _pauseFor = null; + _listenFor = null; + if (null == pauseFor && null == listenFor) { + return; + } + var minDuration; + if (null == pauseFor) { + _listenFor = Duration(milliseconds: listenFor.inMilliseconds); + minDuration = listenFor; + } else if (null == listenFor) { + _pauseFor = Duration(milliseconds: pauseFor.inMilliseconds); + minDuration = pauseFor; + } else { + _listenFor = Duration(milliseconds: listenFor.inMilliseconds); + _pauseFor = Duration(milliseconds: pauseFor.inMilliseconds); + var minMillis = min(listenFor.inMilliseconds - _elapsedListenMillis, + pauseFor.inMilliseconds); + minDuration = Duration(milliseconds: minMillis); + } + _listenTimer = Timer(minDuration, _stopOnPauseOrListen); + } + + int get _elapsedListenMillis => + clock.now().millisecondsSinceEpoch - _listenStartedAt; + int get _elapsedSinceSpeechEvent => + clock.now().millisecondsSinceEpoch - _lastSpeechEventAt; + + void _stopOnPauseOrListen() { + if (null != _listenFor && + _elapsedListenMillis >= _listenFor.inMilliseconds) { + _stop(); + } else if (null != _pauseFor && + _elapsedSinceSpeechEvent >= _pauseFor.inMilliseconds) { + _stop(); + } else { + _setupListenAndPause(_pauseFor, _listenFor); + } + } + + /// returns the list of speech locales available on the device. + /// + /// This method is useful to find the identifier to use + /// for the [listen] method, it is the [localeId] member of the + /// [LocaleName]. + /// + /// Each [LocaleName] in the returned list has the + /// identifier for the locale as well as a name for + /// display. The name is localized for the system locale on + /// the device. + Future> locales() async { + if (!_initWorked) { + throw SpeechToTextNotInitializedException(); + } + final List locales = await channel.invokeMethod('locales'); + List filteredLocales = locales + .map((locale) { + var components = locale.split(":"); + if (components.length != 2) { + return null; + } + return LocaleName(components[0], components[1]); + }) + .where((item) => item != null) + .toList(); + if (filteredLocales.isNotEmpty) { + _systemLocale = filteredLocales.first; + } else { + _systemLocale = null; + } + filteredLocales.sort((ln1, ln2) => ln1.name.compareTo(ln2.name)); + return filteredLocales; + } + + /// returns the locale that will be used if no localeId is passed + /// to the [listen] method. + Future systemLocale() async { + if (null == _systemLocale) { + await locales(); + } + return Future.value(_systemLocale); + } + + Future _handleCallbacks(MethodCall call) async { + // print("SpeechToText call: ${call.method} ${call.arguments}"); + switch (call.method) { + case textRecognitionMethod: + if (call.arguments is String) { + _onTextRecognition(call.arguments); + } + break; + case notifyErrorMethod: + if (call.arguments is String) { + await _onNotifyError(call.arguments); + } + break; + case notifyStatusMethod: + if (call.arguments is String) { + _onNotifyStatus(call.arguments); + } + break; + case soundLevelChangeMethod: + if (call.arguments is double) { + _onSoundLevelChange(call.arguments); + } + break; + default: + } + } + + void _onTextRecognition(String resultJson) { + _lastSpeechEventAt = clock.now().millisecondsSinceEpoch; + Map resultMap = jsonDecode(resultJson); + SpeechRecognitionResult speechResult = + SpeechRecognitionResult.fromJson(resultMap); + if (!_partialResults && !speechResult.finalResult) { + return; + } + _recognized = true; + // print("Recognized text $resultJson"); + + _lastRecognized = speechResult.recognizedWords; + if (null != _resultListener) { + _resultListener(speechResult); + } + } + + Future _onNotifyError(String errorJson) async { + if (isNotListening && _userEnded) { + return; + } + Map errorMap = jsonDecode(errorJson); + SpeechRecognitionError speechError = + SpeechRecognitionError.fromJson(errorMap); + _lastError = speechError; + if (null != errorListener) { + errorListener(speechError); + } + if (_cancelOnError && speechError.permanent) { + await _cancel(); + } + } + + void _onNotifyStatus(String status) { + _lastStatus = status; + _listening = status == listeningStatus; + // print(status); + if (null != statusListener) { + statusListener(status); + } + } + + void _onSoundLevelChange(double level) { + if (isNotListening) { + return; + } + _lastSoundLevel = level; + if (null != _soundLevelChange) { + _soundLevelChange(level); + } + } + + _shutdownListener() { + _listening = false; + _recognized = false; + _listenTimer?.cancel(); + _listenTimer = null; + } + + @visibleForTesting + Future processMethodCall(MethodCall call) async { + return await _handleCallbacks(call); + } +} + +/// A single locale with a [name], localized to the current system locale, +/// and a [localeId] which can be used in the [listen] method to choose a +/// locale for speech recognition. +class LocaleName { + final String localeId; + final String name; + LocaleName(this.localeId, this.name); +} + +/// Thrown when a method is called that requires successful +/// initialization first. +class SpeechToTextNotInitializedException implements Exception {} + +/// Thrown when listen fails to properly start a speech listening session +/// on the device +class ListenFailedException implements Exception { + final String details; + ListenFailedException(this.details); +} diff --git a/speech_to_text_/lib/speech_to_text_provider.dart b/speech_to_text_/lib/speech_to_text_provider.dart new file mode 100644 index 00000000..91adf3b4 --- /dev/null +++ b/speech_to_text_/lib/speech_to_text_provider.dart @@ -0,0 +1,201 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_event.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; + +/// Simplifies interaction with [SpeechToText] by handling all the callbacks and notifying +/// listeners as events happen. +/// +/// Here's an example of using the [SpeechToTextProvider] +/// ``` +/// var speechProvider = SpeechToTextProvider( SpeechToText()); +/// var available = await speechProvider.initialize(); +/// StreamSubscription _subscription; +/// _subscription = speechProvider.recognitionController.stream.listen((recognitionEvent) { +/// if (recognitionEvent.eventType == SpeechRecognitionEventType.finalRecognitionEvent ) { +/// print("I heard: ${recognitionEvent.recognitionResult.recognizedWords}"); +/// } +/// }); +/// speechProvider.addListener(() { +/// var words = speechProvider.lastWords; +/// }); +class SpeechToTextProvider extends ChangeNotifier { + final StreamController _recognitionController = + StreamController.broadcast(); + final SpeechToText _speechToText; + SpeechRecognitionResult _lastResult; + double _lastLevel = 0; + List _locales = []; + LocaleName _systemLocale; + + /// Only construct one instance in an application. + /// + /// Do not call `initialize` on the [SpeechToText] that is passed as a parameter, instead + /// call the [initialize] method on this class. + SpeechToTextProvider(this._speechToText); + + Stream get stream => _recognitionController.stream; + + /// Returns the last result received, may be null. + SpeechRecognitionResult get lastResult => _lastResult; + + /// Returns the last error received, may be null. + SpeechRecognitionError get lastError => _speechToText.lastError; + + /// Returns the last sound level received. + /// + /// Note this is only available when the `soundLevel` is set to true on + /// a call to [listen], will be 0 at all other times. + double get lastLevel => _lastLevel; + + /// Initializes the provider and the contained [SpeechToText] instance. + /// + /// Returns true if [SpeechToText] was initialized successful and can now + /// be used, false otherwse. + Future initialize() async { + if (isAvailable) { + return isAvailable; + } + bool availableBefore = _speechToText.isAvailable; + bool available = + await _speechToText.initialize(onStatus: _onStatus, onError: _onError); + if (available) { + _locales = []; + _locales.addAll(await _speechToText.locales()); + _systemLocale = await _speechToText.systemLocale(); + } + if (availableBefore != available) { + notifyListeners(); + } + return available; + } + + /// Returns true if the provider has been initialized and can be used to recognize speech. + bool get isAvailable => _speechToText.isAvailable; + + /// Returns true if the provider cannot be used to recognize speech, either because it has not + /// yet been initialized or because initialization failed. + bool get isNotAvailable => !_speechToText.isAvailable; + + /// Returns true if [SpeechToText] is listening for new speech. + bool get isListening => _speechToText.isListening; + + /// Returns true if [SpeechToText] is not listening for new speech. + bool get isNotListening => _speechToText.isNotListening; + + /// Returns true if [SpeechToText] has a previous error. + bool get hasError => _speechToText.hasError; + + /// Returns true if [lastResult] has a last result. + bool get hasResults => null != _lastResult; + + /// Returns the list of locales that are available on the device for speech recognition. + List get locales => _locales; + + /// Returns the locale that is currently set as active on the device. + LocaleName get systemLocale => _systemLocale; + + /// Start listening for new events, set [partialResults] to true to receive interim + /// recognition results. + /// + /// [soundLevel] set to true to be notified on changes to the input sound level + /// on the microphone. + /// + /// [listenFor] sets the maximum duration that it will listen for, after + /// that it automatically stops the listen for you. + /// + /// [pauseFor] sets the maximum duration of a pause in speech with no words + /// detected, after that it automatically stops the listen for you. + /// + /// Call this only after a successful [initialize] call + void listen( + {bool partialResults = false, + bool soundLevel = false, + Duration listenFor, + Duration pauseFor}) { + _lastLevel = 0; + _lastResult = null; + if (soundLevel) { + _speechToText.listen( + partialResults: partialResults, + listenFor: listenFor, + pauseFor: pauseFor, + cancelOnError: true, + onResult: _onListenResult, + // onSoundLevelChange: _onSoundLevelChange); + ); + } else { + _speechToText.listen( + partialResults: partialResults, + listenFor: listenFor, + pauseFor: pauseFor, + cancelOnError: true, + onResult: _onListenResult); + } + } + + /// Stops a current active listening session. + /// + /// Call this after calling [listen] to stop the recognizer from listening further + /// and return the current result as final. + void stop() { + _speechToText.stop(); + notifyListeners(); + } + + /// Cancel a current active listening session. + /// + /// Call this after calling [listen] to stop the recognizer from listening further + /// and ignore any results recognized so far. + void cancel() { + _speechToText.cancel(); + notifyListeners(); + } + + void _onError(SpeechRecognitionError errorNotification) { + _recognitionController.add(SpeechRecognitionEvent( + SpeechRecognitionEventType.errorEvent, + null, + errorNotification, + isListening, + null)); + notifyListeners(); + } + + void _onStatus(String status) { + _recognitionController.add(SpeechRecognitionEvent( + SpeechRecognitionEventType.statusChangeEvent, + null, + null, + isListening, + null)); + notifyListeners(); + } + + void _onListenResult(SpeechRecognitionResult result) { + _lastResult = result; + _recognitionController.add(SpeechRecognitionEvent( + result.finalResult + ? SpeechRecognitionEventType.finalRecognitionEvent + : SpeechRecognitionEventType.partialRecognitionEvent, + result, + null, + isListening, + null)); + notifyListeners(); + } + + // void _onSoundLevelChange(double level) { + // _lastLevel = level; + // _recognitionController.add(SpeechRecognitionEvent( + // SpeechRecognitionEventType.soundLevelChangeEvent, + // null, + // null, + // null, + // level)); + // notifyListeners(); + // } +} diff --git a/speech_to_text_/pubspec.yaml b/speech_to_text_/pubspec.yaml new file mode 100644 index 00000000..34b3da29 --- /dev/null +++ b/speech_to_text_/pubspec.yaml @@ -0,0 +1,31 @@ +name: speech_to_text +description: A Flutter plugin that exposes device specific speech to text recognition capability. + + + +environment: + sdk: ">=2.1.0 <3.0.0" + flutter: ">=1.10.0" + +dependencies: + flutter: + sdk: flutter + json_annotation: ^3.0.0 + clock: ^1.0.1 + +dev_dependencies: + flutter_test: + sdk: flutter + build_runner: ^1.0.0 + json_serializable: ^3.0.0 + fake_async: ^1.0.1 + +flutter: + plugin: + platforms: + android: + package: com.csdcorp.speech_to_text + pluginClass: SpeechToTextPlugin + ios: + pluginClass: SpeechToTextPlugin + diff --git a/speech_to_text_/test/speech_recognition_error_test.dart b/speech_to_text_/test/speech_recognition_error_test.dart new file mode 100644 index 00000000..202ae4cd --- /dev/null +++ b/speech_to_text_/test/speech_recognition_error_test.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; + +void main() { + const String msg1 = "msg1"; + + setUp(() {}); + + group('properties', () { + test('equals true for same object', () { + SpeechRecognitionError error = SpeechRecognitionError(msg1, false); + expect(error, error); + }); + test('equals true for different object same values', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError(msg1, false); + expect(error1, error2); + }); + test('equals false for different object', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError("msg2", false); + expect(error1, isNot(error2)); + }); + test('hash same for same object', () { + SpeechRecognitionError error = SpeechRecognitionError(msg1, false); + expect(error.hashCode, error.hashCode); + }); + test('hash same for different object same values', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError(msg1, false); + expect(error1.hashCode, error2.hashCode); + }); + test('hash different for different object', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + SpeechRecognitionError error2 = SpeechRecognitionError("msg2", false); + expect(error1.hashCode, isNot(error2.hashCode)); + }); + test('toString as expected', () { + SpeechRecognitionError error1 = SpeechRecognitionError(msg1, false); + expect(error1.toString(), + "SpeechRecognitionError msg: $msg1, permanent: false"); + }); + }); + group('json', () { + test('loads properly', () { + var json = jsonDecode('{"errorMsg":"$msg1","permanent":true}'); + SpeechRecognitionError error = SpeechRecognitionError.fromJson(json); + expect(error.errorMsg, msg1); + expect(error.permanent, isTrue); + json = jsonDecode('{"errorMsg":"$msg1","permanent":false}'); + error = SpeechRecognitionError.fromJson(json); + expect(error.permanent, isFalse); + }); + test('roundtrips properly', () { + var json = jsonDecode('{"errorMsg":"$msg1","permanent":true}'); + SpeechRecognitionError error = SpeechRecognitionError.fromJson(json); + var roundtripJson = error.toJson(); + SpeechRecognitionError roundtripError = + SpeechRecognitionError.fromJson(roundtripJson); + expect(error, roundtripError); + }); + }); +} diff --git a/speech_to_text_/test/speech_recognition_event_test.dart b/speech_to_text_/test/speech_recognition_event_test.dart new file mode 100644 index 00000000..ceaaab8a --- /dev/null +++ b/speech_to_text_/test/speech_recognition_event_test.dart @@ -0,0 +1,42 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_event.dart'; + +import 'test_speech_channel_handler.dart'; + +void main() { + group('properties', () { + test('status listening matches', () { + var event = SpeechRecognitionEvent( + SpeechRecognitionEventType.statusChangeEvent, null, null, true, null); + expect(event.eventType, SpeechRecognitionEventType.statusChangeEvent); + expect(event.isListening, isTrue); + }); + test('result matches', () { + var event = SpeechRecognitionEvent( + SpeechRecognitionEventType.finalRecognitionEvent, + TestSpeechChannelHandler.firstRecognizedResult, + null, + null, + null); + expect(event.eventType, SpeechRecognitionEventType.finalRecognitionEvent); + expect(event.recognitionResult, + TestSpeechChannelHandler.firstRecognizedResult); + }); + test('error matches', () { + var event = SpeechRecognitionEvent(SpeechRecognitionEventType.errorEvent, + null, TestSpeechChannelHandler.firstError, null, null); + expect(event.eventType, SpeechRecognitionEventType.errorEvent); + expect(event.error, TestSpeechChannelHandler.firstError); + }); + test('sound level matches', () { + var event = SpeechRecognitionEvent( + SpeechRecognitionEventType.soundLevelChangeEvent, + null, + null, + null, + TestSpeechChannelHandler.level1); + expect(event.eventType, SpeechRecognitionEventType.soundLevelChangeEvent); + expect(event.level, TestSpeechChannelHandler.level1); + }); + }); +} diff --git a/speech_to_text_/test/speech_recognition_result_test.dart b/speech_to_text_/test/speech_recognition_result_test.dart new file mode 100644 index 00000000..1516779a --- /dev/null +++ b/speech_to_text_/test/speech_recognition_result_test.dart @@ -0,0 +1,134 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +void main() { + final String firstRecognizedWords = 'hello'; + final String secondRecognizedWords = 'hello there'; + final double firstConfidence = 0.85; + final double secondConfidence = 0.62; + final String firstRecognizedJson = + '{"alternates":[{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}],"finalResult":false}'; + final String secondRecognizedJson = + '{"alternates":[{"recognizedWords":"$secondRecognizedWords","confidence":$secondConfidence}],"finalResult":false}'; + final SpeechRecognitionWords firstWords = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + final SpeechRecognitionWords secondWords = + SpeechRecognitionWords(secondRecognizedWords, secondConfidence); + + setUp(() {}); + + group('recognizedWords', () { + test('empty if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.recognizedWords, isEmpty); + }); + test('matches first alternate', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.recognizedWords, firstRecognizedWords); + }); + }); + group('alternates', () { + test('empty if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.alternates, isEmpty); + }); + test('expected contents', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.alternates, contains(firstWords)); + expect(result.alternates, contains(secondWords)); + }); + test('in order', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.alternates.first, firstWords); + }); + }); + group('confidence', () { + test('0 if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.confidence, 0); + }); + test('isConfident false if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.isConfident(), isFalse); + }); + test('isConfident matches first alternate', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.isConfident(), firstWords.isConfident()); + }); + test('hasConfidenceRating false if no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect(result.hasConfidenceRating, isFalse); + }); + test('hasConfidenceRating matches first alternate', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords, secondWords], true); + expect(result.hasConfidenceRating, firstWords.hasConfidenceRating); + }); + }); + group('json', () { + test('loads correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionResult result = SpeechRecognitionResult.fromJson(json); + expect(result.recognizedWords, firstRecognizedWords); + expect(result.confidence, firstConfidence); + }); + test('roundtrips correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionResult result = SpeechRecognitionResult.fromJson(json); + var roundTripJson = result.toJson(); + SpeechRecognitionResult roundtripResult = + SpeechRecognitionResult.fromJson(roundTripJson); + expect(result, roundtripResult); + }); + }); + group('overrides', () { + test('toString works with no alternates', () { + SpeechRecognitionResult result = SpeechRecognitionResult([], true); + expect( + result.toString(), "SpeechRecognitionResult words: [], final: true"); + }); + test('toString works with alternates', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords], true); + expect(result.toString(), + "SpeechRecognitionResult words: [SpeechRecognitionWords words: hello, confidence: 0.85], final: true"); + }); + test('hash same for same object', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords], true); + expect(result.hashCode, result.hashCode); + }); + test('hash differs for different objects', () { + SpeechRecognitionResult result1 = + SpeechRecognitionResult([firstWords], true); + SpeechRecognitionResult result2 = + SpeechRecognitionResult([secondWords], true); + expect(result1.hashCode, isNot(result2.hashCode)); + }); + test('equals same for same object', () { + SpeechRecognitionResult result = + SpeechRecognitionResult([firstWords], true); + expect(result, result); + }); + test('equals same for different object same values', () { + SpeechRecognitionResult result1 = + SpeechRecognitionResult([firstWords], true); + SpeechRecognitionResult result1a = + SpeechRecognitionResult([firstWords], true); + expect(result1, result1a); + }); + test('equals differs for different objects', () { + SpeechRecognitionResult result1 = + SpeechRecognitionResult([firstWords], true); + SpeechRecognitionResult result2 = + SpeechRecognitionResult([secondWords], true); + expect(result1, isNot(result2)); + }); + }); +} diff --git a/speech_to_text_/test/speech_recognitions_words_test.dart b/speech_to_text_/test/speech_recognitions_words_test.dart new file mode 100644 index 00000000..36a9ef0e --- /dev/null +++ b/speech_to_text_/test/speech_recognitions_words_test.dart @@ -0,0 +1,86 @@ +import 'dart:convert'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; + +void main() { + final String firstRecognizedWords = 'hello'; + final String secondRecognizedWords = 'hello there'; + final double firstConfidence = 0.85; + final double secondConfidence = 0.62; + final String firstRecognizedJson = + '{"recognizedWords":"$firstRecognizedWords","confidence":$firstConfidence}'; + final SpeechRecognitionWords firstWords = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + final SpeechRecognitionWords secondWords = + SpeechRecognitionWords(secondRecognizedWords, secondConfidence); + + setUp(() {}); + + group('properties', () { + test('words', () { + expect(firstWords.recognizedWords, firstRecognizedWords); + expect(secondWords.recognizedWords, secondRecognizedWords); + }); + test('confidence', () { + expect(firstWords.confidence, firstConfidence); + expect(secondWords.confidence, secondConfidence); + expect(firstWords.hasConfidenceRating, isTrue); + }); + test('equals true for same object', () { + expect(firstWords, firstWords); + }); + test('equals true for different object with same values', () { + SpeechRecognitionWords firstWordsA = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + expect(firstWords, firstWordsA); + }); + test('equals false for different results', () { + expect(firstWords, isNot(secondWords)); + }); + test('hash same for same object', () { + expect(firstWords.hashCode, firstWords.hashCode); + }); + test('hash same for different object with same values', () { + SpeechRecognitionWords firstWordsA = + SpeechRecognitionWords(firstRecognizedWords, firstConfidence); + expect(firstWords.hashCode, firstWordsA.hashCode); + }); + test('hash different for different results', () { + expect(firstWords.hashCode, isNot(secondWords.hashCode)); + }); + }); + group('isConfident', () { + test('true when >= 0.8', () { + expect(firstWords.isConfident(), isTrue); + }); + test('false when < 0.8', () { + expect(secondWords.isConfident(), isFalse); + }); + test('respects threshold', () { + expect(secondWords.isConfident(threshold: 0.5), isTrue); + }); + test('true when missing', () { + SpeechRecognitionWords words = SpeechRecognitionWords( + firstRecognizedWords, SpeechRecognitionWords.missingConfidence); + expect(words.isConfident(), isTrue); + expect(words.hasConfidenceRating, isFalse); + }); + }); + group('json', () { + test('loads correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionWords words = SpeechRecognitionWords.fromJson(json); + expect(words.recognizedWords, firstRecognizedWords); + expect(words.confidence, firstConfidence); + }); + test('roundtrips correctly', () { + var json = jsonDecode(firstRecognizedJson); + SpeechRecognitionWords words = SpeechRecognitionWords.fromJson(json); + var roundTripJson = words.toJson(); + SpeechRecognitionWords roundtripWords = + SpeechRecognitionWords.fromJson(roundTripJson); + expect(words, roundtripWords); + }); + }); +} diff --git a/speech_to_text_/test/speech_to_text_provider_test.dart b/speech_to_text_/test/speech_to_text_provider_test.dart new file mode 100644 index 00000000..25366b6f --- /dev/null +++ b/speech_to_text_/test/speech_to_text_provider_test.dart @@ -0,0 +1,196 @@ +import 'package:fake_async/fake_async.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:speech_to_text/speech_to_text.dart'; +import 'package:speech_to_text/speech_to_text_provider.dart'; + +import 'test_speech_channel_handler.dart'; +import 'test_speech_listener.dart'; + +void main() { + SpeechToTextProvider provider; + SpeechToText speechToText; + TestSpeechChannelHandler speechHandler; + TestSpeechListener speechListener; + + TestWidgetsFlutterBinding.ensureInitialized(); + + setUp(() { + speechToText = SpeechToText.withMethodChannel(SpeechToText.speechChannel); + speechHandler = TestSpeechChannelHandler(speechToText); + speechToText.channel + .setMockMethodCallHandler(speechHandler.methodCallHandler); + provider = SpeechToTextProvider(speechToText); + speechListener = TestSpeechListener(provider); + provider.addListener(speechListener.onNotify); + }); + + tearDown(() { + speechToText.channel.setMockMethodCallHandler(null); + }); + + group('delegates', () { + test('isListening matches delegate defaults', () { + expect(provider.isListening, speechToText.isListening); + expect(provider.isNotListening, speechToText.isNotListening); + }); + test('isAvailable matches delegate defaults', () { + expect(provider.isAvailable, speechToText.isAvailable); + expect(provider.isNotAvailable, !speechToText.isAvailable); + }); + test('isAvailable matches delegate after init', () async { + expect(await provider.initialize(), isTrue); + expect(provider.isAvailable, speechToText.isAvailable); + expect(provider.isNotAvailable, !speechToText.isAvailable); + }); + test('hasError matches delegate after error', () async { + expect(await provider.initialize(), isTrue); + expect(provider.hasError, speechToText.hasError); + }); + }); + group('listening', () { + test('notifies on initialize', () async { + fakeAsync((fa) { + provider.initialize(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.isAvailable, isTrue); + }); + }); + test('notifies on listening', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener); + expect(speechListener.notified, isTrue); + expect(speechListener.isListening, isTrue); + expect(provider.hasResults, isFalse); + }); + }); + test('notifies on final words', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener); + speechListener.reset(); + speechHandler.notifyFinalWords(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(provider.hasResults, isTrue); + var result = speechListener.recognitionResult; + expect(result.recognizedWords, + TestSpeechChannelHandler.secondRecognizedWords); + expect(result.finalResult, isTrue); + }); + }); + test('hasResult false after listening before new results', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener); + speechHandler.notifyFinalWords(); + provider.stop(); + setupForListen(provider, fa, speechListener); + fa.flushMicrotasks(); + expect(provider.hasResults, isFalse); + }); + }); + test('notifies on partial words', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener, partialResults: true); + speechListener.reset(); + speechHandler.notifyPartialWords(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(provider.hasResults, isTrue); + var result = speechListener.recognitionResult; + expect(result.recognizedWords, + TestSpeechChannelHandler.firstRecognizedWords); + expect(result.finalResult, isFalse); + }); + }); + }); + group('soundLevel', () { + test('notifies when requested', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener, + partialResults: true, soundLevel: true); + speechListener.reset(); + speechHandler.notifySoundLevel(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.soundLevel, TestSpeechChannelHandler.level2); + }); + }); + test('no notification by default', () async { + fakeAsync((fa) { + setupForListen(provider, fa, speechListener, + partialResults: true, soundLevel: false); + speechListener.reset(); + speechHandler.notifySoundLevel(); + fa.flushMicrotasks(); + expect(speechListener.notified, isFalse); + expect(speechListener.soundLevel, 0); + }); + }); + }); + group('stop/cancel', () { + test('notifies on stop', () async { + fakeAsync((fa) { + provider.initialize(); + setupForListen(provider, fa, speechListener); + speechListener.reset(); + provider.stop(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.isListening, isFalse); + }); + }); + test('notifies on cancel', () async { + fakeAsync((fa) { + provider.initialize(); + setupForListen(provider, fa, speechListener); + speechListener.reset(); + provider.cancel(); + fa.flushMicrotasks(); + expect(speechListener.notified, isTrue); + expect(speechListener.isListening, isFalse); + }); + }); + }); + group('error handling', () { + test('hasError matches delegate default', () async { + expect(await provider.initialize(), isTrue); + expect(provider.hasError, speechToText.hasError); + }); + test('notifies on error', () async { + fakeAsync((fa) { + provider.initialize(); + setupForListen(provider, fa, speechListener); + speechListener.reset(); + speechHandler.notifyPermanentError(); + expect(speechListener.notified, isTrue); + expect(speechListener.hasError, isTrue); + }); + }); + }); + group('locale', () { + test('locales empty before init', () async { + expect(provider.systemLocale, isNull); + expect(provider.locales, isEmpty); + }); + test('set from SpeechToText after init', () async { + fakeAsync((fa) { + speechHandler.setupLocales(); + provider.initialize(); + fa.flushMicrotasks(); + expect( + provider.systemLocale.localeId, TestSpeechChannelHandler.localeId1); + expect(provider.locales, hasLength(speechHandler.locales.length)); + }); + }); + }); +} + +void setupForListen(SpeechToTextProvider provider, FakeAsync fa, + TestSpeechListener speechListener, + {bool partialResults = false, bool soundLevel = false}) { + provider.initialize(); + fa.flushMicrotasks(); + speechListener.reset(); + provider.listen(partialResults: partialResults, soundLevel: soundLevel); + fa.flushMicrotasks(); +} diff --git a/speech_to_text_/test/speech_to_text_test.dart b/speech_to_text_/test/speech_to_text_test.dart new file mode 100644 index 00000000..7b4701ff --- /dev/null +++ b/speech_to_text_/test/speech_to_text_test.dart @@ -0,0 +1,425 @@ +import 'package:fake_async/fake_async.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.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 'test_speech_channel_handler.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + TestSpeechListener listener; + TestSpeechChannelHandler speechHandler; + SpeechToText speech; + + setUp(() { + listener = TestSpeechListener(); + speech = SpeechToText.withMethodChannel(SpeechToText.speechChannel); + speechHandler = TestSpeechChannelHandler(speech); + speech.channel.setMockMethodCallHandler(speechHandler.methodCallHandler); + }); + + tearDown(() { + speech.channel.setMockMethodCallHandler(null); + }); + + group('hasPermission', () { + test('true if platform reports true', () async { + expect(await speech.hasPermission, true); + }); + test('false if platform reports false', () async { + speechHandler.hasPermissionResult = false; + expect(await speech.hasPermission, false); + }); + }); + group('init', () { + test('succeeds on platform success', () async { + expect(await speech.initialize(), true); + expect(speechHandler.initInvoked, true); + expect(speech.isAvailable, true); + }); + test('only invokes once', () async { + expect(await speech.initialize(), true); + speechHandler.initInvoked = false; + expect(await speech.initialize(), true); + expect(speechHandler.initInvoked, false); + }); + test('fails on platform failure', () async { + speechHandler.initResult = false; + expect(await speech.initialize(), false); + expect(speech.isAvailable, false); + }); + }); + + group('listen', () { + test('fails with exception if not initialized', () async { + try { + await speech.listen(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + // This is a good result + } + }); + test('fails with exception if init fails', () async { + try { + speechHandler.initResult = false; + await speech.initialize(); + await speech.listen(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + // This is a good result + } + }); + test('invokes listen after successful init', () async { + await speech.initialize(); + await speech.listen(); + expect(speechHandler.listenLocale, isNull); + expect(speechHandler.listenInvoked, true); + }); + test('converts platformException to listenFailed', () async { + await speech.initialize(); + speechHandler.listenException = true; + try { + await speech.listen(); + fail("Should have thrown"); + } on ListenFailedException catch (e) { + expect(e.details, TestSpeechChannelHandler.listenExceptionDetails); + } catch (wrongE) { + fail("Should have been ListenFailedException"); + } + }); + test('stops listen after listenFor duration', () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(listenFor: Duration(seconds: 2)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 2)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after listenFor duration even with speech event', + () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(listenFor: Duration(seconds: 1)); + speech.processMethodCall(MethodCall(SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after pauseFor duration with no speech', () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(pauseFor: Duration(seconds: 2)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 2)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after pauseFor with longer listenFor duration', + () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen( + pauseFor: Duration(seconds: 1), listenFor: Duration(seconds: 5)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isFalse); + }); + }); + test('stops listen after listenFor with longer pauseFor duration', + () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen( + listenFor: Duration(seconds: 1), pauseFor: Duration(seconds: 5)); + fa.flushMicrotasks(); + expect(speech.isListening, isTrue); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isFalse); + }); + }); + test('keeps listening after pauseFor with speech event', () async { + fakeAsync((fa) { + speech.initialize(); + fa.flushMicrotasks(); + speech.listen(pauseFor: Duration(seconds: 2)); + fa.flushMicrotasks(); + fa.elapse(Duration(seconds: 1)); + speech.processMethodCall(MethodCall(SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + fa.flushMicrotasks(); + fa.elapse(Duration(seconds: 1)); + expect(speech.isListening, isTrue); + }); + }); + test('uses localeId if provided', () async { + await speech.initialize(); + await speech.listen(localeId: TestSpeechChannelHandler.localeId1); + expect(speechHandler.listenInvoked, true); + expect(speechHandler.listenLocale, TestSpeechChannelHandler.localeId1); + }); + test('calls speech listener', () async { + await speech.initialize(); + await speech.listen(onResult: listener.onSpeechResult); + await speech.processMethodCall(MethodCall( + SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + expect(listener.speechResults, 1); + expect( + listener.results, [TestSpeechChannelHandler.firstRecognizedResult]); + expect(speech.lastRecognizedWords, + TestSpeechChannelHandler.firstRecognizedWords); + }); + test('calls speech listener with multiple', () async { + await speech.initialize(); + await speech.listen(onResult: listener.onSpeechResult); + await speech.processMethodCall(MethodCall( + SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.firstRecognizedJson)); + await speech.processMethodCall(MethodCall( + SpeechToText.textRecognitionMethod, + TestSpeechChannelHandler.secondRecognizedJson)); + expect(listener.speechResults, 2); + expect(listener.results, [ + TestSpeechChannelHandler.firstRecognizedResult, + TestSpeechChannelHandler.secondRecognizedResult + ]); + expect(speech.lastRecognizedWords, + TestSpeechChannelHandler.secondRecognizedWords); + }); + }); + + group('status callback', () { + test('invoked on listen', () async { + await speech.initialize( + onError: listener.onSpeechError, onStatus: listener.onSpeechStatus); + await speech.processMethodCall(MethodCall( + SpeechToText.notifyStatusMethod, SpeechToText.listeningStatus)); + expect(listener.speechStatus, 1); + expect(listener.statuses.contains(SpeechToText.listeningStatus), true); + }); + }); + + group('soundLevel callback', () { + test('invoked on listen', () async { + await speech.initialize(); + await speech.listen(onSoundLevelChange: listener.onSoundLevel); + await speech.processMethodCall(MethodCall( + SpeechToText.soundLevelChangeMethod, + TestSpeechChannelHandler.level1)); + expect(listener.soundLevel, 1); + expect(listener.soundLevels, contains(TestSpeechChannelHandler.level1)); + }); + test('sets lastLevel', () async { + await speech.initialize(); + await speech.listen(onSoundLevelChange: listener.onSoundLevel); + await speech.processMethodCall(MethodCall( + SpeechToText.soundLevelChangeMethod, + TestSpeechChannelHandler.level1)); + expect(speech.lastSoundLevel, TestSpeechChannelHandler.level1); + }); + }); + + group('cancel', () { + test('does nothing if not initialized', () async { + speech.cancel(); + expect(speechHandler.cancelInvoked, false); + }); + test('cancels an active listen', () async { + await speech.initialize(); + await speech.listen(); + await speech.cancel(); + expect(speechHandler.cancelInvoked, true); + expect(speech.isListening, isFalse); + }); + }); + group('stop', () { + test('does nothing if not initialized', () async { + speech.stop(); + expect(speechHandler.cancelInvoked, false); + }); + test('stops an active listen', () async { + await speech.initialize(); + speech.listen(); + speech.stop(); + expect(speechHandler.stopInvoked, true); + }); + }); + group('error', () { + test('notifies handler with transient', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.transientErrorJson)); + expect(listener.speechErrors, 1); + expect(listener.errors.first.permanent, isFalse); + }); + test('notifies handler with permanent', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(listener.speechErrors, 1); + expect(listener.errors.first.permanent, isTrue); + }); + test('continues listening on transient', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.transientErrorJson)); + expect(speech.isListening, isTrue); + }); + test('continues listening on permanent if cancel not explicitly requested', + () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isTrue); + }); + test('stops listening on permanent if cancel explicitly requested', + () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(cancelOnError: true); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isFalse); + }); + test('Error not sent after cancel', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(); + await speech.cancel(); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isFalse); + expect(listener.speechErrors, 0); + }); + test('Error still sent after implicit cancel', () async { + await speech.initialize(onError: listener.onSpeechError); + await speech.listen(cancelOnError: true); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + await speech.processMethodCall(MethodCall(SpeechToText.notifyErrorMethod, + TestSpeechChannelHandler.permanentErrorJson)); + expect(speech.isListening, isFalse); + expect(listener.speechErrors, 2); + }); + }); + group('locales', () { + test('fails with exception if not initialized', () async { + try { + await speech.locales(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + // This is a good result + } + }); + test('system locale null if not initialized', () async { + LocaleName current; + try { + current = await speech.systemLocale(); + fail("Expected an exception."); + } on SpeechToTextNotInitializedException { + expect(current, isNull); + } + }); + test('handles an empty list', () async { + await speech.initialize(onError: listener.onSpeechError); + List localeNames = await speech.locales(); + expect(speechHandler.localesInvoked, isTrue); + expect(localeNames, isEmpty); + }); + test('returns expected locales', () async { + await speech.initialize(onError: listener.onSpeechError); + speechHandler.locales.add(TestSpeechChannelHandler.locale1); + speechHandler.locales.add(TestSpeechChannelHandler.locale2); + List localeNames = await speech.locales(); + expect(localeNames, hasLength(speechHandler.locales.length)); + expect(localeNames[0].localeId, TestSpeechChannelHandler.localeId1); + expect(localeNames[0].name, TestSpeechChannelHandler.name1); + expect(localeNames[1].localeId, TestSpeechChannelHandler.localeId2); + expect(localeNames[1].name, TestSpeechChannelHandler.name2); + }); + test('skips incorrect locales', () async { + await speech.initialize(onError: listener.onSpeechError); + speechHandler.locales.add("InvalidJunk"); + speechHandler.locales.add(TestSpeechChannelHandler.locale1); + List localeNames = await speech.locales(); + expect(localeNames, hasLength(1)); + expect(localeNames[0].localeId, TestSpeechChannelHandler.localeId1); + expect(localeNames[0].name, TestSpeechChannelHandler.name1); + }); + test('system locale matches first returned locale', () async { + await speech.initialize(onError: listener.onSpeechError); + speechHandler.locales.add(TestSpeechChannelHandler.locale1); + speechHandler.locales.add(TestSpeechChannelHandler.locale2); + LocaleName current = await speech.systemLocale(); + expect(current.localeId, TestSpeechChannelHandler.localeId1); + }); + }); + group('status', () { + test('recognized false at start', () async { + expect(speech.hasRecognized, isFalse); + }); + test('listening false at start', () async { + expect(speech.isListening, isFalse); + }); + }); + test('available false at start', () async { + expect(speech.isAvailable, isFalse); + }); + test('hasError false at start', () async { + expect(speech.hasError, isFalse); + }); + test('lastError null at start', () async { + expect(speech.lastError, isNull); + }); + test('status empty at start', () async { + expect(speech.lastStatus, isEmpty); + }); +} + +class TestSpeechListener { + int speechResults = 0; + List results = []; + int speechErrors = 0; + List errors = []; + int speechStatus = 0; + List statuses = []; + int soundLevel = 0; + List soundLevels = []; + + void onSpeechResult(SpeechRecognitionResult result) { + ++speechResults; + results.add(result); + } + + void onSpeechError(SpeechRecognitionError errorResult) { + ++speechErrors; + errors.add(errorResult); + } + + void onSpeechStatus(String status) { + ++speechStatus; + statuses.add(status); + } + + void onSoundLevel(double level) { + ++soundLevel; + soundLevels.add(level); + } +}