import 'dart:convert'; import 'dart:io'; import 'package:flutter/services.dart'; import 'package:flutter_text_detect_area/flutter_text_detect_area.dart'; import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:speech_to_text/speech_recognition_result.dart'; import 'package:trans_lark/entity/language_entity.dart'; import 'package:trans_lark/entity/scene_entity.dart'; import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/global/app_tracking_authorization_manager.dart'; import 'package:trans_lark/global/flutter_tts_manager.dart'; import 'package:trans_lark/global/speech_to_text_manager.dart'; import 'package:trans_lark/global/translate_manager.dart'; import 'package:trans_lark/page/settings/settings_widget.dart'; import 'package:trans_lark/router/get_router.dart'; import 'package:trans_lark/util/t_device_utils.dart'; import 'package:trans_lark/util/t_number_utils.dart'; import 'package:trans_lark/util/t_object_utils.dart'; import 'package:trans_lark/util/t_permission_utils.dart'; import 'package:trans_lark/util/t_print.dart'; import 'package:trans_lark/widget/t_base_easy_loading.dart'; import 'package:trans_lark/widget/t_photo_picker_bottom_sheet.dart'; import 'package:trans_lark/widget/t_speak_dialog.dart'; class IndexController extends GetxController { static IndexController get to => Get.find(); var lastWords = ''; var fromLanguage = Rx(null); var toLanguage = Rx(null); var fromStr = Rx(null); var toStr = Rx(null); var languageScene = [ LanguageEntity(languageCode: 'ar', languageName: 'Arabic'), LanguageEntity(languageCode: 'bn', languageName: 'Bengali'), LanguageEntity( languageCode: 'zh-cn', languageName: 'Chinese (Simplified)'), LanguageEntity(languageCode: 'en', languageName: 'English'), LanguageEntity(languageCode: 'fr', languageName: 'French'), LanguageEntity(languageCode: 'de', languageName: 'German'), LanguageEntity(languageCode: 'hi', languageName: 'Hindi'), LanguageEntity(languageCode: 'ja', languageName: 'Japanese'), LanguageEntity(languageCode: 'jv', languageName: 'Javanese'), LanguageEntity(languageCode: 'ko', languageName: 'Korean'), LanguageEntity(languageCode: 'pt', languageName: 'Portuguese'), LanguageEntity(languageCode: 'pa', languageName: 'Punjabi'), LanguageEntity(languageCode: 'ru', languageName: 'Russian'), LanguageEntity(languageCode: 'es', languageName: 'Spanish'), ]; @override void onInit() { super.onInit(); AppTrackingAuthorizationManager().requestTrackingAuthorization(); } @override void onReady() { super.onReady(); getDailyQuoteData(); } Future getDailyQuoteData({int? dataType}) async { LanguageEntity fromLanguageEntity = TranslateManager().fromLanguageEntity.value; LanguageEntity toLanguageEntity = TranslateManager().toLanguageEntity.value; fromLanguage.value = languageScene.firstWhereOrNull( (e) => e.languageCode == fromLanguageEntity.languageCode, ) ?? LanguageEntity( languageCode: 'en', languageName: 'English', ); toLanguage.value = languageScene.firstWhereOrNull( (e) => e.languageCode == toLanguageEntity.languageCode, ) ?? LanguageEntity( languageCode: 'zh-cn', languageName: 'Chinese (Simplified)', ); // final f = NumUtil.getRandomNumber(0, languageScene.length); // final t = NumUtil.getRandomNumberExcludingCurrent(0, languageScene.length, f); // fromLanguage.value = languageScene[f]; // toLanguage.value = languageScene[t]; var data = jsonDecode(await rootBundle.loadString(Assets.jsonTranslationScene)); if (data != null && data is List) { var sceneTypeList = data.map((e) => SceneEntity.fromMap(e)).toList(); if (sceneTypeList.isNotEmpty) { var x = TNumberUtils.getRandomNumber(0, sceneTypeList.length); SceneEntity entity = sceneTypeList[x]; if (entity.sceneList != null && entity.sceneList!.isNotEmpty) { var y = TNumberUtils.getRandomNumber(0, entity.sceneList!.length); fromStr.value = _getSentence(true, entity.sceneList![y]); toStr.value = _getSentence(false, entity.sceneList![y]); } } } } String _getSentence(bool isFrom, SceneList item) { List keys = item.toMap().keys.toList(); int index = 0; for (var i = 0; i < keys.length; ++i) { var e = keys[i]; if (e == (isFrom ? fromLanguage.value?.languageName : toLanguage.value?.languageName)) { index = i; break; } } if (item.toMap().values.toList()[index] != null) { return item.toMap().values.toList()[index]; } return 'loading'; } void translatorTtsPlay(bool isFrom) { if (fromLanguage.value != null && toLanguage.value != null) { FlutterTtsManager().translatorTtsPlay( isFrom ? fromStr.value! : toStr.value!, isFrom ? fromLanguage.value!.languageCode : toLanguage.value!.languageCode, ); } } void openSettingsBottomSheet() { Get.bottomSheet( isScrollControlled: true, SettingsWidget(), ); } void toSceneCategory() { Get.toNamed(GetRouter.sceneCategory); } Future toPhotos() async { Get.bottomSheet( isScrollControlled: true, TPhotoPickerBottomSheet( funCamera: () async { bool result = await TPermissionUtils.checkPermission([Permission.camera]); if (!result) return; _openCameraGallery(ImageSource.camera); }, funGallery: () async { Permission permission = Permission.photos; if (Platform.isAndroid) { int sdkInt = await TDeviceUtils.getAndroidSDKInt(); if (sdkInt <= 32) { permission = Permission.storage; } else { permission = Permission.photos; } } bool result = await TPermissionUtils.checkPermission([permission]); if (!result) return; _openCameraGallery(ImageSource.gallery); }, ), ); } Future _openCameraGallery(ImageSource source) async { String detectedValue = ""; final ImagePicker picker = ImagePicker(); final XFile? photo = await picker.pickImage(source: source); if (photo != null) { Get.to(() => SelectImageAreaTextDetect( detectOnce: true, enableImageInteractions: true, imagePath: photo.path, onDetectText: (v) { if (v is String) { detectedValue = v; } if (v is List) { int counter = 0; for (var element in v) { detectedValue += "$counter. \t\t $element \n\n"; counter++; } } }, onDetectError: (error) { ///This error will occurred in Android only while user will try to crop image at max zoom level then ml kit will throw max 32 height/width exception if (error is PlatformException && (error.message?.contains( "InputImage width and height should be at least 32!") ?? false)) { TBaseEasyLoading.toast( 'Selected area should be able to crop image with at least 32 width and height.'); } }, ))?.then( (onValue) { if (TObjectUtils.isEmpty(detectedValue)) { TBaseEasyLoading.toast('No text recognized'); return; } Get.toNamed( GetRouter.translateResult, arguments: {"sourceText": detectedValue}, ); }, ); } } Future onTapSpeak() async { bool micResult = await TPermissionUtils.checkPermission([Permission.microphone]); if (!micResult) return; if (Platform.isIOS) { bool speechResult = await TPermissionUtils.checkPermission([Permission.speech]); if (!speechResult) return; } await Get.dialog( barrierDismissible: true, useSafeArea: false, TSpeakDialog( isListening: SpeechToTextManager().isListening, onTap: () async { if (!SpeechToTextManager().hasSpeech) { await SpeechToTextManager().init(); } if (SpeechToTextManager().hasSpeech) { if (SpeechToTextManager().isListening.value) { _openTranslatorResultPage(); } else { SpeechToTextManager().startListening( TranslateManager().fromLanguageEntity.value.languageCode, _onSpeechResult); } } else { Get.back(); TBaseEasyLoading.toast('Speech not available'); } }, ), ); if (Get.isDialogOpen != null && !Get.isDialogOpen!) { SpeechToTextManager().stopListening(); } } void _onSpeechResult(SpeechRecognitionResult result) { TPrint.d('识别结果:${result.recognizedWords}'); lastWords = result.recognizedWords; } void _openTranslatorResultPage() { if (TObjectUtils.isEmpty(lastWords)) { TBaseEasyLoading.toast('No text recognized'); return; } Get.back(); Get.toNamed( GetRouter.translateResult, arguments: {"sourceText": lastWords}, ); } void toTranslate() { Get.toNamed(GetRouter.translate); } Future toP2P() async { bool micResult = await TPermissionUtils.checkPermission([Permission.microphone]); if (!micResult) return; if (Platform.isIOS) { bool speechResult = await TPermissionUtils.checkPermission([Permission.speech]); if (!speechResult) return; } Get.toNamed(GetRouter.p2p); } void toTranslateHistory() { Get.toNamed(GetRouter.translateRecord); } }