This commit is contained in:
xh 2024-07-24 11:59:36 +08:00
parent db01a24756
commit 1eb6ed4546
68 changed files with 1484 additions and 1639 deletions

View File

@ -2,8 +2,7 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:app_tracking_transparency/app_tracking_transparency.dart'; import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:flutter/material.dart'; import 'package:trans_lark/util/t_print.dart';
import 'package:trans_lark/util/log_print.dart';
class AppTrackingAuthorizationManager { class AppTrackingAuthorizationManager {
AppTrackingAuthorizationManager._(); AppTrackingAuthorizationManager._();
@ -23,7 +22,7 @@ class AppTrackingAuthorizationManager {
if (status == TrackingStatus.notDetermined) { if (status == TrackingStatus.notDetermined) {
if (_timer != null && _timer!.isActive) { if (_timer != null && _timer!.isActive) {
final TrackingStatus status = await AppTrackingTransparency.requestTrackingAuthorization(); final TrackingStatus status = await AppTrackingTransparency.requestTrackingAuthorization();
LogPrint.d('跟踪授权状态: $status'); TPrint.d('跟踪授权状态: $status');
} else { } else {
_startTimer(); _startTimer();
} }

View File

@ -1,20 +1,20 @@
import 'package:flutter_tts/flutter_tts.dart'; import 'package:flutter_tts/flutter_tts.dart';
import 'package:trans_lark/util/log_print.dart'; import 'package:trans_lark/util/t_print.dart';
import 'package:trans_lark/widget/base_easyloading.dart'; import 'package:trans_lark/widget/t_base_easy_loading.dart';
class FlutterTtsManager { class FlutterTtsManager {
FlutterTtsManager._(); FlutterTtsManager._();
static final FlutterTtsManager _instance = FlutterTtsManager._();
factory FlutterTtsManager() { factory FlutterTtsManager() {
return _instance; return _instance;
} }
static final FlutterTtsManager _instance = FlutterTtsManager._();
late FlutterTts ttsController; late FlutterTts ttsController;
Future<void> init() async { Future<void> init() async {
LogPrint.d("TTS Service init start"); TPrint.d("TTS Service init start");
ttsController = FlutterTts(); ttsController = FlutterTts();
await ttsController.setSharedInstance(true); await ttsController.setSharedInstance(true);
await ttsController.setIosAudioCategory( await ttsController.setIosAudioCategory(
@ -27,7 +27,7 @@ class FlutterTtsManager {
IosTextToSpeechAudioMode.voicePrompt); IosTextToSpeechAudioMode.voicePrompt);
await ttsController.awaitSpeakCompletion(true); await ttsController.awaitSpeakCompletion(true);
await ttsController.awaitSynthCompletion(true); await ttsController.awaitSynthCompletion(true);
LogPrint.d("TTS Service init success"); TPrint.d("TTS Service init success");
} }
Future<void> translatorTtsPlay(String text, String language) async { Future<void> translatorTtsPlay(String text, String language) async {
@ -36,7 +36,7 @@ class FlutterTtsManager {
await ttsController.setLanguage(language); await ttsController.setLanguage(language);
await ttsController.speak(text); await ttsController.speak(text);
} catch (e) { } catch (e) {
BaseEasyLoading.toast('This language cannot be played'); TBaseEasyLoading.toast('This language cannot be played');
return; return;
} }
} }

View File

@ -1,53 +1,41 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:speech_to_text/speech_recognition_error.dart'; import 'package:speech_to_text/speech_recognition_error.dart';
import 'package:speech_to_text/speech_to_text.dart'; import 'package:speech_to_text/speech_to_text.dart';
import 'package:trans_lark/util/log_print.dart'; import 'package:trans_lark/util/t_print.dart';
import 'package:trans_lark/widget/base_easyloading.dart'; import 'package:trans_lark/widget/t_base_easy_loading.dart';
class SpeechToTextManager { class SpeechToTextManager {
static final SpeechToTextManager _instance = SpeechToTextManager._(); static final SpeechToTextManager _instance = SpeechToTextManager._();
SpeechToTextManager._();
factory SpeechToTextManager() { factory SpeechToTextManager() {
return _instance; return _instance;
} }
SpeechToTextManager._();
final _speechToText = SpeechToText(); final _speechToText = SpeechToText();
var hasSpeech = false;
var isListening = false.obs;
Future<void> initSpeech() async { var isListening = false.obs;
var hasSpeech = false;
Future<void> init() async {
try { try {
BaseEasyLoading.loading(); TBaseEasyLoading.loading();
hasSpeech = await _speechToText.initialize( hasSpeech = await _speechToText.initialize(
onStatus: _statusListener, onStatus: _statusListener,
onError: _errorListener, onError: _errorListener,
); );
BaseEasyLoading.dismiss(); TBaseEasyLoading.dismiss();
_speechToText.statusListener ??= _statusListener; _speechToText.statusListener ??= _statusListener;
_speechToText.errorListener ??= _errorListener; _speechToText.errorListener ??= _errorListener;
} catch (e) { } catch (e) {
LogPrint.d('Speech recognition failed: ${e.toString()}'); TPrint.d('Speech recognition failed: ${e.toString()}');
} }
} }
void _statusListener(String status) { Future<void> startListening(
LogPrint.d('状态:$status'); String localeId, SpeechResultListener onResult) async {
if (status == 'listening') { TBaseEasyLoading.loading();
isListening.value = true;
} else {
isListening.value = false;
}
}
void _errorListener(SpeechRecognitionError error) {
LogPrint.d('Received error status: $error, listening: ${_speechToText.isListening}');
BaseEasyLoading.toast('Speech recognition failed: ${error.errorMsg}');
}
Future<void> startListening(String localeId, SpeechResultListener onResult) async {
BaseEasyLoading.loading();
try { try {
await _speechToText.listen( await _speechToText.listen(
onResult: onResult, onResult: onResult,
@ -60,22 +48,39 @@ class SpeechToTextManager {
listenMode: ListenMode.dictation, listenMode: ListenMode.dictation,
), ),
); );
BaseEasyLoading.dismiss(); TBaseEasyLoading.dismiss();
} catch (e) { } catch (e) {
if (e.runtimeType == ListenFailedException) { if (e.runtimeType == ListenFailedException) {
LogPrint.d('speechToText.listen${(e as ListenFailedException).message}'); TPrint.d(
'speechToText.listen${(e as ListenFailedException).message}');
} else { } else {
LogPrint.d('speechToText.listen${e.toString()}'); TPrint.d('speechToText.listen${e.toString()}');
} }
BaseEasyLoading.toast('The current language does not support speech recognition'); TBaseEasyLoading.toast(
'The current language does not support speech recognition');
} }
} }
void _statusListener(String status) {
TPrint.d('状态:$status');
if (status == 'listening') {
isListening.value = true;
} else {
isListening.value = false;
}
}
void _errorListener(SpeechRecognitionError error) {
TPrint.d(
'Received error status: $error, listening: ${_speechToText.isListening}');
TBaseEasyLoading.toast('Speech recognition failed: ${error.errorMsg}');
}
Future<void> stopListening() async { Future<void> stopListening() async {
if (isListening.value) { if (isListening.value) {
BaseEasyLoading.loading(); TBaseEasyLoading.loading();
await _speechToText.stop(); await _speechToText.stop();
BaseEasyLoading.dismiss(); TBaseEasyLoading.dismiss();
} }
} }
} }

View File

@ -6,20 +6,23 @@ import 'package:flutter/services.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/entity/language_entity.dart'; import 'package:trans_lark/entity/language_entity.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/util/num_util.dart'; import 'package:trans_lark/util/t_number_utils.dart';
class TranslateManager { class TranslateManager {
TranslateManager._(); TranslateManager._();
static final TranslateManager _instance = TranslateManager._();
factory TranslateManager() { factory TranslateManager() {
return _instance; return _instance;
} }
static final TranslateManager _instance = TranslateManager._();
/// ///
var languageList = <LanguageEntity>[].obs; var languageList = <LanguageEntity>[].obs;
///
var isSelectFromLanguage = true.obs;
/// ///
var fromLanguageEntity = LanguageEntity( var fromLanguageEntity = LanguageEntity(
languageCode: 'en', languageCode: 'en',
@ -32,9 +35,6 @@ class TranslateManager {
languageName: 'Chinese (Simplified)', languageName: 'Chinese (Simplified)',
).obs; ).obs;
///
var isSelectFromLanguage = true.obs;
Future<void> init() async { Future<void> init() async {
var data = jsonDecode(await rootBundle.loadString(Assets.jsonLanguage)); var data = jsonDecode(await rootBundle.loadString(Assets.jsonLanguage));
if (data != null && data is List) { if (data != null && data is List) {
@ -56,7 +56,7 @@ class TranslateManager {
break; break;
} }
} }
var num = NumUtil.getRandomNumberExcludingCurrent(0, languageList.length, index); var num = TNumberUtils.getRandomNumberExcludingCurrent(0, languageList.length, index);
fromLanguageEntity.value = languageList[num].copyWith(); fromLanguageEntity.value = languageList[num].copyWith();
} }
} }

View File

@ -1,7 +1,7 @@
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:trans_lark/entity/history_model.dart'; import 'package:trans_lark/entity/history_model.dart';
import 'package:trans_lark/storage/hive_storage.dart'; import 'package:trans_lark/hive/hive_storage.dart';
import 'package:trans_lark/util/date_util.dart'; import 'package:trans_lark/util/t_date_utils.dart';
class HistoryData { class HistoryData {
/// ///
@ -20,35 +20,35 @@ class HistoryData {
final _box = getHistoryBox(); final _box = getHistoryBox();
/// ///
List<HistoryEntity> getList() { List<HistoryEntity> getAllHistory() {
return _box.values.toList(); return _box.values.toList();
} }
/// ///
Map<String, List<HistoryEntity>> getGroupByList() { Map<String, List<HistoryEntity>> getMapList() {
// 使 groupBy // 使 groupBy
var groupedEvents = groupBy( var groupedEvents = groupBy(
getList().reversed.toList(), getAllHistory().reversed.toList(),
(HistoryEntity event) => DateUtil.formatDateMs( (HistoryEntity event) => TDateUtils.formatDateMs(
event.translationTime ?? DateUtil.getNowTimestamp(), event.translationTime ?? TDateUtils.getNowTimestamp(),
format: DateFormats.yMoD)); format: DateFormats.yMoD));
return groupedEvents; return groupedEvents;
} }
/// ///
Future<int> addData(HistoryEntity entity) async { Future<int> addHistory(HistoryEntity entity, {int? index}) async {
entity.translationTime = DateUtil.getNowTimestamp(); entity.translationTime = TDateUtils.getNowTimestamp();
return await _box.add(entity); return await _box.add(entity);
} }
/// ///
Future<void> delete(int index) async { Future<void> deleteHistory(int index, {HistoryEntity? entity}) async {
await _box.deleteAt(index); await _box.deleteAt(index);
await _box.flush(); await _box.flush();
} }
/// ///
Future<void> clear() async { Future<void> clearHistory() async {
await _box.clear(); await _box.clear();
await _box.flush(); await _box.flush();
} }

View File

@ -8,9 +8,10 @@ import 'package:get/get.dart';
import 'package:trans_lark/global/flutter_tts_manager.dart'; import 'package:trans_lark/global/flutter_tts_manager.dart';
import 'package:trans_lark/global/global_config.dart'; import 'package:trans_lark/global/global_config.dart';
import 'package:trans_lark/global/translate_manager.dart'; import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/router/router.dart'; import 'package:trans_lark/hive/hive_storage.dart';
import 'package:trans_lark/storage/hive_storage.dart'; import 'package:trans_lark/router/get_router.dart';
import 'package:trans_lark/widget/base_easyloading.dart'; import 'package:trans_lark/util/t_print.dart';
import 'package:trans_lark/widget/t_base_easy_loading.dart';
void main() async { void main() async {
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
@ -53,16 +54,18 @@ class MyApp extends StatelessWidget {
), ),
useMaterial3: true, useMaterial3: true,
), ),
initialRoute: GetRouter.home, initialRoute: GetRouter.index,
getPages: GetRouter.routers, getPages: GetRouter.routers,
defaultTransition: Transition.rightToLeft, defaultTransition: Transition.rightToLeft,
builder: (context, widget) { builder: (context, widget) {
BaseEasyLoading.configLoading(); TBaseEasyLoading.configLoading();
widget = easyLoading(context, widget); widget = easyLoading(context, widget);
// //
return MediaQuery.withNoTextScaling(child: widget); return MediaQuery.withNoTextScaling(child: widget);
}, },
), routingCallback: (routing) {
TPrint.d("路由变化 ${routing?.current}");
}),
); );
} }
} }

View File

@ -1,9 +0,0 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/face_to_face/face_to_face_controller.dart';
class FaceToFaceBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => FaceToFaceController());
}
}

View File

@ -14,42 +14,25 @@ import 'package:trans_lark/global/app_tracking_authorization_manager.dart';
import 'package:trans_lark/global/flutter_tts_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/speech_to_text_manager.dart';
import 'package:trans_lark/global/translate_manager.dart'; import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/page/settings/settings_view.dart'; import 'package:trans_lark/page/settings/settings_widget.dart';
import 'package:trans_lark/router/router.dart'; import 'package:trans_lark/router/get_router.dart';
import 'package:trans_lark/util/device_info_util.dart'; import 'package:trans_lark/util/t_device_utils.dart';
import 'package:trans_lark/util/log_print.dart'; import 'package:trans_lark/util/t_number_utils.dart';
import 'package:trans_lark/util/num_util.dart'; import 'package:trans_lark/util/t_object_utils.dart';
import 'package:trans_lark/util/obj_util.dart'; import 'package:trans_lark/util/t_permission_utils.dart';
import 'package:trans_lark/util/permission_util.dart'; import 'package:trans_lark/util/t_print.dart';
import 'package:trans_lark/widget/base_easyloading.dart'; import 'package:trans_lark/widget/t_base_easy_loading.dart';
import 'package:trans_lark/widget/photo_picker_bottom_sheet.dart'; import 'package:trans_lark/widget/t_photo_picker_bottom_sheet.dart';
import 'package:trans_lark/widget/speak_dialog.dart'; import 'package:trans_lark/widget/t_speak_dialog.dart';
class HomeLogic extends GetxController { class IndexController extends GetxController {
static HomeLogic get to => Get.find<HomeLogic>(); static IndexController get to => Get.find<IndexController>();
var lastWords = ''; var lastWords = '';
var fromLanguage = Rx<LanguageEntity?>(null); var fromLanguage = Rx<LanguageEntity?>(null);
var toLanguage = Rx<LanguageEntity?>(null); var toLanguage = Rx<LanguageEntity?>(null);
var fromStr = Rx<String?>(null); var fromStr = Rx<String?>(null);
var toStr = Rx<String?>(null); var toStr = Rx<String?>(null);
@override
void onInit() {
super.onInit();
AppTrackingAuthorizationManager().requestTrackingAuthorization();
}
@override
void onReady() {
super.onReady();
getDailyQuote();
}
Future<void> getDailyQuote() async {
LanguageEntity fromLanguageEntity =
TranslateManager().fromLanguageEntity.value;
LanguageEntity toLanguageEntity = TranslateManager().toLanguageEntity.value;
var languageScene = <LanguageEntity>[ var languageScene = <LanguageEntity>[
LanguageEntity(languageCode: 'ar', languageName: 'Arabic'), LanguageEntity(languageCode: 'ar', languageName: 'Arabic'),
LanguageEntity(languageCode: 'bn', languageName: 'Bengali'), LanguageEntity(languageCode: 'bn', languageName: 'Bengali'),
@ -67,6 +50,23 @@ class HomeLogic extends GetxController {
LanguageEntity(languageCode: 'ru', languageName: 'Russian'), LanguageEntity(languageCode: 'ru', languageName: 'Russian'),
LanguageEntity(languageCode: 'es', languageName: 'Spanish'), 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( fromLanguage.value = languageScene.firstWhereOrNull(
(e) => e.languageCode == fromLanguageEntity.languageCode, (e) => e.languageCode == fromLanguageEntity.languageCode,
) ?? ) ??
@ -91,10 +91,10 @@ class HomeLogic extends GetxController {
if (data != null && data is List) { if (data != null && data is List) {
var sceneTypeList = data.map((e) => SceneEntity.fromMap(e)).toList(); var sceneTypeList = data.map((e) => SceneEntity.fromMap(e)).toList();
if (sceneTypeList.isNotEmpty) { if (sceneTypeList.isNotEmpty) {
var x = NumUtil.getRandomNumber(0, sceneTypeList.length); var x = TNumberUtils.getRandomNumber(0, sceneTypeList.length);
SceneEntity entity = sceneTypeList[x]; SceneEntity entity = sceneTypeList[x];
if (entity.sceneList != null && entity.sceneList!.isNotEmpty) { if (entity.sceneList != null && entity.sceneList!.isNotEmpty) {
var y = NumUtil.getRandomNumber(0, entity.sceneList!.length); var y = TNumberUtils.getRandomNumber(0, entity.sceneList!.length);
fromStr.value = _getSentence(true, entity.sceneList![y]); fromStr.value = _getSentence(true, entity.sceneList![y]);
toStr.value = _getSentence(false, entity.sceneList![y]); toStr.value = _getSentence(false, entity.sceneList![y]);
} }
@ -132,38 +132,38 @@ class HomeLogic extends GetxController {
} }
} }
void openSettings() { void openSettingsBottomSheet() {
Get.bottomSheet( Get.bottomSheet(
isScrollControlled: true, isScrollControlled: true,
SettingsView(), SettingsWidget(),
); );
} }
void openSceneType() { void toSceneCategory() {
Get.toNamed(GetRouter.sceneType); Get.toNamed(GetRouter.sceneCategory);
} }
Future<void> onTapPhotos() async { Future<void> toPhotos() async {
Get.bottomSheet( Get.bottomSheet(
isScrollControlled: true, isScrollControlled: true,
PhotoPickerBottomSheet( TPhotoPickerBottomSheet(
funCamera: () async { funCamera: () async {
bool result = bool result =
await PermissionUtil.checkPermission([Permission.camera]); await TPermissionUtils.checkPermission([Permission.camera]);
if (!result) return; if (!result) return;
_openCameraGallery(ImageSource.camera); _openCameraGallery(ImageSource.camera);
}, },
funGallery: () async { funGallery: () async {
Permission permission = Permission.photos; Permission permission = Permission.photos;
if (Platform.isAndroid) { if (Platform.isAndroid) {
int sdkInt = await DeviceInfoUtil.getAndroidSDKInt(); int sdkInt = await TDeviceUtils.getAndroidSDKInt();
if (sdkInt <= 32) { if (sdkInt <= 32) {
permission = Permission.storage; permission = Permission.storage;
} else { } else {
permission = Permission.photos; permission = Permission.photos;
} }
} }
bool result = await PermissionUtil.checkPermission([permission]); bool result = await TPermissionUtils.checkPermission([permission]);
if (!result) return; if (!result) return;
_openCameraGallery(ImageSource.gallery); _openCameraGallery(ImageSource.gallery);
}, },
@ -198,14 +198,14 @@ class HomeLogic extends GetxController {
(error.message?.contains( (error.message?.contains(
"InputImage width and height should be at least 32!") ?? "InputImage width and height should be at least 32!") ??
false)) { false)) {
BaseEasyLoading.toast( TBaseEasyLoading.toast(
'Selected area should be able to crop image with at least 32 width and height.'); 'Selected area should be able to crop image with at least 32 width and height.');
} }
}, },
))?.then( ))?.then(
(onValue) { (onValue) {
if (ObjUtil.isEmpty(detectedValue)) { if (TObjectUtils.isEmpty(detectedValue)) {
BaseEasyLoading.toast('No text recognized'); TBaseEasyLoading.toast('No text recognized');
return; return;
} }
Get.toNamed( Get.toNamed(
@ -219,21 +219,21 @@ class HomeLogic extends GetxController {
Future<void> onTapSpeak() async { Future<void> onTapSpeak() async {
bool micResult = bool micResult =
await PermissionUtil.checkPermission([Permission.microphone]); await TPermissionUtils.checkPermission([Permission.microphone]);
if (!micResult) return; if (!micResult) return;
if (Platform.isIOS) { if (Platform.isIOS) {
bool speechResult = bool speechResult =
await PermissionUtil.checkPermission([Permission.speech]); await TPermissionUtils.checkPermission([Permission.speech]);
if (!speechResult) return; if (!speechResult) return;
} }
await Get.dialog( await Get.dialog(
barrierDismissible: true, barrierDismissible: true,
useSafeArea: false, useSafeArea: false,
SpeakDialog( TSpeakDialog(
isListening: SpeechToTextManager().isListening, isListening: SpeechToTextManager().isListening,
onTap: () async { onTap: () async {
if (!SpeechToTextManager().hasSpeech) { if (!SpeechToTextManager().hasSpeech) {
await SpeechToTextManager().initSpeech(); await SpeechToTextManager().init();
} }
if (SpeechToTextManager().hasSpeech) { if (SpeechToTextManager().hasSpeech) {
if (SpeechToTextManager().isListening.value) { if (SpeechToTextManager().isListening.value) {
@ -245,7 +245,7 @@ class HomeLogic extends GetxController {
} }
} else { } else {
Get.back(); Get.back();
BaseEasyLoading.toast('Speech not available'); TBaseEasyLoading.toast('Speech not available');
} }
}, },
), ),
@ -256,13 +256,13 @@ class HomeLogic extends GetxController {
} }
void _onSpeechResult(SpeechRecognitionResult result) { void _onSpeechResult(SpeechRecognitionResult result) {
LogPrint.d('识别结果:${result.recognizedWords}'); TPrint.d('识别结果:${result.recognizedWords}');
lastWords = result.recognizedWords; lastWords = result.recognizedWords;
} }
void _openTranslatorResultPage() { void _openTranslatorResultPage() {
if (ObjUtil.isEmpty(lastWords)) { if (TObjectUtils.isEmpty(lastWords)) {
BaseEasyLoading.toast('No text recognized'); TBaseEasyLoading.toast('No text recognized');
return; return;
} }
Get.back(); Get.back();
@ -272,23 +272,23 @@ class HomeLogic extends GetxController {
); );
} }
void openTranslate() { void toTranslate() {
Get.toNamed(GetRouter.translate); Get.toNamed(GetRouter.translate);
} }
Future<void> openFaceToFace() async { Future<void> toP2P() async {
bool micResult = bool micResult =
await PermissionUtil.checkPermission([Permission.microphone]); await TPermissionUtils.checkPermission([Permission.microphone]);
if (!micResult) return; if (!micResult) return;
if (Platform.isIOS) { if (Platform.isIOS) {
bool speechResult = bool speechResult =
await PermissionUtil.checkPermission([Permission.speech]); await TPermissionUtils.checkPermission([Permission.speech]);
if (!speechResult) return; if (!speechResult) return;
} }
Get.toNamed(GetRouter.faceToFace); Get.toNamed(GetRouter.p2p);
} }
void openTranslateHistory() { void toTranslateHistory() {
Get.toNamed(GetRouter.translateHistory); Get.toNamed(GetRouter.translateRecord);
} }
} }

View File

@ -2,14 +2,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/page/home/home_logic.dart'; import 'package:trans_lark/page/index/index_controller.dart';
import 'package:trans_lark/util/obj_util.dart'; import 'package:trans_lark/util/t_object_utils.dart';
import 'package:trans_lark/widget/language_bar.dart'; import 'package:trans_lark/widget/t_language_bar_widget.dart';
class HomePage extends StatelessWidget { class IndexView extends StatelessWidget {
final HomeLogic logic = Get.put(HomeLogic()); final IndexController logic = Get.put(IndexController());
HomePage({super.key}); IndexView({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -59,7 +59,7 @@ class HomePage extends StatelessWidget {
), ),
), ),
GestureDetector( GestureDetector(
onTap: logic.openSettings, onTap: logic.openSettingsBottomSheet,
child: ClipOval( child: ClipOval(
child: Container( child: Container(
width: 32, width: 32,
@ -85,7 +85,7 @@ class HomePage extends StatelessWidget {
return Stack( return Stack(
children: [ children: [
GestureDetector( GestureDetector(
onTap: logic.openSceneType, onTap: logic.toSceneCategory,
child: Column( child: Column(
children: [ children: [
const SizedBox(height: 30), const SizedBox(height: 30),
@ -104,7 +104,7 @@ class HomePage extends StatelessWidget {
top: 46, top: 46,
left: 20, left: 20,
child: GestureDetector( child: GestureDetector(
onTap: logic.openSceneType, onTap: logic.toSceneCategory,
child: Row( child: Row(
children: [ children: [
const Text( const Text(
@ -173,7 +173,7 @@ class HomePage extends StatelessWidget {
Expanded( Expanded(
child: Obx(() { child: Obx(() {
return Text( return Text(
ObjUtil.getStr(logic.fromStr.value), TObjectUtils.getStr(logic.fromStr.value),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: const TextStyle( style: const TextStyle(
fontSize: 16, fontSize: 16,
@ -235,7 +235,7 @@ class HomePage extends StatelessWidget {
Expanded( Expanded(
child: Obx(() { child: Obx(() {
return Text( return Text(
ObjUtil.getStr(logic.toStr.value), TObjectUtils.getStr(logic.toStr.value),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: const TextStyle( style: const TextStyle(
fontSize: 16, fontSize: 16,
@ -286,7 +286,7 @@ class HomePage extends StatelessWidget {
Column( Column(
children: [ children: [
GestureDetector( GestureDetector(
onTap: logic.onTapPhotos, onTap: logic.toPhotos,
child: Container( child: Container(
width: 72, width: 72,
height: 72, height: 72,
@ -316,7 +316,7 @@ class HomePage extends StatelessWidget {
Column( Column(
children: [ children: [
GestureDetector( GestureDetector(
onTap: logic.openFaceToFace, onTap: logic.toP2P,
child: Container( child: Container(
width: 72, width: 72,
height: 72, height: 72,
@ -346,7 +346,7 @@ class HomePage extends StatelessWidget {
Column( Column(
children: [ children: [
GestureDetector( GestureDetector(
onTap: logic.openTranslateHistory, onTap: logic.toTranslateHistory,
child: Container( child: Container(
width: 72, width: 72,
height: 72, height: 72,
@ -381,7 +381,7 @@ class HomePage extends StatelessWidget {
return Column( return Column(
children: [ children: [
GestureDetector( GestureDetector(
onTap: logic.openTranslate, onTap: logic.toTranslate,
child: Container( child: Container(
height: 76, height: 76,
alignment: Alignment.center, alignment: Alignment.center,
@ -438,7 +438,7 @@ class HomePage extends StatelessWidget {
), ),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
const LanguageBar(), const TLanguageBarWidget(),
const SizedBox(height: 20), const SizedBox(height: 20),
], ],
); );

View File

@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/p2p/p2p_controller.dart';
class P2PBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => P2PController());
}
}

View File

@ -2,32 +2,33 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:speech_to_text/speech_recognition_result.dart'; import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:trans_lark/global/translate_manager.dart'; import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/util/log_print.dart'; import 'package:trans_lark/util/t_object_utils.dart';
import 'package:trans_lark/util/t_print.dart';
import 'package:trans_lark/widget/t_base_easy_loading.dart';
import 'package:translator/translator.dart'; import 'package:translator/translator.dart';
import 'package:trans_lark/global/speech_to_text_manager.dart'; import 'package:trans_lark/global/speech_to_text_manager.dart';
import 'package:trans_lark/util/obj_util.dart';
import 'package:trans_lark/widget/base_easyloading.dart';
class FaceToFaceController extends GetxController with GetSingleTickerProviderStateMixin{ class P2PController extends GetxController
with GetSingleTickerProviderStateMixin {
final aboveScrollController = ScrollController(); final aboveScrollController = ScrollController();
final underScrollController = ScrollController(); final underScrollController = ScrollController();
var angle = 0.0.obs; var angle = 0.0.obs;
///
final _translator = GoogleTranslator();
/// ///
var aboveText = ''.obs; var aboveText = ''.obs;
var underText = ''.obs; var underText = ''.obs;
///
final _translator = GoogleTranslator();
/// ///
var selectedUnder = true.obs; var selectedUnder = true.obs;
@override @override
void onReady() async { void onReady() async {
super.onReady(); super.onReady();
onTapSpeak(true); onSpeak(true);
} }
@override @override
@ -38,19 +39,19 @@ class FaceToFaceController extends GetxController with GetSingleTickerProviderSt
super.onClose(); super.onClose();
} }
Future<void> onBackTap() async { Future<void> onBack() async {
await SpeechToTextManager().stopListening(); await SpeechToTextManager().stopListening();
Get.back(); Get.back();
} }
/// 180 /// 180
void onTapRotate() { void onRotate() {
angle.value -= 0.5; angle.value -= 0.5;
} }
Future<void> onTapSpeak(bool isUnder) async { Future<void> onSpeak(bool isUnder, {int? speakType}) async {
if (!SpeechToTextManager().hasSpeech) { if (!SpeechToTextManager().hasSpeech) {
await SpeechToTextManager().initSpeech(); await SpeechToTextManager().init();
} }
if (SpeechToTextManager().hasSpeech) { if (SpeechToTextManager().hasSpeech) {
if (isUnder) { if (isUnder) {
@ -59,35 +60,38 @@ class FaceToFaceController extends GetxController with GetSingleTickerProviderSt
} }
selectedUnder.value = true; selectedUnder.value = true;
_scrollToBottom(); _scrollToBottom();
SpeechToTextManager().startListening(TranslateManager().fromLanguageEntity.value.languageCode, _onSpeechResult); SpeechToTextManager().startListening(
TranslateManager().fromLanguageEntity.value.languageCode,
_speechRes);
} else { } else {
if (selectedUnder.value) { if (selectedUnder.value) {
await SpeechToTextManager().stopListening(); await SpeechToTextManager().stopListening();
} }
selectedUnder.value = false; selectedUnder.value = false;
_scrollToBottom(); _scrollToBottom();
SpeechToTextManager().startListening(TranslateManager().toLanguageEntity.value.languageCode, _onSpeechResult); SpeechToTextManager().startListening(
TranslateManager().toLanguageEntity.value.languageCode, _speechRes);
} }
} else { } else {
BaseEasyLoading.toast('Speech not available'); TBaseEasyLoading.toast('Speech not available');
} }
} }
Future<void> _onSpeechResult(SpeechRecognitionResult result) async { Future<void> _speechRes(SpeechRecognitionResult result) async {
LogPrint.d('识别结果:${result.recognizedWords}'); TPrint.d('识别结果:${result.recognizedWords}');
if (ObjUtil.isNotEmptyStr(result.recognizedWords)) { if (TObjectUtils.isNotEmptyStr(result.recognizedWords)) {
if (selectedUnder.value) { if (selectedUnder.value) {
underText.value += '${result.recognizedWords}\n'; underText.value += '${result.recognizedWords}\n';
var translateText = await _translation(result.recognizedWords); var translateText = await _translation(result.recognizedWords);
LogPrint.d('翻译结果:${result.recognizedWords}'); TPrint.d('翻译结果:${result.recognizedWords}');
if (ObjUtil.isNotEmptyStr(translateText)) { if (TObjectUtils.isNotEmptyStr(translateText)) {
aboveText.value += '$translateText\n'; aboveText.value += '$translateText\n';
} }
} else { } else {
aboveText.value += '${result.recognizedWords}\n'; aboveText.value += '${result.recognizedWords}\n';
var translateText = await _translation(result.recognizedWords); var translateText = await _translation(result.recognizedWords);
LogPrint.d('翻译结果:${result.recognizedWords}'); TPrint.d('翻译结果:${result.recognizedWords}');
if (ObjUtil.isNotEmptyStr(translateText)) { if (TObjectUtils.isNotEmptyStr(translateText)) {
underText.value += '$translateText\n'; underText.value += '$translateText\n';
} }
} }
@ -95,10 +99,14 @@ class FaceToFaceController extends GetxController with GetSingleTickerProviderSt
} }
} }
Future<String> _translation(String sourceText) async { Future<String> _translation(String sourceText, {int? translationType}) async {
try { try {
String from = selectedUnder.value ? TranslateManager().fromLanguageEntity.value.languageCode : TranslateManager().toLanguageEntity.value.languageCode; String from = selectedUnder.value
String to = selectedUnder.value ? TranslateManager().toLanguageEntity.value.languageCode : TranslateManager().fromLanguageEntity.value.languageCode; ? TranslateManager().fromLanguageEntity.value.languageCode
: TranslateManager().toLanguageEntity.value.languageCode;
String to = selectedUnder.value
? TranslateManager().toLanguageEntity.value.languageCode
: TranslateManager().fromLanguageEntity.value.languageCode;
Translation translate = await _translator.translate( Translation translate = await _translator.translate(
sourceText, sourceText,
from: from, from: from,
@ -106,7 +114,7 @@ class FaceToFaceController extends GetxController with GetSingleTickerProviderSt
); );
return translate.text; return translate.text;
} catch (e) { } catch (e) {
LogPrint.d('Translation failed,${e.toString()}'); TPrint.d('Translation failed,${e.toString()}');
} }
return ''; return '';
} }

View File

@ -1,34 +1,46 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/global/speech_to_text_manager.dart'; import 'package:trans_lark/global/speech_to_text_manager.dart';
import 'package:trans_lark/page/face_to_face/face_to_face_controller.dart'; import 'package:trans_lark/page/p2p/p2p_controller.dart';
import 'package:trans_lark/util/obj_util.dart'; import 'package:trans_lark/util/t_object_utils.dart';
import 'package:trans_lark/widget/base_appbar.dart'; import 'package:trans_lark/widget/t_base_appbar_widget.dart';
import 'package:wave/config.dart'; import 'package:wave/config.dart';
import 'package:wave/wave.dart'; import 'package:wave/wave.dart';
class FaceToFaceView extends GetView<FaceToFaceController> { class P2PView extends GetView<P2PController> {
const FaceToFaceView({super.key}); const P2PView({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
extendBodyBehindAppBar: true,
extendBody: true, extendBody: true,
extendBodyBehindAppBar: true,
backgroundColor: Colors.black, backgroundColor: Colors.black,
appBar: BaseAppBar( appBar: _buildAppBar(),
body: Column(
children: [
_buildAbove(context),
_buildUnder(context),
],
),
);
}
TBaseAppbarWidget _buildAppBar() {
return TBaseAppbarWidget(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
backColor: Colors.white, backColor: Colors.white,
onBackTap: controller.onBackTap, onBackTap: controller.onBack,
actionWidget: Padding( actionWidget: Padding(
padding: const EdgeInsets.only(right: 10), padding: const EdgeInsets.only(right: 10),
child: ClipOval( child: ClipOval(
child: Material( child: Material(
color: Colors.transparent, color: Colors.transparent,
child: InkWell( child: InkWell(
onTap: controller.onTapRotate, onTap: controller.onRotate,
child: Padding( child: Padding(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
child: SvgPicture.asset( child: SvgPicture.asset(
@ -41,13 +53,6 @@ class FaceToFaceView extends GetView<FaceToFaceController> {
), ),
), ),
), ),
),
body: Column(
children: [
_buildAbove(context),
_buildUnder(context),
],
),
); );
} }
@ -55,7 +60,7 @@ class FaceToFaceView extends GetView<FaceToFaceController> {
return Expanded( return Expanded(
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTap: () => controller.onTapSpeak(false), onTap: () => controller.onSpeak(false),
child: SizedBox( child: SizedBox(
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
height: double.infinity, height: double.infinity,
@ -124,7 +129,7 @@ class FaceToFaceView extends GetView<FaceToFaceController> {
Flexible( Flexible(
child: Visibility( child: Visibility(
visible: SpeechToTextManager().isListening.value && visible: SpeechToTextManager().isListening.value &&
ObjUtil.isNotEmptyStr( TObjectUtils.isNotEmptyStr(
controller.aboveText.value), controller.aboveText.value),
replacement: const Text( replacement: const Text(
'Please start talking', 'Please start talking',
@ -163,7 +168,7 @@ class FaceToFaceView extends GetView<FaceToFaceController> {
return Expanded( return Expanded(
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
onTap: () => controller.onTapSpeak(true), onTap: () => controller.onSpeak(true),
child: SizedBox( child: SizedBox(
width: MediaQuery.of(context).size.width, width: MediaQuery.of(context).size.width,
height: double.infinity, height: double.infinity,
@ -223,7 +228,8 @@ class FaceToFaceView extends GetView<FaceToFaceController> {
Flexible( Flexible(
child: Visibility( child: Visibility(
visible: SpeechToTextManager().isListening.value && visible: SpeechToTextManager().isListening.value &&
ObjUtil.isNotEmptyStr(controller.underText.value), TObjectUtils.isNotEmptyStr(
controller.underText.value),
replacement: const Text( replacement: const Text(
'Please start talking', 'Please start talking',
style: TextStyle( style: TextStyle(

View File

@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/scene_category/scene_category_controller.dart';
class SceneCategoryBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => SceneCategoryController());
}
}

View File

@ -4,17 +4,16 @@ import 'package:flutter/services.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/entity/scene_entity.dart'; import 'package:trans_lark/entity/scene_entity.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/router/router.dart'; import 'package:trans_lark/router/get_router.dart';
import 'package:trans_lark/widget/view_state_widget.dart'; import 'package:trans_lark/widget/t_view_state_widget.dart';
class SceneTypeController extends GetxController { class SceneCategoryController extends GetxController {
var sceneTypeList = <SceneEntity>[].obs; var sceneTypeList = <SceneEntity>[].obs;
var viewState = ViewState.loading.obs; var viewState = ViewState.loading.obs;
@override @override
void onReady() async { void onReady() async {
super.onReady(); super.onReady();
var data = jsonDecode(await rootBundle.loadString(Assets.jsonTranslationScene)); var data = jsonDecode(await rootBundle.loadString(Assets.jsonTranslationScene));
if (data != null && data is List) { if (data != null && data is List) {
sceneTypeList.value = data.map((e) => SceneEntity.fromMap(e)).toList(); sceneTypeList.value = data.map((e) => SceneEntity.fromMap(e)).toList();
@ -22,7 +21,7 @@ class SceneTypeController extends GetxController {
viewState.value = sceneTypeList.isNotEmpty ? ViewState.normal : ViewState.empty; viewState.value = sceneTypeList.isNotEmpty ? ViewState.normal : ViewState.empty;
} }
void onTapItem(SceneEntity item) { void toSceneItem(SceneEntity item) {
Get.toNamed(GetRouter.sceneList, arguments: item.sceneList); Get.toNamed(GetRouter.sceneList, arguments: item.sceneList);
} }
} }

View File

@ -3,30 +3,30 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/entity/scene_entity.dart'; import 'package:trans_lark/entity/scene_entity.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/page/scene_type/scene_type_controller.dart'; import 'package:trans_lark/page/scene_category/scene_category_controller.dart';
import 'package:trans_lark/util/obj_util.dart'; import 'package:trans_lark/util/t_object_utils.dart';
import 'package:trans_lark/widget/base_appbar.dart'; import 'package:trans_lark/widget/t_base_appbar_widget.dart';
import 'package:trans_lark/widget/base_scrollbar.dart'; import 'package:trans_lark/widget/t_base_scrollbar_widget.dart';
import 'package:trans_lark/widget/view_state_widget.dart'; import 'package:trans_lark/widget/t_view_state_widget.dart';
class SceneTypeView extends StatelessWidget { class SceneCategoryView extends StatelessWidget {
SceneTypeView({super.key}); SceneCategoryView({super.key});
final controller = Get.find<SceneTypeController>(); final controller = Get.find<SceneCategoryController>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: const BaseAppBar( appBar: const TBaseAppbarWidget(
title: 'Selected oral expressions', title: 'Selected oral expressions',
), ),
body: SafeArea( body: SafeArea(
top: false, top: false,
child: Obx(() { child: Obx(() {
return ViewStateWidget( return TViewStateWidget(
viewState: controller.viewState.value, viewState: controller.viewState.value,
child: BaseScrollbar( child: TBaseScrollbarWidget(
child: ListView.builder( child: ListView.builder(
itemCount: controller.sceneTypeList.length, itemCount: controller.sceneTypeList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
@ -76,7 +76,7 @@ class SceneTypeView extends StatelessWidget {
bgColor = const Color(0xffFD9D65); bgColor = const Color(0xffFD9D65);
} }
return InkWell( return InkWell(
onTap: () => controller.onTapItem(item), onTap: () => controller.toSceneItem(item),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20), padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20),
child: Row( child: Row(
@ -108,7 +108,7 @@ class SceneTypeView extends StatelessWidget {
left: 7, left: 7,
right: 7, right: 7,
child: Text( child: Text(
ObjUtil.getStr(item.sceneType).toUpperCase(), TObjectUtils.getStr(item.sceneType).toUpperCase(),
maxLines: 3, maxLines: 3,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: const TextStyle( style: const TextStyle(
@ -127,7 +127,7 @@ class SceneTypeView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
ObjUtil.getStr(item.sceneType), TObjectUtils.getStr(item.sceneType),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: const TextStyle( style: const TextStyle(

View File

@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/scene_category_item/scene_category_item_controller.dart';
class SceneCategoryItemBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => SceneCategoryItemController());
}
}

View File

@ -2,9 +2,9 @@ import 'package:get/get.dart';
import 'package:trans_lark/entity/language_entity.dart'; import 'package:trans_lark/entity/language_entity.dart';
import 'package:trans_lark/entity/scene_entity.dart'; import 'package:trans_lark/entity/scene_entity.dart';
import 'package:trans_lark/global/flutter_tts_manager.dart'; import 'package:trans_lark/global/flutter_tts_manager.dart';
import 'package:trans_lark/widget/language_scene_bottom_sheet.dart'; import 'package:trans_lark/widget/t_language_scene_bottom_sheet.dart';
class SceneListController extends GetxController { class SceneCategoryItemController extends GetxController {
var languageScene = <LanguageEntity>[ var languageScene = <LanguageEntity>[
LanguageEntity(languageCode: 'ar', languageName: 'Arabic'), LanguageEntity(languageCode: 'ar', languageName: 'Arabic'),
LanguageEntity(languageCode: 'bn', languageName: 'Bengali'), LanguageEntity(languageCode: 'bn', languageName: 'Bengali'),
@ -34,25 +34,32 @@ class SceneListController extends GetxController {
toLanguage = languageScene[2].copyWith().obs; toLanguage = languageScene[2].copyWith().obs;
} }
void onTapFrom() { void onChangeFromLanguage({String? languageCode, String? languageName}) {
Get.bottomSheet( Get.bottomSheet(
LanguageSceneBottomSheet( TLanguageSceneBottomSheet(
languageScene: languageScene, languageScene: languageScene,
selectedLanguage: fromLanguage, selectedLanguage: fromLanguage,
), ),
); );
} }
void onTapTo() { void onChangeToLanguage({String? languageCode, String? languageName}) {
Get.bottomSheet( Get.bottomSheet(
LanguageSceneBottomSheet( TLanguageSceneBottomSheet(
languageScene: languageScene, languageScene: languageScene,
selectedLanguage: toLanguage, selectedLanguage: toLanguage,
), ),
); );
} }
String getSentence(bool isFrom, SceneList item) { void translatorTtsPlay(bool isFrom, SceneList item, {String? language}) {
FlutterTtsManager().translatorTtsPlay(
getSentence(isFrom, item),
isFrom ? fromLanguage.value.languageCode : toLanguage.value.languageCode,
);
}
String getSentence(bool isFrom, SceneList item, {String? language}) {
List keys = item.toMap().keys.toList(); List keys = item.toMap().keys.toList();
int index = 0; int index = 0;
for (var i = 0; i < keys.length; ++i) { for (var i = 0; i < keys.length; ++i) {
@ -70,11 +77,4 @@ class SceneListController extends GetxController {
} }
return 'loading'; return 'loading';
} }
void translatorTtsPlay(bool isFrom, SceneList item) {
FlutterTtsManager().translatorTtsPlay(
getSentence(isFrom, item),
isFrom ? fromLanguage.value.languageCode : toLanguage.value.languageCode,
);
}
} }

View File

@ -0,0 +1,131 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:trans_lark/entity/scene_entity.dart';
import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/page/scene_category_item/scene_category_item_controller.dart';
import 'package:trans_lark/widget/t_base_appbar_widget.dart';
import 'package:trans_lark/widget/t_base_scrollbar_widget.dart';
import 'package:trans_lark/widget/t_language_scene_bar_widget.dart';
class SceneCategoryItemView extends GetView<SceneCategoryItemController> {
const SceneCategoryItemView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xffF5F6F8),
appBar: TBaseAppbarWidget(
titleWidget: TLanguageSceneBarWidget(
fromLanguage: controller.fromLanguage,
toLanguage: controller.toLanguage,
onTapFrom: controller.onChangeFromLanguage,
onTapTo: controller.onChangeToLanguage,
),
),
body: _buildList(),
);
}
Widget _buildList() {
return Expanded(
child: TBaseScrollbarWidget(
child: ListView.separated(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
itemCount: controller.sceneList.length,
itemBuilder: (context, index) {
var item = controller.sceneList[index];
return Container(
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Obx(
() => Column(
children: [
_buildScene(
item,
isFrom: true,
languageName: controller.fromLanguage.value.languageName,
),
Container(
width: double.infinity,
height: 1,
color: const Color(0xffF4F4F4),
margin: const EdgeInsets.symmetric(vertical: 20),
),
_buildScene(
item,
isFrom: false,
languageName: controller.toLanguage.value.languageName,
),
],
),
),
);
},
separatorBuilder: (context, index) {
return const SizedBox(height: 12);
},
),
),
);
}
Widget _buildScene(
SceneList item, {
required bool isFrom,
required String languageName,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
languageName,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: Color(0xffC2C3C5),
fontSize: 12,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: Obx(() {
return Text(
controller.getSentence(isFrom, item),
style: const TextStyle(
color: Color(0xff152A3D),
fontSize: 16,
fontWeight: FontWeight.w500,
),
);
}),
),
GestureDetector(
onTap: () => controller.translatorTtsPlay(isFrom, item),
child: ClipOval(
child: Container(
width: 24,
height: 24,
color: const Color(0xff4ECA8C).withOpacity(0.2),
child: FittedBox(
fit: BoxFit.none,
child: SvgPicture.asset(
Assets.svgSpeaker,
width: 16,
height: 16,
),
),
),
),
),
],
),
],
);
}
}

View File

@ -1,9 +0,0 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/scene_list/scene_list_controller.dart';
class SceneListBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => SceneListController());
}
}

View File

@ -1,174 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
import 'package:trans_lark/entity/scene_entity.dart';
import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/page/scene_list/scene_list_controller.dart';
import 'package:trans_lark/widget/base_appbar.dart';
import 'package:trans_lark/widget/base_scrollbar.dart';
import 'package:trans_lark/widget/language_scene_bar.dart';
class SceneListView extends GetView<SceneListController> {
const SceneListView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xffF5F6F8),
appBar: BaseAppBar(
titleWidget: LanguageSceneBar(
fromLanguage: controller.fromLanguage,
toLanguage: controller.toLanguage,
onTapFrom: controller.onTapFrom,
onTapTo: controller.onTapTo,
),
),
body: SafeArea(
top: false,
child: Column(
children: [
Expanded(
child: BaseScrollbar(
child: ListView.separated(
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
itemCount: controller.sceneList.length,
itemBuilder: (context, index) {
var item = controller.sceneList[index];
return _buildItem(item);
},
separatorBuilder: (context, index) {
return const SizedBox(height: 12);
},
),
),
),
],
),
),
);
}
Widget _buildItem(SceneList item) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Obx(() {
return Text(
controller.fromLanguage.value.languageName,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: Color(0xffC2C3C5),
fontSize: 12,
fontWeight: FontWeight.w500,
),
);
}),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: Obx(() {
return Text(
controller.getSentence(true, item),
style: const TextStyle(
color: Color(0xff152A3D),
fontSize: 16,
fontWeight: FontWeight.w500,
),
);
}),
),
GestureDetector(
onTap: () => controller.translatorTtsPlay(true, item),
child: ClipOval(
child: Container(
width: 24,
height: 24,
color: const Color(0xff4ECA8C).withOpacity(0.2),
child: FittedBox(
fit: BoxFit.none,
child: SvgPicture.asset(
Assets.svgSpeaker,
width: 16,
height: 16,
),
),
),
),
),
],
),
const SizedBox(height: 20),
],
),
Container(
width: double.infinity,
height: 1,
color: const Color(0xffF4F4F4),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 20),
Obx(() {
return Text(
controller.toLanguage.value.languageName,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: Color(0xffC2C3C5),
fontSize: 12,
fontWeight: FontWeight.w500,
),
);
}),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: Obx(() {
return Text(
controller.getSentence(false, item),
style: const TextStyle(
color: Color(0xff152A3D),
fontSize: 16,
fontWeight: FontWeight.w500,
),
);
}),
),
GestureDetector(
onTap: () => controller.translatorTtsPlay(false, item),
child: ClipOval(
child: Container(
width: 24,
height: 24,
color: const Color(0xff4ECA8C).withOpacity(0.2),
child: FittedBox(
fit: BoxFit.none,
child: SvgPicture.asset(
Assets.svgSpeaker,
width: 16,
height: 16,
),
),
),
),
),
],
),
],
),
],
),
);
}
}

View File

@ -1,9 +0,0 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/scene_type/scene_type_controller.dart';
class SceneTypeBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => SceneTypeController());
}
}

View File

@ -1,10 +1,10 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:trans_lark/router/router.dart'; import 'package:trans_lark/router/get_router.dart';
class SettingsController extends GetxController { class SettingsController extends GetxController {
var versionName = ''.obs; var versionName = ''.obs;
// var options = ['Feedback', 'Privacy Policy', 'User Agreement'];
var options = ['Privacy Policy', 'User Agreement']; var options = ['Privacy Policy', 'User Agreement'];
@override @override
@ -19,7 +19,7 @@ class SettingsController extends GetxController {
versionName.value = 'version number ${packageInfo.version}'; versionName.value = 'version number ${packageInfo.version}';
} }
void itemOnTap(int index) { void clickItem(int index, {String? title}) {
if (index == 0) { if (index == 0) {
Get.toNamed(GetRouter.privacy, arguments: { Get.toNamed(GetRouter.privacy, arguments: {
'title': options[index], 'title': options[index],

View File

@ -1,147 +0,0 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/global/global_config.dart';
import 'package:trans_lark/widget/divider_widget.dart';
import 'settings_controller.dart';
class SettingsView extends StatelessWidget {
SettingsView({super.key});
final controller = Get.put(SettingsController());
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.77,
clipBehavior: Clip.antiAlias,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(26), topRight: Radius.circular(26),
),
),
child: Stack(
children: [
Image.asset(
Assets.imagesHomeBackground,
width: MediaQuery.of(context).size.width,
height: 384,
fit: BoxFit.fitWidth,
),
Column(
children: [
const SizedBox(height: 46),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 34),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.asset(
Assets.launcherIconLauncherIcon,
width: 48,
height: 48,
fit: BoxFit.cover,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
GlobalConfig.appName,
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.w500,
overflow: TextOverflow.ellipsis,
),
),
Obx(() {
return Text(
controller.versionName.value,
style: const TextStyle(
color: Color(0xff979797),
fontSize: 12,
overflow: TextOverflow.ellipsis,
),
);
}),
],
),
),
],
),
),
const SizedBox(height: 15),
// _buildItem('Give a good review', -1),
// const SizedBox(height: 15),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 34),
child: DividerWidget(),
),
_buildListView(),
Image.asset(
Assets.imagesRabbitSayGood,
width: 90,
height: 90,
fit: BoxFit.cover,
),
const SizedBox(height: 58),
],
),
],
),
);
}
Widget _buildListView() {
return Expanded(
child: ListView.builder(
itemCount: controller.options.length,
itemBuilder: (context, index) {
var item = controller.options[index];
return _buildItem(item, index);
},
),
);
}
Widget _buildItem(String item, int index) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: () => controller.itemOnTap(index),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 30),
child: Row(
children: [
Expanded(
child: Text(
item,
style: const TextStyle(
color: Color(0xff222F38),
fontSize: 16,
overflow: TextOverflow.ellipsis,
),
),
),
const Padding(
padding: EdgeInsets.only(left: 10),
child: Icon(
Icons.keyboard_arrow_right_rounded,
color: Color(0xffBCC0CE),
size: 20,
),
),
],
),
),
),
);
}
}

View File

@ -0,0 +1,149 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/global/global_config.dart';
import 'package:trans_lark/widget/t_divider_widget.dart';
import 'settings_controller.dart';
class SettingsWidget extends StatelessWidget {
SettingsWidget({super.key});
final controller = Get.put(SettingsController());
@override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.77,
clipBehavior: Clip.antiAlias,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(26),
topRight: Radius.circular(26),
),
),
child: _buildSettingBody(context),
);
}
Widget _buildSettingBody(context) {
return Stack(
children: [
Image.asset(
Assets.imagesHomeBackground,
width: MediaQuery.of(context).size.width,
height: 384,
fit: BoxFit.fitWidth,
),
Column(
children: [
const SizedBox(height: 46),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 34),
child: Row(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.asset(
Assets.launcherIconLauncherIcon,
width: 48,
height: 48,
fit: BoxFit.cover,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
GlobalConfig.appName,
style: TextStyle(
color: Colors.black,
fontSize: 22,
fontWeight: FontWeight.w500,
overflow: TextOverflow.ellipsis,
),
),
Obx(() {
return Text(
controller.versionName.value,
style: const TextStyle(
color: Color(0xff979797),
fontSize: 12,
overflow: TextOverflow.ellipsis,
),
);
}),
],
),
),
],
),
),
const SizedBox(height: 15),
// _buildItem('Give a good review', -1),
// const SizedBox(height: 15),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 34),
child: TDividerWidget(),
),
_buildSettingItems(),
Image.asset(
Assets.imagesRabbitSayGood,
width: 90,
height: 90,
fit: BoxFit.cover,
),
const SizedBox(height: 58),
],
),
],
);
}
Widget _buildSettingItems() {
return Expanded(
child: ListView.builder(
itemCount: controller.options.length,
itemBuilder: (context, index) {
var item = controller.options[index];
return Material(
color: Colors.transparent,
child: InkWell(
onTap: () => controller.clickItem(index),
child: Container(
padding:
const EdgeInsets.symmetric(vertical: 15, horizontal: 30),
child: Row(
children: [
Expanded(
child: Text(
item,
style: const TextStyle(
color: Color(0xff222F38),
fontSize: 16,
overflow: TextOverflow.ellipsis,
),
),
),
const Padding(
padding: EdgeInsets.only(left: 10),
child: Icon(
Icons.keyboard_arrow_right_rounded,
color: Color(0xffBCC0CE),
size: 20,
),
),
],
),
),
),
);
},
),
);
}
}

View File

@ -1,9 +0,0 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/splash/splash_controller.dart';
class SplashBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => SplashController());
}
}

View File

@ -1,46 +0,0 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:trans_lark/router/router.dart';
class SplashController extends GetxController with GetTickerProviderStateMixin {
var processValue = 0.0.obs;
late AnimationController _controller;
late Animation<double> _animation;
@override
void onInit() {
super.onInit();
_controller = AnimationController(
duration: const Duration(seconds: 10),
vsync: this,
);
// Tween AnimationController
_animation = Tween<double>(begin: 0, end: 1).animate(_controller)
..addListener(() {
processValue.value = _animation.value;
if (processValue.value >= 1) {
_openInitial();
}
});
//
_controller.forward();
}
@override
void onReady() {
super.onReady();
}
@override
void onClose() {
_controller.dispose();
super.onClose();
}
///
void _openInitial() {
Get.offNamed(GetRouter.home);
}
}

View File

@ -1,60 +0,0 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:trans_lark/page/splash/splash_controller.dart';
class SplashView extends GetView<SplashController> {
const SplashView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
// _buildImageBg(),
_buildProgress(),
],
),
);
}
// Widget _buildImageBg() {
// return Image.asset(
// Assets.sideALaunchImage,
// width: ,
// height: ,
// fit: BoxFit.cover,
// );
// }
Widget _buildProgress() {
return Container(
alignment: Alignment.center,
margin: const EdgeInsets.only(bottom: 60),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
SizedBox(
width: 0.5,
child: Obx(() {
return LinearProgressIndicator(
value: controller.processValue.value,
backgroundColor: Colors.white,
valueColor: const AlwaysStoppedAnimation<Color>(Color.fromARGB(255, 185, 239, 200)),
borderRadius: BorderRadius.circular(8),
);
}),
),
const SizedBox(height: 14),
const Text(
'Resource Loading...',
style: TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.w500,
),
),
],
),
);
}
}

View File

@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/translator/translator_controller.dart';
class TranslatorBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => TranslatorController());
}
}

View File

@ -0,0 +1,146 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:trans_lark/entity/history_model.dart';
import 'package:trans_lark/global/speech_to_text_manager.dart';
import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/hive/history_data.dart';
import 'package:trans_lark/router/get_router.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_speak_dialog.dart';
class TranslatorController extends GetxController {
var textController = TextEditingController();
var isValue = false.obs;
var historyList = <HistoryEntity>[].obs;
var lastWords = '';
@override
void onInit() {
super.onInit();
_getAllHistory();
}
@override
void onClose() {
textController.dispose();
super.onClose();
}
_getAllHistory() async {
historyList.value = HistoryData().getAllHistory().reversed.toList();
}
void onSpeakTranslation() {
if (isValue.value) {
textController.text = "";
isValue.value = false;
} else {
_onSpeak();
}
}
Future<void> _onSpeak({String? translation}) 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) {
_toTranslatorRes();
} else {
SpeechToTextManager().startListening(
TranslateManager().fromLanguageEntity.value.languageCode,
_speechRes,
);
}
} else {
Get.back();
TBaseEasyLoading.toast('Speech not available');
}
},
),
);
if (Get.isDialogOpen != null && !Get.isDialogOpen!) {
SpeechToTextManager().stopListening();
}
}
void _speechRes(SpeechRecognitionResult result) {
TPrint.d('识别结果:${result.recognizedWords}');
lastWords = result.recognizedWords;
}
void _toTranslatorRes() {
if (TObjectUtils.isEmpty(lastWords)) {
TBaseEasyLoading.toast('No text recognized');
return;
}
Get.back();
Get.toNamed(
GetRouter.translateResult,
arguments: {"sourceText": lastWords},
);
}
void toHistoryItem(HistoryEntity entity, {int? index}) {
Get.toNamed(
GetRouter.translateResult,
arguments: {
'sourceText': entity.sourceText,
'targetText': entity.targetText,
'isHistory': true,
'fromLanguage': entity.sourceLanguageName,
'toLanguage': entity.targetLanguageName,
},
);
}
void deleteHistoryByIndex(int index, {HistoryEntity? entity}) {
//
int indexToRemoveFromDb = HistoryData().getAllHistory().length - 1 - index;
historyList.removeAt(indexToRemoveFromDb);
HistoryData().deleteHistory(indexToRemoveFromDb);
}
void onTextChanged(String value) {
isValue.value = value.trim().isNotEmpty;
}
void onTextSubmit(String value) {
Get.toNamed(
GetRouter.translateResult,
arguments: {"sourceText": value},
);
}
void insertHistory(HistoryEntity entity, {int? index}) {
historyList.insert(0, entity);
}
void dropHistory() {
historyList.clear();
HistoryData().clearHistory();
}
}

View File

@ -1,144 +0,0 @@
import 'dart:io';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:trans_lark/entity/history_model.dart';
import 'package:trans_lark/global/speech_to_text_manager.dart';
import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/router/router.dart';
import 'package:trans_lark/storage/history_data.dart';
import 'package:trans_lark/util/log_print.dart';
import 'package:trans_lark/util/obj_util.dart';
import 'package:trans_lark/util/permission_util.dart';
import 'package:trans_lark/widget/base_easyloading.dart';
import 'package:trans_lark/widget/speak_dialog.dart';
import 'translator_state.dart';
/// @description:
/// @author
/// @date: 2024-06-27 13:55:27
class TranslatorLogic extends GetxController {
final state = TranslatorState();
@override
void onInit() {
super.onInit();
initData();
}
@override
void onClose() {
state.textController.dispose();
super.onClose();
}
initData() async {
state.historyList.value = HistoryData().getList().reversed.toList();
}
void onTapSuffix() {
if (state.isValue.value) {
state.textController.text = "";
state.isValue.value = false;
} else {
_onTapSpeak();
}
}
Future<void> _onTapSpeak() async {
bool micResult =
await PermissionUtil.checkPermission([Permission.microphone]);
if (!micResult) return;
if (Platform.isIOS) {
bool speechResult =
await PermissionUtil.checkPermission([Permission.speech]);
if (!speechResult) return;
}
await Get.dialog(
barrierDismissible: true,
useSafeArea: false,
SpeakDialog(
isListening: SpeechToTextManager().isListening,
onTap: () async {
if (!SpeechToTextManager().hasSpeech) {
await SpeechToTextManager().initSpeech();
}
if (SpeechToTextManager().hasSpeech) {
if (SpeechToTextManager().isListening.value) {
_openTranslatorResultPage();
} else {
SpeechToTextManager().startListening(
TranslateManager().fromLanguageEntity.value.languageCode,
_onSpeechResult);
}
} else {
Get.back();
BaseEasyLoading.toast('Speech not available');
}
},
),
);
if (Get.isDialogOpen != null && !Get.isDialogOpen!) {
SpeechToTextManager().stopListening();
}
}
void _onSpeechResult(SpeechRecognitionResult result) {
LogPrint.d('识别结果:${result.recognizedWords}');
state.lastWords = result.recognizedWords;
}
void _openTranslatorResultPage() {
if (ObjUtil.isEmpty(state.lastWords)) {
BaseEasyLoading.toast('No text recognized');
return;
}
Get.back();
Get.toNamed(
GetRouter.translateResult,
arguments: {"sourceText": state.lastWords},
);
}
void onTapHistoryItem(HistoryEntity entity) {
Get.toNamed(
GetRouter.translateResult,
arguments: {
'sourceText': entity.sourceText,
'targetText': entity.targetText,
'isHistory': true,
'fromLanguage': entity.sourceLanguageName,
'toLanguage': entity.targetLanguageName,
},
);
}
void deleteItem(int index) {
//
int indexToRemoveFromDb = HistoryData().getList().length - 1 - index;
state.historyList.removeAt(indexToRemoveFromDb);
HistoryData().delete(indexToRemoveFromDb);
}
void onChanged(String value) {
state.isValue.value = value.trim().isNotEmpty;
}
void onSubmitted(String value) {
Get.toNamed(
GetRouter.translateResult,
arguments: {"sourceText": value},
);
}
void insertHistory(HistoryEntity entity) {
state.historyList.insert(0, entity);
}
void cleanAllHistory() {
state.historyList.clear();
HistoryData().clear();
}
}

View File

@ -1,14 +0,0 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:trans_lark/entity/history_model.dart';
import 'package:trans_lark/entity/translator_history_entity.dart';
/// @description:
/// @author
/// @date: 2024-06-27 13:55:27
class TranslatorState {
var textController = TextEditingController();
var isValue = false.obs;
var historyList = <HistoryEntity>[].obs;
var lastWords = '';
}

View File

@ -3,35 +3,20 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart'; import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/page/translator/translator_logic.dart'; import 'package:trans_lark/page/translator/translator_controller.dart';
import 'package:trans_lark/page/translator/translator_state.dart'; import 'package:trans_lark/util/t_object_utils.dart';
import 'package:trans_lark/util/obj_util.dart'; import 'package:trans_lark/widget/t_base_appbar_widget.dart';
import 'package:trans_lark/widget/base_appbar.dart'; import 'package:trans_lark/widget/t_language_bar_widget.dart';
import 'package:trans_lark/widget/language_bar.dart';
class TranslatorPage extends StatefulWidget { class TranslatorView extends GetView<TranslatorController> {
const TranslatorPage({super.key}); const TranslatorView({super.key});
@override
State<TranslatorPage> createState() => _TranslatorPageState();
}
class _TranslatorPageState extends State<TranslatorPage> {
final TranslatorLogic logic = Get.put(TranslatorLogic());
final TranslatorState state = Get.find<TranslatorLogic>().state;
@override
void initState() {
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: const BaseAppBar( appBar: const TBaseAppbarWidget(
titleWidget: LanguageBar(), titleWidget: TLanguageBarWidget(),
), ),
body: Padding( body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20), padding: const EdgeInsets.symmetric(horizontal: 20),
@ -53,7 +38,7 @@ class _TranslatorPageState extends State<TranslatorPage> {
textInputAction: TextInputAction.done, textInputAction: TextInputAction.done,
textAlignVertical: TextAlignVertical.center, textAlignVertical: TextAlignVertical.center,
textAlign: TextAlign.left, textAlign: TextAlign.left,
controller: state.textController, controller: controller.textController,
maxLines: null, maxLines: null,
minLines: 1, minLines: 1,
autofocus: true, autofocus: true,
@ -74,19 +59,19 @@ class _TranslatorPageState extends State<TranslatorPage> {
fontSize: 20, fontSize: 20,
), ),
), ),
onChanged: (value) => logic.onChanged(value), onChanged: (value) => controller.onTextChanged(value),
onSubmitted: (value) => logic.onSubmitted(value), onSubmitted: (value) => controller.onTextSubmit(value),
), ),
), ),
Obx(() { Obx(() {
return Padding( return Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
top: state.isValue.value ? 26 : 20, right: 20), top: controller.isValue.value ? 26 : 20, right: 20),
child: GestureDetector( child: GestureDetector(
onTap: logic.onTapSuffix, onTap: controller.onSpeakTranslation,
child: ClipOval( child: ClipOval(
child: Visibility( child: Visibility(
visible: state.isValue.value, visible: controller.isValue.value,
replacement: Container( replacement: Container(
width: 36, width: 36,
height: 36, height: 36,
@ -111,7 +96,7 @@ class _TranslatorPageState extends State<TranslatorPage> {
), ),
), ),
Obx( Obx(
() => state.historyList.isNotEmpty () => controller.historyList.isNotEmpty
? Expanded( ? Expanded(
child: Column( child: Column(
children: [ children: [
@ -128,7 +113,7 @@ class _TranslatorPageState extends State<TranslatorPage> {
), ),
), ),
IconButton( IconButton(
onPressed: logic.cleanAllHistory, onPressed: controller.dropHistory,
icon: Image.asset( icon: Image.asset(
Assets.imagesDeleteIcon, Assets.imagesDeleteIcon,
width: 24, width: 24,
@ -139,9 +124,9 @@ class _TranslatorPageState extends State<TranslatorPage> {
), ),
Expanded( Expanded(
child: ListView.builder( child: ListView.builder(
itemCount: state.historyList.length, itemCount: controller.historyList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
final historyEntity = state.historyList[index]; final historyEntity = controller.historyList[index];
return CustomPopupMenu( return CustomPopupMenu(
arrowColor: Colors.black, arrowColor: Colors.black,
barrierColor: Colors.transparent, barrierColor: Colors.transparent,
@ -150,7 +135,7 @@ class _TranslatorPageState extends State<TranslatorPage> {
pressType: PressType.longPress, pressType: PressType.longPress,
menuBuilder: () { menuBuilder: () {
return GestureDetector( return GestureDetector(
onTap: () => logic.deleteItem(index), onTap: () => controller.deleteHistoryByIndex(index),
child: Container( child: Container(
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -168,7 +153,7 @@ class _TranslatorPageState extends State<TranslatorPage> {
}, },
child: InkWell( child: InkWell(
onTap: () => onTap: () =>
logic.onTapHistoryItem(historyEntity), controller.toHistoryItem(historyEntity),
child: Column( child: Column(
crossAxisAlignment: crossAxisAlignment:
CrossAxisAlignment.start, CrossAxisAlignment.start,
@ -182,7 +167,7 @@ class _TranslatorPageState extends State<TranslatorPage> {
text: TextSpan( text: TextSpan(
children: [ children: [
TextSpan( TextSpan(
text: ObjUtil.getStr( text: TObjectUtils.getStr(
historyEntity.sourceText), historyEntity.sourceText),
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -196,7 +181,7 @@ class _TranslatorPageState extends State<TranslatorPage> {
), ),
), ),
TextSpan( TextSpan(
text: ObjUtil.getStr( text: TObjectUtils.getStr(
historyEntity.targetText), historyEntity.targetText),
style: const TextStyle( style: const TextStyle(
color: Color(0xff979797), color: Color(0xff979797),

View File

@ -1,8 +0,0 @@
import 'package:get/get.dart';
import 'package:get/get_rx/get_rx.dart';
import 'package:get/get_rx/src/rx_types/rx_types.dart';
import 'package:trans_lark/entity/history_model.dart';
class TranslatorHistoryState {
RxMap<String, List<HistoryEntity>> historyList = <String, List<HistoryEntity>>{}.obs;
}

View File

@ -1,203 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/page/translator_history/translator_history_logic.dart';
import 'package:trans_lark/page/translator_history/translator_history_state.dart';
import 'package:trans_lark/util/obj_util.dart';
import 'package:trans_lark/widget/base_appbar.dart';
import 'package:trans_lark/widget/base_scrollbar.dart';
class TranslatorHistoryPage extends StatefulWidget {
static String routName = "/translateHistory";
const TranslatorHistoryPage({super.key});
@override
State<TranslatorHistoryPage> createState() => _TranslatorHistoryPageState();
}
class _TranslatorHistoryPageState extends State<TranslatorHistoryPage> {
final TranslatorHistoryLogic logic = Get.put(TranslatorHistoryLogic());
final TranslatorHistoryState state = Get.find<TranslatorHistoryLogic>().state;
@override
Widget build(BuildContext context) {
return Stack(
children: [
Scaffold(
backgroundColor: Colors.white,
appBar: const BaseAppBar(
title: 'History',
backColor: Colors.black,
),
body: Obx(() {
return state.historyList.isNotEmpty ? BaseScrollbar(
child: ListView.builder(
padding: const EdgeInsets.symmetric(vertical: 20),
itemCount: state.historyList.length,
itemBuilder: (context, index) {
final map = state.historyList.entries.elementAt(index);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Text(
map.key,
style: const TextStyle(
color: Color(0xff949494),
fontSize: 12,
),
),
),
ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: map.value.length,
itemBuilder: (context, index) {
final item = map.value[index];
return InkWell(
onTap: () => logic.onTapItem(item),
child: Dismissible(
key: Key(item.translationTime.toString()),
dismissThresholds: const {
DismissDirection.startToEnd: 0.5,
DismissDirection.endToStart: 0.5,
},
onDismissed: (_) => logic.deleteItem(map.key, item, index),
background: Container(
color: const Color(0xffFF98BC),
child: Stack(
children: [
Positioned(
left: 16,
top: 0,
bottom: 0,
child: Image.asset(
Assets.imagesDeleteIcon,
width: 24,
height: 24,
color: Colors.white,
),
),
],
),
),
secondaryBackground: Container(
color: const Color(0xffFF98BC),
child: Stack(
children: [
Positioned(
right: 16,
top: 0,
bottom: 0,
child: Image.asset(
Assets.imagesDeleteIcon,
width: 24,
height: 24,
color: Colors.white,
),
),
],
),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () => logic.translatorTtsPlay(item),
child: ClipOval(
child: Container(
width: 32,
height: 32,
color: const Color(0xff4ECA8C),
child: FittedBox(
fit: BoxFit.none,
child: SvgPicture.asset(
Assets.svgSpeakerWhite,
width: 20,
height: 20,
),
),
),
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
ObjUtil.getStr(item.sourceText),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: Color(0xff212121),
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 12),
Text(
ObjUtil.getStr(item.targetText),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: Color(0xff979797),
fontSize: 13,
),
),
],
),
),
],
),
),
),
);
},
separatorBuilder: (context, index) {
return Container(
height: 0.5,
margin: const EdgeInsets.symmetric(horizontal: 20),
color: const Color(0xffEDEDED),
);
},
),
],
);
},
),
) : Center(
child: Image.asset(
Assets.imagesRabbitSayGood,
width: 90,
height: 90,
fit: BoxFit.cover,
),
);
}),
),
Obx(() {
return Visibility(
visible: state.historyList.isNotEmpty,
child: Positioned(
top: 59,
right: 23,
child: Image.asset(
Assets.imagesRabbitSayGood,
width: 90,
height: 90,
fit: BoxFit.cover,
),
),
);
}),
],
);
}
}

View File

@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/translator_record/translator_record_controller.dart';
class TranslatorRecordBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => TranslatorRecordController());
}
}

View File

@ -1,21 +1,20 @@
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/entity/history_model.dart'; import 'package:trans_lark/entity/history_model.dart';
import 'package:trans_lark/global/flutter_tts_manager.dart'; import 'package:trans_lark/global/flutter_tts_manager.dart';
import 'package:trans_lark/page/translator_history/translator_history_state.dart'; import 'package:trans_lark/hive/history_data.dart';
import 'package:trans_lark/router/router.dart'; import 'package:trans_lark/router/get_router.dart';
import 'package:trans_lark/storage/history_data.dart'; import 'package:trans_lark/util/t_object_utils.dart';
import 'package:trans_lark/util/obj_util.dart';
class TranslatorHistoryLogic extends GetxController { class TranslatorRecordController extends GetxController {
final state = TranslatorHistoryState(); RxMap<String, List<HistoryEntity>> historyList = <String, List<HistoryEntity>>{}.obs;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
state.historyList.value = HistoryData().getGroupByList(); historyList.value = HistoryData().getMapList();
} }
void onTapItem(HistoryEntity entity) { void toHistoryItem(HistoryEntity entity, {int? index}) {
Get.toNamed( Get.toNamed(
GetRouter.translateResult, GetRouter.translateResult,
arguments: { arguments: {
@ -28,8 +27,8 @@ class TranslatorHistoryLogic extends GetxController {
); );
} }
void translatorTtsPlay(HistoryEntity entity) { void onTextToSpeech(HistoryEntity entity, {String? text}) {
if (ObjUtil.isNotEmpty(entity.targetText)) { if (TObjectUtils.isNotEmpty(entity.targetText)) {
FlutterTtsManager().translatorTtsPlay( FlutterTtsManager().translatorTtsPlay(
entity.targetText!, entity.targetText!,
entity.targetLanguageCode!, entity.targetLanguageCode!,
@ -37,18 +36,18 @@ class TranslatorHistoryLogic extends GetxController {
} }
} }
void deleteItem(String key, HistoryEntity entity, int index) { void deleteHistoryItem(String key, HistoryEntity entity, int index) {
final list = HistoryData().getList(); final list = HistoryData().getAllHistory();
state.historyList.forEach((key, value) { historyList.forEach((key, value) {
value.removeWhere((e) => e.translationTime == entity.translationTime); value.removeWhere((e) => e.translationTime == entity.translationTime);
}); });
if (state.historyList[key] != null && state.historyList[key]!.isEmpty) { if (historyList[key] != null && historyList[key]!.isEmpty) {
state.historyList.remove(key); historyList.remove(key);
} }
final deleteEntity = list.firstWhereOrNull( final deleteEntity = list.firstWhereOrNull(
(item) => item.translationTime == entity.translationTime); (item) => item.translationTime == entity.translationTime);
if (deleteEntity != null) { if (deleteEntity != null) {
HistoryData().delete(list.indexOf(deleteEntity)); HistoryData().deleteHistory(list.indexOf(deleteEntity));
} }
} }
} }

View File

@ -0,0 +1,198 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/page/translator_record/translator_record_controller.dart';
import 'package:trans_lark/util/t_object_utils.dart';
import 'package:trans_lark/widget/t_base_appbar_widget.dart';
import 'package:trans_lark/widget/t_base_scrollbar_widget.dart';
class TranslatorRecordView extends GetView<TranslatorRecordController> {
const TranslatorRecordView({super.key});
@override
Widget build(BuildContext context) {
return Stack(
children: [
Scaffold(
backgroundColor: Colors.white,
appBar: const TBaseAppbarWidget(
title: 'History',
backColor: Colors.black,
),
body: Obx(() {
if (controller.historyList.isNotEmpty) return _buildHistoryList();
return Center(
child: Image.asset(
Assets.imagesRabbitSayGood,
width: 90,
height: 90,
fit: BoxFit.cover,
),
);
}),
),
Obx(() {
return Visibility(
visible: controller.historyList.isNotEmpty,
child: Positioned(
top: 59,
right: 23,
child: Image.asset(
Assets.imagesRabbitSayGood,
width: 90,
height: 90,
fit: BoxFit.cover,
),
),
);
}),
],
);
}
Widget _buildHistoryList() {
return TBaseScrollbarWidget(
child: ListView.builder(
padding: const EdgeInsets.symmetric(vertical: 20),
itemCount: controller.historyList.length,
itemBuilder: (context, index) {
final map = controller.historyList.entries.elementAt(index);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Text(
map.key,
style: const TextStyle(
color: Color(0xff949494),
fontSize: 12,
),
),
),
ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: map.value.length,
itemBuilder: (context, index) {
final item = map.value[index];
return InkWell(
onTap: () => controller.toHistoryItem(item),
child: Dismissible(
key: Key(item.translationTime.toString()),
dismissThresholds: const {
DismissDirection.startToEnd: 0.5,
DismissDirection.endToStart: 0.5,
},
onDismissed: (_) =>
controller.deleteHistoryItem(map.key, item, index),
background: Container(
color: const Color(0xffFF98BC),
child: Stack(
children: [
Positioned(
left: 16,
top: 0,
bottom: 0,
child: Image.asset(
Assets.imagesDeleteIcon,
width: 24,
height: 24,
color: Colors.white,
),
),
],
),
),
secondaryBackground: Container(
color: const Color(0xffFF98BC),
child: Stack(
children: [
Positioned(
right: 16,
top: 0,
bottom: 0,
child: Image.asset(
Assets.imagesDeleteIcon,
width: 24,
height: 24,
color: Colors.white,
),
),
],
),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
GestureDetector(
onTap: () => controller.onTextToSpeech(item),
child: ClipOval(
child: Container(
width: 32,
height: 32,
color: const Color(0xff4ECA8C),
child: FittedBox(
fit: BoxFit.none,
child: SvgPicture.asset(
Assets.svgSpeakerWhite,
width: 20,
height: 20,
),
),
),
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
TObjectUtils.getStr(item.sourceText),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: Color(0xff212121),
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 12),
Text(
TObjectUtils.getStr(item.targetText),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: Color(0xff979797),
fontSize: 13,
),
),
],
),
),
],
),
),
),
);
},
separatorBuilder: (context, index) {
return Container(
height: 0.5,
margin: const EdgeInsets.symmetric(horizontal: 20),
color: const Color(0xffEDEDED),
);
},
),
],
);
},
),
);
}
}

View File

@ -0,0 +1,9 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/translator_result/translator_result_controller.dart';
class TranslatorResultBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => TranslatorResultController());
}
}

View File

@ -0,0 +1,112 @@
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:trans_lark/global/flutter_tts_manager.dart';
import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/hive/history_data.dart';
import 'package:trans_lark/page/translator/translator_controller.dart';
import 'package:trans_lark/util/t_object_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_translate_text_full_screen_page.dart';
import 'package:translator/translator.dart';
import 'package:trans_lark/entity/history_model.dart';
class TranslatorResultController extends GetxController {
var translator = GoogleTranslator();
RxString sourceText = "".obs;
RxString targetText = "".obs;
var isTranslationCompleted = false.obs;
bool isHistory = false;
String? fromLanguage;
String? toLanguage;
@override
void onInit() {
super.onInit();
sourceText.value = Get.arguments['sourceText'] ?? '';
targetText.value = Get.arguments['targetText'] ?? '';
isHistory = Get.arguments['isHistory'] ?? false;
fromLanguage = Get.arguments['fromLanguage'];
toLanguage = Get.arguments['toLanguage'];
}
@override
void onReady() {
super.onReady();
if (isHistory) {
isTranslationCompleted.value = true;
} else {
translation();
}
}
Future<void> translation({String? text, String? language}) async {
if (TObjectUtils.isNotEmpty(sourceText.value)) {
try {
Translation translate = await translator.translate(
sourceText.value,
from: TranslateManager().fromLanguageEntity.value.languageCode,
to: TranslateManager().toLanguageEntity.value.languageCode,
);
targetText.value = translate.text;
addHistory();
} catch (e) {
TBaseEasyLoading.toast('Translation failed');
TPrint.d('Translation failed,${e.toString()}');
}
isTranslationCompleted.value = true;
}
}
void addHistory({HistoryEntity? entity, int? index}) {
final entity = HistoryEntity(
sourceText: sourceText.value,
targetText: targetText.value,
sourceLanguageName:
TranslateManager().fromLanguageEntity.value.languageName,
sourceLanguageCode:
TranslateManager().fromLanguageEntity.value.languageCode,
targetLanguageName:
TranslateManager().toLanguageEntity.value.languageName,
targetLanguageCode:
TranslateManager().toLanguageEntity.value.languageCode,
);
HistoryData().addHistory(entity);
if (Get.isRegistered<TranslatorController>()) {
final controller = Get.find<TranslatorController>();
controller.insertHistory(entity);
}
}
void onTextToSpeech(String text, String type, {String? language}) {
if (TObjectUtils.isNotEmpty(text)) {
String language =
TranslateManager().fromLanguageEntity.value.languageCode;
switch (type) {
case "from":
language = fromLanguage ??
TranslateManager().fromLanguageEntity.value.languageCode;
break;
case "to":
language = toLanguage ??
TranslateManager().toLanguageEntity.value.languageCode;
break;
}
FlutterTtsManager().translatorTtsPlay(text, language);
}
}
void copyText({String? copyText}) {
if (TObjectUtils.isNotEmpty(targetText.value)) {
Clipboard.setData(ClipboardData(text: targetText.value));
TBaseEasyLoading.toast('Copied to clipboard');
}
}
void toFullScreen({String? title}) {
if (TObjectUtils.isNotEmpty(targetText.value)) {
Get.to(() => const TTranslateTextFullScreenPage(),
arguments: {"data": targetText.value});
}
}
}

View File

@ -1,107 +0,0 @@
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:trans_lark/global/flutter_tts_manager.dart';
import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/page/translator_result/translator_result_state.dart';
import 'package:trans_lark/util/log_print.dart';
import 'package:translator/translator.dart';
import 'package:trans_lark/entity/history_model.dart';
import 'package:trans_lark/page/translator/translator_logic.dart';
import 'package:trans_lark/storage/history_data.dart';
import 'package:trans_lark/util/obj_util.dart';
import 'package:trans_lark/widget/base_easyloading.dart';
import 'package:trans_lark/widget/translate_text_full_screen_page.dart';
class TranslatorResultPageLogic extends GetxController {
final state = TranslatorResultPageState();
@override
void onInit() {
super.onInit();
state.sourceText.value = Get.arguments['sourceText'] ?? '';
state.targetText.value = Get.arguments['targetText'] ?? '';
state.isHistory = Get.arguments['isHistory'] ?? false;
state.fromLanguage = Get.arguments['fromLanguage'];
state.toLanguage = Get.arguments['toLanguage'];
}
@override
void onReady() {
super.onReady();
if (state.isHistory) {
state.isTranslationCompleted.value = true;
} else {
translation();
}
}
Future<void> translation() async {
if (ObjUtil.isNotEmpty(state.sourceText.value)) {
try {
Translation translate = await state.translator.translate(
state.sourceText.value,
from: TranslateManager().fromLanguageEntity.value.languageCode,
to: TranslateManager().toLanguageEntity.value.languageCode,
);
state.targetText.value = translate.text;
addHistory();
} catch (e) {
BaseEasyLoading.toast('Translation failed');
LogPrint.d('Translation failed,${e.toString()}');
}
state.isTranslationCompleted.value = true;
}
}
void addHistory() {
final entity = HistoryEntity(
sourceText: state.sourceText.value,
targetText: state.targetText.value,
sourceLanguageName:
TranslateManager().fromLanguageEntity.value.languageName,
sourceLanguageCode:
TranslateManager().fromLanguageEntity.value.languageCode,
targetLanguageName:
TranslateManager().toLanguageEntity.value.languageName,
targetLanguageCode:
TranslateManager().toLanguageEntity.value.languageCode,
);
HistoryData().addData(entity);
if (Get.isRegistered<TranslatorLogic>()) {
final logic = Get.find<TranslatorLogic>();
logic.insertHistory(entity);
}
}
void translatorTtsPlay(String text, type) {
if (ObjUtil.isNotEmpty(text)) {
String language =
TranslateManager().fromLanguageEntity.value.languageCode;
switch (type) {
case "from":
language = state.fromLanguage ??
TranslateManager().fromLanguageEntity.value.languageCode;
break;
case "to":
language = state.toLanguage ??
TranslateManager().toLanguageEntity.value.languageCode;
break;
}
FlutterTtsManager().translatorTtsPlay(text, language);
}
}
void copy() {
if (ObjUtil.isNotEmpty(state.targetText.value)) {
Clipboard.setData(ClipboardData(text: state.targetText.value));
BaseEasyLoading.toast('Copied to clipboard');
}
}
void openFullScreenPage() {
if (ObjUtil.isNotEmpty(state.targetText.value)) {
Get.to(() => const TranslateTextFullScreenPage(),
arguments: {"data": state.targetText.value});
}
}
}

View File

@ -1,12 +0,0 @@
import 'package:get/get_rx/src/rx_types/rx_types.dart';
import 'package:translator/translator.dart';
class TranslatorResultPageState {
var translator = GoogleTranslator();
RxString sourceText = "".obs;
RxString targetText = "".obs;
var isTranslationCompleted = false.obs;
bool isHistory = false;
String? fromLanguage;
String? toLanguage;
}

View File

@ -3,56 +3,57 @@ import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/global/translate_manager.dart'; import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/page/translator_result/translator_result_logic.dart'; import 'package:trans_lark/page/translator_result/translator_result_controller.dart';
import 'package:trans_lark/page/translator_result/translator_result_state.dart'; import 'package:trans_lark/util/t_object_utils.dart';
import 'package:trans_lark/util/obj_util.dart'; import 'package:trans_lark/widget/t_base_appbar_widget.dart';
import 'package:trans_lark/widget/base_appbar.dart'; import 'package:trans_lark/widget/t_language_result_bar_widget.dart';
import 'package:trans_lark/widget/language_result_bar.dart';
class TranslatorResultPage extends StatefulWidget { class TranslatorResultView extends GetView<TranslatorResultController> {
const TranslatorResultPage({super.key}); const TranslatorResultView({super.key});
@override
State<TranslatorResultPage> createState() => _TranslatorResultPageState();
}
class _TranslatorResultPageState extends State<TranslatorResultPage> {
final TranslatorResultPageLogic logic = Get.put(TranslatorResultPageLogic());
final TranslatorResultPageState state =
Get.find<TranslatorResultPageLogic>().state;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Container(
body: Container(
height: double.infinity,
width: double.infinity,
decoration: const BoxDecoration( decoration: const BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage(Assets.imagesTranslatorResultBackground), image: AssetImage(Assets.imagesTranslatorResultBackground),
fit: BoxFit.fill, fit: BoxFit.fill,
), ),
), ),
child: Column( child: Scaffold(
children: [
BaseAppBar(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
titleWidget: LanguageResultBar( appBar: _buildAppbar(),
fromLanguage: state.isHistory body: _buildBody(),
? (state.fromLanguage != null ? state.fromLanguage! : '') ),
);
}
TBaseAppbarWidget _buildAppbar() {
return TBaseAppbarWidget(
backgroundColor: Colors.transparent,
titleWidget: TLanguageResultBarWidget(
fromLanguage: controller.isHistory
? (controller.fromLanguage != null ? controller.fromLanguage! : '')
: TranslateManager().fromLanguageEntity.value.languageName, : TranslateManager().fromLanguageEntity.value.languageName,
toLanguage: state.isHistory toLanguage: controller.isHistory
? (state.toLanguage != null ? state.toLanguage! : '') ? (controller.toLanguage != null ? controller.toLanguage! : '')
: TranslateManager().toLanguageEntity.value.languageName, : TranslateManager().toLanguageEntity.value.languageName,
), ),
), );
Expanded( }
child: ListView(
Widget _buildBody() {
return ListView(
padding: const EdgeInsets.symmetric(vertical: 20), padding: const EdgeInsets.symmetric(vertical: 20),
children: [ children: [
Obx( _buildFromWidget(),
() => Padding( _buildToWidget(),
],
);
}
Widget _buildFromWidget() {
return Obx(() => Padding(
padding: const EdgeInsets.symmetric(horizontal: 24), padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -62,7 +63,7 @@ class _TranslatorResultPageState extends State<TranslatorResultPage> {
children: [ children: [
Expanded( Expanded(
child: Text( child: Text(
state.sourceText.value, controller.sourceText.value,
style: const TextStyle( style: const TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -90,8 +91,10 @@ class _TranslatorResultPageState extends State<TranslatorResultPage> {
height: 30, height: 30,
), ),
GestureDetector( GestureDetector(
onTap: () => logic.translatorTtsPlay( onTap: () => controller.onTextToSpeech(
state.sourceText.value, "from"), controller.sourceText.value,
"from",
),
child: ClipOval( child: ClipOval(
child: Container( child: Container(
width: 32, width: 32,
@ -116,9 +119,11 @@ class _TranslatorResultPageState extends State<TranslatorResultPage> {
) )
], ],
), ),
), ));
), }
Padding(
Widget _buildToWidget() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20), padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -130,10 +135,7 @@ class _TranslatorResultPageState extends State<TranslatorResultPage> {
children: [ children: [
Flexible( Flexible(
child: Text( child: Text(
TranslateManager() TranslateManager().toLanguageEntity.value.languageName,
.toLanguageEntity
.value
.languageName,
style: const TextStyle( style: const TextStyle(
color: Color(0xff949494), color: Color(0xff949494),
fontSize: 16, fontSize: 16,
@ -143,7 +145,7 @@ class _TranslatorResultPageState extends State<TranslatorResultPage> {
), ),
const SizedBox(width: 20), const SizedBox(width: 20),
Visibility( Visibility(
visible: !state.isTranslationCompleted.value, visible: !controller.isTranslationCompleted.value,
child: const SizedBox( child: const SizedBox(
width: 20, width: 20,
height: 20, height: 20,
@ -159,7 +161,7 @@ class _TranslatorResultPageState extends State<TranslatorResultPage> {
), ),
Obx( Obx(
() => Text( () => Text(
state.targetText.value, controller.targetText.value,
style: const TextStyle( style: const TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -172,13 +174,14 @@ class _TranslatorResultPageState extends State<TranslatorResultPage> {
), ),
Obx(() { Obx(() {
return Visibility( return Visibility(
visible: visible: TObjectUtils.isNotEmptyStr(controller.targetText.value),
ObjUtil.isNotEmptyStr(state.targetText.value),
child: Row( child: Row(
children: [ children: [
GestureDetector( GestureDetector(
onTap: () => logic.translatorTtsPlay( onTap: () => controller.onTextToSpeech(
state.targetText.value, "to"), controller.targetText.value,
"to",
),
child: ClipOval( child: ClipOval(
child: Container( child: Container(
width: 32, width: 32,
@ -197,7 +200,7 @@ class _TranslatorResultPageState extends State<TranslatorResultPage> {
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
GestureDetector( GestureDetector(
onTap: logic.copy, onTap: controller.copyText,
child: ClipOval( child: ClipOval(
child: Container( child: Container(
width: 32, width: 32,
@ -216,7 +219,7 @@ class _TranslatorResultPageState extends State<TranslatorResultPage> {
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
GestureDetector( GestureDetector(
onTap: logic.openFullScreenPage, onTap: controller.toFullScreen,
child: ClipOval( child: ClipOval(
child: Container( child: Container(
width: 32, width: 32,
@ -239,12 +242,6 @@ class _TranslatorResultPageState extends State<TranslatorResultPage> {
}), }),
], ],
), ),
),
],
)),
],
),
),
); );
} }
} }

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/widget/view_state_widget.dart'; import 'package:trans_lark/widget/t_view_state_widget.dart';
import 'package:webview_flutter/webview_flutter.dart'; import 'package:webview_flutter/webview_flutter.dart';
class WebPageController extends GetxController { class WebPageController extends GetxController {

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/page/web_page/web_page_controller.dart'; import 'package:trans_lark/page/web_page/web_page_controller.dart';
import 'package:trans_lark/widget/base_appbar.dart'; import 'package:trans_lark/widget/t_base_appbar_widget.dart';
import 'package:trans_lark/widget/view_state_widget.dart'; import 'package:trans_lark/widget/t_view_state_widget.dart';
import 'package:webview_flutter/webview_flutter.dart'; import 'package:webview_flutter/webview_flutter.dart';
class WebPageView extends GetView<WebPageController> { class WebPageView extends GetView<WebPageController> {
@ -12,11 +12,11 @@ class WebPageView extends GetView<WebPageController> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: BaseAppBar( appBar: TBaseAppbarWidget(
title: controller.title, title: controller.title,
), ),
body: Obx(() { body: Obx(() {
return ViewStateWidget( return TViewStateWidget(
viewState: controller.viewState.value, viewState: controller.viewState.value,
child: WebViewWidget(controller: controller.webViewController), child: WebViewWidget(controller: controller.webViewController),
); );

View File

@ -0,0 +1,88 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/index/index_view.dart';
import 'package:trans_lark/page/p2p/p2p_binding.dart';
import 'package:trans_lark/page/p2p/p2p_view.dart';
import 'package:trans_lark/page/scene_category/scene_category_binding.dart';
import 'package:trans_lark/page/scene_category/scene_category_view.dart';
import 'package:trans_lark/page/scene_category_item/scene_category_item_binding.dart';
import 'package:trans_lark/page/scene_category_item/scene_category_item_view.dart';
import 'package:trans_lark/page/translator/translator_binding.dart';
import 'package:trans_lark/page/translator/translator_view.dart';
import 'package:trans_lark/page/translator_record/translator_record_binding.dart';
import 'package:trans_lark/page/translator_record/translator_record_view.dart';
import 'package:trans_lark/page/translator_result/translator_result_binding.dart';
import 'package:trans_lark/page/translator_result/translator_result_view.dart';
import 'package:trans_lark/page/web_page/web_page_binding.dart';
import 'package:trans_lark/page/web_page/web_page_view.dart';
class GetRouter {
static const splash = '/';
static const index = '/index';
static const sceneCategory = '/scene_category';
static const sceneList = '/scene_list';
static const translate = '/translate';
static const p2p = '/p2p';
static const translateResult = '/translate_result';
static const translateRecord = '/translate_record';
static const terms = '/terms';
static const privacy = '/privacy';
static List<GetPage> routers = [
// GetPage(
// name: splash,
// page: () => SplashView(),
// binding: SplashBinding(),
// ),
//
GetPage(
name: index,
page: () => IndexView(),
),
GetPage(
name: sceneCategory,
page: () => SceneCategoryView(),
binding: SceneCategoryBinding(),
),
GetPage(
name: sceneList,
page: () => const SceneCategoryItemView(),
binding: SceneCategoryItemBinding(),
),
//
GetPage(
name: translate,
page: () => const TranslatorView(),
binding: TranslatorBinding(),
),
//
GetPage(
name: translateResult,
page: () => const TranslatorResultView(),
binding: TranslatorResultBinding(),
),
//
GetPage(
name: translateRecord,
page: () => const TranslatorRecordView(),
binding: TranslatorRecordBinding(),
),
//
GetPage(
name: p2p,
page: () => const P2PView(),
binding: P2PBinding(),
),
//
GetPage(
name: privacy,
page: () => const WebPageView(),
binding: WebPageBinding(),
),
//
GetPage(
name: terms,
page: () => const WebPageView(),
binding: WebPageBinding(),
),
];
}

View File

@ -1,82 +0,0 @@
import 'package:get/get.dart';
import 'package:trans_lark/page/face_to_face/face_to_face_binding.dart';
import 'package:trans_lark/page/face_to_face/face_to_face_view.dart';
import 'package:trans_lark/page/home/home_view.dart';
import 'package:trans_lark/page/scene_list/scene_list_binding.dart';
import 'package:trans_lark/page/scene_list/scene_list_view.dart';
import 'package:trans_lark/page/scene_type/scene_type_binding.dart';
import 'package:trans_lark/page/scene_type/scene_type_view.dart';
import 'package:trans_lark/page/translator/translator_view.dart';
import 'package:trans_lark/page/translator_history/translator_history_view.dart';
import 'package:trans_lark/page/translator_result/translator_result_view.dart';
import 'package:trans_lark/page/web_page/web_page_binding.dart';
import 'package:trans_lark/page/web_page/web_page_view.dart';
class GetRouter {
static const splash = '/';
static const home = '/home';
static const sceneType = '/scene_type';
static const sceneList = '/scene_list';
static const translate = '/translate';
static const faceToFace = '/face_to_face';
static const translateResult = '/translate_result';
static const translateHistory = '/translate_history';
static const terms = '/terms';
static const privacy = '/privacy';
static List<GetPage> routers = [
// GetPage(
// name: splash,
// page: () => SplashView(),
// binding: SplashBinding(),
// ),
//
GetPage(
name: home,
page: () => HomePage(),
),
GetPage(
name: sceneType,
page: () => SceneTypeView(),
binding: SceneTypeBinding(),
),
GetPage(
name: sceneList,
page: () => SceneListView(),
binding: SceneListBinding(),
),
//
GetPage(
name: translate,
page: () => const TranslatorPage(),
),
//
GetPage(
name: translateResult,
page: () => const TranslatorResultPage(),
),
//
GetPage(
name: translateHistory,
page: () => const TranslatorHistoryPage(),
),
//
GetPage(
name: faceToFace,
page: () => FaceToFaceView(),
binding: FaceToFaceBinding(),
),
//
GetPage(
name: privacy,
page: () => WebPageView(),
binding: WebPageBinding(),
),
//
GetPage(
name: terms,
page: () => WebPageView(),
binding: WebPageBinding(),
),
];
}

View File

@ -1,9 +0,0 @@
import 'package:intl/intl.dart';
class DateConverter {
static stringToYyMmDd(String date) {
DateTime sourceDate = DateTime.parse(date);
String formatDate = DateFormat("yyyy-MM-dd").format(sourceDate);
return formatDate;
}
}

View File

@ -1,3 +1,5 @@
import 'package:intl/intl.dart';
class DateFormats { class DateFormats {
static String full = 'yyyy-MM-dd HH:mm:ss'; static String full = 'yyyy-MM-dd HH:mm:ss';
static String yMoDHM = 'yyyy-MM-dd HH:mm'; static String yMoDHM = 'yyyy-MM-dd HH:mm';
@ -18,7 +20,7 @@ class DateFormats {
static String zhHM = 'HH时mm分'; static String zhHM = 'HH时mm分';
} }
class DateUtil { class TDateUtils {
/// ->. /// ->.
static Map<int, int> monthDay = { static Map<int, int> monthDay = {
1: 31, 1: 31,
@ -188,7 +190,7 @@ class DateUtil {
DateTime.fromMillisecondsSinceEpoch(milliseconds, isUtc: isUtc); DateTime.fromMillisecondsSinceEpoch(milliseconds, isUtc: isUtc);
DateTime now; DateTime now;
if (locMs != null) { if (locMs != null) {
now = DateUtil.getDateTimeByMs(locMs); now = TDateUtils.getDateTimeByMs(locMs);
} else { } else {
now = isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal(); now = isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal();
} }
@ -223,7 +225,7 @@ class DateUtil {
DateTime oldT = DateTime.fromMillisecondsSinceEpoch(ms, isUtc: isUtc); DateTime oldT = DateTime.fromMillisecondsSinceEpoch(ms, isUtc: isUtc);
DateTime nowT; DateTime nowT;
if (locMs != null) { if (locMs != null) {
nowT = DateUtil.getDateTimeByMs(locMs, isUtc: isUtc); nowT = TDateUtils.getDateTimeByMs(locMs, isUtc: isUtc);
} else { } else {
nowT = isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal(); nowT = isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal();
} }
@ -285,4 +287,10 @@ class DateUtil {
} }
return dateTime.month + 1; return dateTime.month + 1;
} }
static stringToYyMmDd(String date) {
DateTime sourceDate = DateTime.parse(date);
String formatDate = DateFormat("yyyy-MM-dd").format(sourceDate);
return formatDate;
}
} }

View File

@ -1,6 +1,6 @@
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
class DeviceInfoUtil { class TDeviceUtils {
/// Android设备的系统版本 /// Android设备的系统版本
static Future<int> getAndroidSDKInt() async { static Future<int> getAndroidSDKInt() async {
DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();

View File

@ -1,6 +1,6 @@
import 'dart:math'; import 'dart:math';
class NumUtil { class TNumberUtils {
/// ///
static int getRandomNumber(int min, int max) { static int getRandomNumber(int min, int max) {
Random random = Random(); Random random = Random();

View File

@ -1,4 +1,4 @@
class ObjUtil { class TObjectUtils {
static bool isNotEmptyStr(String? str) { static bool isNotEmptyStr(String? str) {
return str != null && str.trim().isNotEmpty; return str != null && str.trim().isNotEmpty;
} }

View File

@ -2,9 +2,9 @@ import 'dart:io';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:trans_lark/widget/remind_dialog.dart'; import 'package:trans_lark/widget/t_remind_dialog.dart';
class PermissionUtil { class TPermissionUtils {
/// ///
/// [permissionList] /// [permissionList]
static Future<bool> checkPermission(List<Permission> permissionList, static Future<bool> checkPermission(List<Permission> permissionList,
@ -107,7 +107,7 @@ class PermissionUtil {
{bool isPermanentlyDenied = false}) async { {bool isPermanentlyDenied = false}) async {
Get.dialog( Get.dialog(
barrierDismissible: false, barrierDismissible: false,
RemindDialog( TRemindDialog(
content: await _getDescription(permissionList), content: await _getDescription(permissionList),
confirmText: isPermanentlyDenied ? 'Go open' : 'Confirm', confirmText: isPermanentlyDenied ? 'Go open' : 'Confirm',
confirmOnTap: () { confirmOnTap: () {

View File

@ -17,30 +17,30 @@ final _logger = Logger(
), ),
); );
class LogPrint { class TPrint {
static const String _tag = 'LogPrint'; static const String _tag = 'LogPrint';
LogPrint.t(dynamic msg, {String tag = _tag}) { TPrint.t(dynamic msg, {String tag = _tag}) {
_logger.t('[$tag]: $msg'); _logger.t('[$tag]: $msg');
} }
LogPrint.d(dynamic msg, {String tag = _tag}) { TPrint.d(dynamic msg, {String tag = _tag}) {
_logger.d('[$tag]: $msg'); _logger.d('[$tag]: $msg');
} }
LogPrint.i(dynamic msg, {String tag = _tag}) { TPrint.i(dynamic msg, {String tag = _tag}) {
_logger.i('[$tag]: $msg'); _logger.i('[$tag]: $msg');
} }
LogPrint.w(dynamic msg, {String tag = _tag}) { TPrint.w(dynamic msg, {String tag = _tag}) {
_logger.w('[$tag]: $msg'); _logger.w('[$tag]: $msg');
} }
LogPrint.e(dynamic msg, {String tag = _tag}) { TPrint.e(dynamic msg, {String tag = _tag}) {
_logger.e('[$tag]: $msg'); _logger.e('[$tag]: $msg');
} }
LogPrint.f(dynamic msg, {String tag = _tag}) { TPrint.f(dynamic msg, {String tag = _tag}) {
_logger.f('[$tag]: $msg'); _logger.f('[$tag]: $msg');
} }
} }

View File

@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
class BaseAppBar extends StatelessWidget implements PreferredSizeWidget { class TBaseAppbarWidget extends StatelessWidget implements PreferredSizeWidget {
const BaseAppBar({ const TBaseAppbarWidget({
super.key, super.key,
this.backgroundColor, this.backgroundColor,
this.backColor, this.backColor,

View File

@ -1,6 +1,6 @@
import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart';
class BaseEasyLoading { class TBaseEasyLoading {
static void configLoading() { static void configLoading() {
EasyLoading.instance EasyLoading.instance
// loading展示的时候. // loading展示的时候.

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class BaseScrollbar extends StatelessWidget { class TBaseScrollbarWidget extends StatelessWidget {
const BaseScrollbar({super.key, required this.child, this.thumbColor}); const TBaseScrollbarWidget({super.key, required this.child, this.thumbColor});
final Widget child; final Widget child;
final Color? thumbColor; final Color? thumbColor;

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class DividerWidget extends StatelessWidget { class TDividerWidget extends StatelessWidget {
const DividerWidget({super.key, this.height, this.color}); const TDividerWidget({super.key, this.height, this.color});
final double? height; final double? height;
final Color? color; final Color? color;

View File

@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/global/translate_manager.dart'; import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/widget/language_bottom_sheet.dart'; import 'package:trans_lark/widget/t_language_bottom_sheet.dart';
class LanguageBar extends StatelessWidget { class TLanguageBarWidget extends StatelessWidget {
const LanguageBar({ const TLanguageBarWidget({
super.key, super.key,
this.isSelect = false, this.isSelect = false,
this.onTapFrom, this.onTapFrom,
@ -155,7 +155,7 @@ class LanguageBar extends StatelessWidget {
TranslateManager().isSelectFromLanguage.value = true; TranslateManager().isSelectFromLanguage.value = true;
Get.bottomSheet( Get.bottomSheet(
isScrollControlled: true, isScrollControlled: true,
const LanguageBottomSheet(), const TLanguageBottomSheet(),
); );
} }
@ -163,7 +163,7 @@ class LanguageBar extends StatelessWidget {
TranslateManager().isSelectFromLanguage.value = false; TranslateManager().isSelectFromLanguage.value = false;
Get.bottomSheet( Get.bottomSheet(
isScrollControlled: true, isScrollControlled: true,
const LanguageBottomSheet(), const TLanguageBottomSheet(),
); );
} }
} }

View File

@ -4,12 +4,12 @@ import 'package:get/get_state_manager/get_state_manager.dart';
import 'package:trans_lark/entity/language_entity.dart'; import 'package:trans_lark/entity/language_entity.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/global/translate_manager.dart'; import 'package:trans_lark/global/translate_manager.dart';
import 'package:trans_lark/page/home/home_logic.dart'; import 'package:trans_lark/page/index/index_controller.dart';
import 'package:trans_lark/widget/base_scrollbar.dart'; import 'package:trans_lark/widget/t_base_scrollbar_widget.dart';
import 'package:trans_lark/widget/language_bar.dart'; import 'package:trans_lark/widget/t_language_bar_widget.dart';
class LanguageBottomSheet extends StatelessWidget { class TLanguageBottomSheet extends StatelessWidget {
const LanguageBottomSheet({super.key}); const TLanguageBottomSheet({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -35,7 +35,7 @@ class LanguageBottomSheet extends StatelessWidget {
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
LanguageBar( TLanguageBarWidget(
isSelect: true, isSelect: true,
onTapFrom: _onTapFrom, onTapFrom: _onTapFrom,
onTapTo: _onTapTo, onTapTo: _onTapTo,
@ -49,7 +49,7 @@ class LanguageBottomSheet extends StatelessWidget {
Widget _buildListView() { Widget _buildListView() {
return Expanded( return Expanded(
child: BaseScrollbar( child: TBaseScrollbarWidget(
child: ListView.builder( child: ListView.builder(
itemCount: TranslateManager().languageList.length, itemCount: TranslateManager().languageList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
@ -136,8 +136,8 @@ class LanguageBottomSheet extends StatelessWidget {
fn?.languageName = item.languageName; fn?.languageName = item.languageName;
}); });
} }
if (Get.isRegistered<HomeLogic>()) { if (Get.isRegistered<IndexController>()) {
HomeLogic.to.getDailyQuote(); IndexController.to.getDailyQuoteData();
} }
} }

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
class LanguageResultBar extends StatelessWidget { class TLanguageResultBarWidget extends StatelessWidget {
const LanguageResultBar({ const TLanguageResultBarWidget({
super.key, super.key,
required this.fromLanguage, required this.fromLanguage,
required this.toLanguage, required this.toLanguage,

View File

@ -3,8 +3,8 @@ import 'package:get/get.dart';
import 'package:trans_lark/entity/language_entity.dart'; import 'package:trans_lark/entity/language_entity.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
class LanguageSceneBar extends StatelessWidget { class TLanguageSceneBarWidget extends StatelessWidget {
const LanguageSceneBar({ const TLanguageSceneBarWidget({
super.key, super.key,
required this.fromLanguage, required this.fromLanguage,
required this.toLanguage, required this.toLanguage,

View File

@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/entity/language_entity.dart'; import 'package:trans_lark/entity/language_entity.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/widget/base_scrollbar.dart'; import 'package:trans_lark/widget/t_base_scrollbar_widget.dart';
class LanguageSceneBottomSheet extends StatelessWidget { class TLanguageSceneBottomSheet extends StatelessWidget {
const LanguageSceneBottomSheet({super.key, required this.languageScene, required this.selectedLanguage}); const TLanguageSceneBottomSheet({super.key, required this.languageScene, required this.selectedLanguage});
final List<LanguageEntity> languageScene; final List<LanguageEntity> languageScene;
final Rx<LanguageEntity> selectedLanguage; final Rx<LanguageEntity> selectedLanguage;
@ -41,7 +41,7 @@ class LanguageSceneBottomSheet extends StatelessWidget {
Widget _buildListView() { Widget _buildListView() {
return Expanded( return Expanded(
child: BaseScrollbar( child: TBaseScrollbarWidget(
child: ListView.builder( child: ListView.builder(
itemCount: languageScene.length, itemCount: languageScene.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {

View File

@ -1,9 +1,9 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:trans_lark/widget/divider_widget.dart'; import 'package:trans_lark/widget/t_divider_widget.dart';
class PhotoPickerBottomSheet extends StatelessWidget { class TPhotoPickerBottomSheet extends StatelessWidget {
const PhotoPickerBottomSheet({super.key, required this.funCamera, required this.funGallery}); const TPhotoPickerBottomSheet({super.key, required this.funCamera, required this.funGallery});
final Function() funCamera; final Function() funCamera;
final Function() funGallery; final Function() funGallery;
@ -24,7 +24,7 @@ class PhotoPickerBottomSheet extends StatelessWidget {
Expanded( Expanded(
child: _buildItem('Open camera', funCamera), child: _buildItem('Open camera', funCamera),
), ),
const DividerWidget(), const TDividerWidget(),
Expanded( Expanded(
child: _buildItem('Open gallery', funGallery), child: _buildItem('Open gallery', funGallery),
), ),

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
class RemindDialog extends StatelessWidget { class TRemindDialog extends StatelessWidget {
const RemindDialog({ const TRemindDialog({
super.key, super.key,
this.title, this.title,
this.content, this.content,

View File

@ -4,8 +4,8 @@ import 'package:get/get.dart';
import 'package:trans_lark/generated/assets.dart'; import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/global/translate_manager.dart'; import 'package:trans_lark/global/translate_manager.dart';
class SpeakDialog extends StatelessWidget { class TSpeakDialog extends StatelessWidget {
const SpeakDialog({ const TSpeakDialog({
super.key, super.key,
required this.isListening, required this.isListening,
required this.onTap, required this.onTap,

View File

@ -6,16 +6,16 @@ import 'package:trans_lark/generated/assets.dart';
import 'package:trans_lark/global/flutter_tts_manager.dart'; import 'package:trans_lark/global/flutter_tts_manager.dart';
import 'package:trans_lark/global/translate_manager.dart'; import 'package:trans_lark/global/translate_manager.dart';
class TranslateTextFullScreenPage extends StatefulWidget { class TTranslateTextFullScreenPage extends StatefulWidget {
const TranslateTextFullScreenPage({super.key}); const TTranslateTextFullScreenPage({super.key});
@override @override
State<TranslateTextFullScreenPage> createState() => State<TTranslateTextFullScreenPage> createState() =>
_TranslateTextFullScreenPageState(); _TranslateTextFullScreenPageState();
} }
class _TranslateTextFullScreenPageState class _TranslateTextFullScreenPageState
extends State<TranslateTextFullScreenPage> { extends State<TTranslateTextFullScreenPage> {
String showData = ""; String showData = "";
@override @override

View File

@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
/// ///
enum ViewState { normal, error, loading, empty } enum ViewState { normal, error, loading, empty }
class ViewStateWidget extends StatelessWidget { class TViewStateWidget extends StatelessWidget {
const ViewStateWidget({ const TViewStateWidget({
super.key, super.key,
required this.viewState, required this.viewState,
required this.child, required this.child,