diff --git a/android/gradle.properties b/android/gradle.properties index 08dfdfcb..b20905ec 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,4 +1,4 @@ org.gradle.jvmargs=-Xmx2048m android.useAndroidX=true android.enableJetifier=true -org.gradle.java.home=/Users/waseem/Library/Java/JavaVirtualMachines/jbr-17.0.12/Contents/Home + diff --git a/assets/images/logo_white.png b/assets/images/logo_white.png index 0f7acf0f..fb16b7cb 100644 Binary files a/assets/images/logo_white.png and b/assets/images/logo_white.png differ diff --git a/lib/new_views/app_style/app_color.dart b/lib/new_views/app_style/app_color.dart index 8f263e2b..fb4a8f9b 100644 --- a/lib/new_views/app_style/app_color.dart +++ b/lib/new_views/app_style/app_color.dart @@ -118,6 +118,8 @@ class AppColor { return white936; case "new": return primary63; + case "open": + return primary63; case "closed": return black1E; case "completed": @@ -135,6 +137,8 @@ class AppColor { return orange30; case "new": return primary10.withOpacity(.30); + case "open": + return primary10.withOpacity(.30); case "closed": return white936.withOpacity(.30); case "completed": diff --git a/lib/new_views/common_widgets/app_text_form_field.dart b/lib/new_views/common_widgets/app_text_form_field.dart index 65440d6c..152af656 100644 --- a/lib/new_views/common_widgets/app_text_form_field.dart +++ b/lib/new_views/common_widgets/app_text_form_field.dart @@ -1,6 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:provider/provider.dart'; +import 'package:speech_to_text/speech_recognition_error.dart'; +import 'package:speech_to_text/speech_recognition_result.dart'; +import 'package:speech_to_text/speech_to_text.dart'; +import 'package:test_sa/controllers/providers/settings/setting_provider.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; +import 'package:test_sa/extensions/text_extensions.dart'; +import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; import 'package:test_sa/new_views/app_style/app_text_style.dart'; @@ -32,6 +40,7 @@ class AppTextFormField extends StatefulWidget { final EdgeInsets? contentPadding; final bool showWithoutDecoration; final VoidCallback? onTap; + final bool showSpeechToText; const AppTextFormField({ Key? key, @@ -47,6 +56,7 @@ class AppTextFormField extends StatefulWidget { this.textInputType = TextInputType.text, this.initialValue, // Provide default value this.enable = true, + this.showSpeechToText = false, this.style, this.contentPadding, this.textAlign, @@ -69,24 +79,92 @@ class AppTextFormField extends StatefulWidget { } class _AppTextFormFieldState extends State { + bool _speechEnabled = false; + final SpeechToText _speechToText = SpeechToText(); + SettingProvider? _settingProvider; + + late FocusNode _focusNode; + @override void initState() { if (widget.initialValue != null) { widget.controller?.text = widget.initialValue!; } - + _focusNode = widget.node ?? FocusNode(); + _initSpeech(); super.initState(); } + void _initSpeech() async { + _speechEnabled = await _speechToText.initialize( + onError: (SpeechRecognitionError error) async { + Fluttertoast.showToast(msg: "failed to convert text to speech"); + setState(() {}); + }, + ); + } + + void _startListening() async { + _speechEnabled = _speechToText.isAvailable; + if (_speechToText.isListening) { + Fluttertoast.showToast(msg: "Currently in use"); + return; + } + if (!_speechEnabled) return; + await _speechToText.listen( + onResult: (SpeechRecognitionResult result) { + widget.controller?.text = result.recognizedWords; + if (widget.onChange != null) widget.onChange!(result.recognizedWords); + widget.controller?.text = result.recognizedWords; + if (widget.onSaved != null) widget.onSaved!(result.recognizedWords); + _focusNode.unfocus(); + setState(() {}); + }, + localeId: _settingProvider!.speechToText); + setState(() {}); + } + + void _stopListening() async { + await _speechToText.stop(); + _focusNode.unfocus(); + setState(() {}); + + } + @override Widget build(BuildContext context) { + _settingProvider ??= Provider.of(context, listen: false); final border = UnderlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.circular(10), ); + Widget speechToTextWidget = PopupMenuButton( + child: SizedBox( + height: 24.toScreenHeight, + width: 24.toScreenWidth, + child: "speech_to_text".toSvgAsset(color: context.isDark ? AppColor.neutral10 : AppColor.neutral20, height: 24, width: 24), + ), + onSelected: (String selectedLanguage) { + _settingProvider!.setSpeechToText(selectedLanguage); + _startListening(); + }, + itemBuilder: (BuildContext context) { + return [ + const PopupMenuItem( + value: 'ar', + child: Text('Arabic'), + ), + const PopupMenuItem( + value: 'en', + child: Text('English'), + ), + ]; + }, + ); + final textField = TextFormField( - focusNode: widget.node, + focusNode: _focusNode, enabled: widget.enable, onSaved: (text) { if (widget.onSaved != null && text != null) widget.onSaved!(text); @@ -110,10 +188,11 @@ class _AppTextFormFieldState extends State { focusedBorder: border, enabledBorder: border, errorBorder: border, - contentPadding: widget.contentPadding ?? EdgeInsets.symmetric(vertical: 12.toScreenHeight, horizontal: 16.toScreenWidth), constraints: const BoxConstraints(), - suffixIconConstraints: const BoxConstraints(minWidth: 0), + suffixIconConstraints: const BoxConstraints( + minWidth: 0, + ), filled: true, fillColor: widget.backgroundColor ?? (context.isDark && !widget.enable @@ -124,7 +203,7 @@ class _AppTextFormFieldState extends State { errorStyle: AppTextStyle.tiny.copyWith(color: context.isDark ? AppColor.red50 : AppColor.red60), floatingLabelStyle: AppTextStyle.body1.copyWith(fontWeight: FontWeight.w500, color: context.isDark ? null : AppColor.neutral20), hintText: widget.hintText ?? "", - labelText: widget.labelText ?? "", + labelText: (widget.showSpeechToText && _speechToText.isListening) ? "Listening..." : widget.labelText ?? "", labelStyle: widget.labelStyle, prefixIcon: widget.prefixIcon ?? (widget.prefixIconData == null @@ -134,17 +213,36 @@ class _AppTextFormFieldState extends State { size: widget.prefixIconSize == null ? 20.toScreenWidth : (widget.prefixIconSize! - 10).toScreenWidth, color: AppColor.neutral70, )), - suffixIcon: widget.suffixIcon, + suffixIcon: widget.suffixIcon ?? + (widget.showSpeechToText + ? (_speechToText.isListening + ? SizedBox( + height: 24.toScreenHeight, + width: 24.toScreenWidth, + child: const Icon( + Icons.fiber_manual_record, + color: Colors.red, + )).onPress(() { + // _focusNode.unfocus(); + _stopListening(); + }) + : speechToTextWidget) + .paddingOnly(end: 12, bottom: 50) + : null), ), ); + // + // Widget myWidget = Row( + // children: [textField.expanded, if (widget.showSpeechToText) speechToTextWidget], + // ); + if (widget.showWithoutDecoration) return textField; return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - boxShadow: widget.showShadow ? [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)] : null, - ), - child: textField, - ); + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + boxShadow: widget.showShadow ? [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)] : null, + ), + child: textField); } } diff --git a/lib/new_views/pages/login_page.dart b/lib/new_views/pages/login_page.dart index 54efe6a9..67e75d2d 100644 --- a/lib/new_views/pages/login_page.dart +++ b/lib/new_views/pages/login_page.dart @@ -219,7 +219,7 @@ class _LoginPageState extends State { SizedBox( height: 100.toScreenHeight, ), - "logo_white".toPngAsset(), + "logo_white".toPngAsset(width: 110), 25.height, context.translation.signInToYour.customHeadingText(context).custom(color: Colors.white, fontSize: 27, fontWeight: FontWeight.w500), context.translation.account.customHeadingText(context).custom(color: Colors.white, fontSize: 27, fontWeight: FontWeight.w500), diff --git a/lib/service_request_latest/views/components/history_log_view.dart b/lib/service_request_latest/views/components/history_log_view.dart index 4847767b..c589210e 100644 --- a/lib/service_request_latest/views/components/history_log_view.dart +++ b/lib/service_request_latest/views/components/history_log_view.dart @@ -97,9 +97,9 @@ class HistoryLogView extends StatelessWidget { } String statusText(String status) { - if (status == "new") { + if (status == "new" || status == "open") { return "Open Request".addTranslation; - } else if (status == "in progress") { + } else if (status == "in progress") { return "Status update to In Progress".addTranslation; } else if (status == "closed") { return "Status update to Closed".addTranslation; diff --git a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart index 70dfba35..9bff42ca 100644 --- a/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart +++ b/lib/service_request_latest/views/forms/spare_part/spare_part_request.dart @@ -188,6 +188,7 @@ class _SparePartRequestState extends State with TickerProvider initialValue: requestDetailProvider.sparePartHelperModel?.comment, labelStyle: AppTextStyles.textFieldLabelStyle, controller: _descriptionController, + showSpeechToText: true, backgroundColor: context.isDark ? AppColor.neutral20 : AppColor.neutral90, labelText: context.translation.description, alignLabelWithHint: true,