295 lines
10 KiB
Dart
295 lines
10 KiB
Dart
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<IndexController>();
|
|
var lastWords = '';
|
|
|
|
var fromLanguage = Rx<LanguageEntity?>(null);
|
|
var toLanguage = Rx<LanguageEntity?>(null);
|
|
var fromStr = Rx<String?>(null);
|
|
var toStr = Rx<String?>(null);
|
|
var languageScene = <LanguageEntity>[
|
|
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<void> 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<void> 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<void> _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<void> 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<void> 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);
|
|
}
|
|
}
|