diff --git a/lib/pages/feedback/send_feedback_page.dart b/lib/pages/feedback/send_feedback_page.dart index 189b4761..8ebdabd8 100644 --- a/lib/pages/feedback/send_feedback_page.dart +++ b/lib/pages/feedback/send_feedback_page.dart @@ -1,6 +1,8 @@ +import 'package:diplomaticquarterapp/config/config.dart'; import 'package:diplomaticquarterapp/core/enum/viewstate.dart'; import 'package:diplomaticquarterapp/core/viewModels/feedback/feedback_view_model.dart'; import 'package:diplomaticquarterapp/pages/base/base_view.dart'; +import 'package:diplomaticquarterapp/services/robo_search/event_provider.dart'; import 'package:diplomaticquarterapp/uitl/app_toast.dart'; import 'package:diplomaticquarterapp/uitl/date_uitl.dart'; import 'package:diplomaticquarterapp/uitl/gif_loader_dialog_utils.dart'; @@ -13,12 +15,15 @@ import 'package:diplomaticquarterapp/widgets/data_display/text.dart'; import 'package:diplomaticquarterapp/widgets/input/text_field.dart'; import 'package:diplomaticquarterapp/widgets/others/StarRating.dart'; import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart'; +import 'package:diplomaticquarterapp/widgets/others/floating_button_search.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; import 'dart:convert'; import 'dart:io'; import 'appointment_history.dart'; +import 'package:speech_to_text/speech_to_text.dart' as stt; class SendFeedbackPage extends StatefulWidget { @override @@ -35,8 +40,10 @@ class _SendFeedbackPageState extends State { String message; final formKey = GlobalKey(); MessageType messageType = MessageType.NON; - - + var _currentLocaleId; + stt.SpeechToText speech = stt.SpeechToText(); + var reconizedWord; + var event = RobotProvider(); String getSelected(BuildContext context) { switch (messageType) { case MessageType.ComplaintOnAnAppointment: @@ -61,13 +68,10 @@ class _SendFeedbackPageState extends State { return TranslationBase.of(context).notClassified; } - - setMessageType(MessageType messageType) { - setState(() { - this.messageType = messageType; - }); - + setState(() { + this.messageType = messageType; + }); } @override @@ -116,7 +120,7 @@ class _SendFeedbackPageState extends State { getSelected(context), variant: 'bodyText', ), - margin: EdgeInsets.only(left: 10,right: 10), + margin: EdgeInsets.only(left: 10, right: 10), ), Icon( Icons.arrow_drop_down, @@ -127,8 +131,8 @@ class _SendFeedbackPageState extends State { ), ), ), - if (appointHistory != null && messageType == - MessageType.ComplaintOnAnAppointment) + if (appointHistory != null && + messageType == MessageType.ComplaintOnAnAppointment) InkWell( onTap: () { setState(() { @@ -203,10 +207,13 @@ class _SendFeedbackPageState extends State { ), ), ), - if (messageType == MessageType.ComplaintOnAnAppointment && model.appointHistoryList.length != 0 && + if (messageType == MessageType.ComplaintOnAnAppointment && + model.appointHistoryList.length != 0 && isShowListAppointHistory) Container( - height: model.appointHistoryList.length>2?MediaQuery.of(context).size.height * 0.25:MediaQuery.of(context).size.height * 0.15, + height: model.appointHistoryList.length > 2 + ? MediaQuery.of(context).size.height * 0.25 + : MediaQuery.of(context).size.height * 0.15, child: ListView.builder( itemCount: model.appointHistoryList.length, itemBuilder: (context, index) => InkWell( @@ -336,6 +343,10 @@ class _SendFeedbackPageState extends State { maxLines: 25, minLines: 13, controller: messageController, + suffixIcon: Icons.mic, + onSuffixTap: () { + openSpeechReco(); + }, validator: (value) { if (value.isEmpty) return TranslationBase.of(context).emptyMessage; @@ -345,11 +356,12 @@ class _SendFeedbackPageState extends State { ), InkWell( onTap: () { - ImageOptions.showImageOptions(context, (String image,File file) { + ImageOptions.showImageOptions(context, + (String image, File file) { setState(() { images.add(image); }); - } ); + }); }, child: Container( margin: EdgeInsets.only(left: 10, right: 10, top: 15), @@ -427,18 +439,21 @@ class _SendFeedbackPageState extends State { child: SecondaryButton( label: TranslationBase.of(context).send, textColor: Colors.white, - disabled: (titleController.text.toString().isEmpty || messageController.text.toString().isEmpty|| messageType == MessageType.NON), + disabled: (titleController.text.toString().isEmpty || + messageController.text.toString().isEmpty || + messageType == MessageType.NON), onTap: () { final form = formKey.currentState; - if (form.validate()) - if (messageType != MessageType.NON){ - GifLoaderDialogUtils.showMyDialog(context); - model.sendCOCItem( + if (form.validate()) if (messageType != MessageType.NON) { + GifLoaderDialogUtils.showMyDialog(context); + model + .sendCOCItem( title: titleController.text, attachment: images.length > 0 ? images[0] : "", details: messageController.text, cOCTypeName: getCOCName(), - appointHistory:messageType == MessageType.ComplaintOnAnAppointment + appointHistory: messageType == + MessageType.ComplaintOnAnAppointment ? appointHistory : null) .then((value) { @@ -456,9 +471,10 @@ class _SendFeedbackPageState extends State { AppToast.showErrorToast(message: model.error); GifLoaderDialogUtils.hideDialog(context); } - });} - else { - AppToast.showErrorToast(message: TranslationBase.of(context).selectPart); + }); + } else { + AppToast.showErrorToast( + message: TranslationBase.of(context).selectPart); } }, ), @@ -513,28 +529,64 @@ class _SendFeedbackPageState extends State { }, )); } + + openSpeechReco() async { + new RoboSearch(context: context).showAlertDialog(context); + _currentLocaleId = + TranslationBase.of(AppGlobal.context).locale.languageCode; + bool available = await speech.initialize( + onStatus: statusListener, onError: errorListener); + if (available) { + speech.listen( + onResult: resultListener, + // listenMode: ListenMode.confirmation, + localeId: _currentLocaleId == 'en' ? 'en-US' : 'ar-SA', + ); + } else { + print("The user has denied the use of speech recognition."); + } + } + + void errorListener(SpeechRecognitionError error) {} + + void statusListener(String status) { + reconizedWord = status == 'listening' ? 'Lisening...' : 'Sorry....'; + } + + void resultListener(result) { + reconizedWord = result.recognizedWords; + event.setValue({"searchText": reconizedWord}); + + if (result.finalResult == true) { + setState(() { + RoboSearch.closeAlertDialog(context); + messageController.text = reconizedWord; + }); + } + } } class FeedbackTypeDialog extends StatefulWidget { final Function(MessageType) onValueSelected; final MessageType messageTypeDialog; - const FeedbackTypeDialog({Key key, this.onValueSelected, this.messageTypeDialog=MessageType.NON}) : super(key: key); + const FeedbackTypeDialog( + {Key key, this.onValueSelected, this.messageTypeDialog = MessageType.NON}) + : super(key: key); @override State createState() => new FeedbackTypeDialogState(); } class FeedbackTypeDialogState extends State { - - MessageType messageTypeDialog = MessageType.NON; setMessageDialogType(MessageType messageType) { - setState(() { - messageTypeDialog = messageType; - }); + setState(() { + messageTypeDialog = messageType; + }); } + @override void initState() { messageTypeDialog = widget.messageTypeDialog; @@ -562,10 +614,10 @@ class FeedbackTypeDialogState extends State { Expanded( flex: 1, child: InkWell( - onTap: () => setMessageDialogType( - MessageType.NON), + onTap: () => setMessageDialogType(MessageType.NON), child: ListTile( - title: Texts(TranslationBase.of(context).notClassified), + title: + Texts(TranslationBase.of(context).notClassified), leading: Radio( value: MessageType.NON, groupValue: messageTypeDialog, @@ -589,7 +641,8 @@ class FeedbackTypeDialogState extends State { onTap: () => setMessageDialogType( MessageType.ComplaintOnAnAppointment), child: ListTile( - title: Texts(TranslationBase.of(context).complainAppo), + title: + Texts(TranslationBase.of(context).complainAppo), leading: Radio( value: MessageType.ComplaintOnAnAppointment, groupValue: messageTypeDialog, @@ -613,7 +666,8 @@ class FeedbackTypeDialogState extends State { onTap: () => setMessageDialogType( MessageType.ComplaintWithoutAppointment), child: ListTile( - title: Texts(TranslationBase.of(context).complainWithoutAppo), + title: Texts( + TranslationBase.of(context).complainWithoutAppo), leading: Radio( value: MessageType.ComplaintWithoutAppointment, groupValue: messageTypeDialog, @@ -634,8 +688,7 @@ class FeedbackTypeDialogState extends State { Expanded( flex: 1, child: InkWell( - onTap: () => - setMessageDialogType(MessageType.Question), + onTap: () => setMessageDialogType(MessageType.Question), child: ListTile( title: Texts(TranslationBase.of(context).question), leading: Radio( @@ -690,7 +743,8 @@ class FeedbackTypeDialogState extends State { value: MessageType.Suggestion, groupValue: messageTypeDialog, activeColor: Theme.of(context).primaryColor, - onChanged: (MessageType value) => setMessageDialogType(value), + onChanged: (MessageType value) => + setMessageDialogType(value), ), ), ), @@ -745,7 +799,7 @@ class FeedbackTypeDialogState extends State { padding: const EdgeInsets.all(8.0), child: Center( child: Texts( - TranslationBase.of(context).ok, + TranslationBase.of(context).ok, fontWeight: FontWeight.w400, )), ),