139 lines
4.1 KiB
Dart
139 lines
4.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_translate/common/utils/bot_toast.dart';
|
|
import 'package:flutter_translate/common/utils/log_utils.dart';
|
|
import 'package:flutter_translate/common/utils/object_utils.dart';
|
|
import 'package:flutter_translate/manager/speech_convert.dart';
|
|
import 'package:flutter_translate/manager/translate.dart';
|
|
import 'package:flutter_translate/pages/home/home_controller.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:speech_to_text/speech_recognition_result.dart';
|
|
import 'package:translator/translator.dart';
|
|
|
|
class FaceToFaceController extends GetxController
|
|
with GetSingleTickerProviderStateMixin {
|
|
final aboveScrollController = ScrollController();
|
|
final underScrollController = ScrollController();
|
|
HomeController homeController = Get.find<HomeController>();
|
|
|
|
var angle = 0.0.obs;
|
|
|
|
/// 显示的文本
|
|
var aboveText = ''.obs;
|
|
var underText = ''.obs;
|
|
|
|
/// 翻译
|
|
final _translator = GoogleTranslator();
|
|
|
|
/// 是否选择的下方
|
|
var selectedUnder = true.obs;
|
|
|
|
@override
|
|
void onReady() async {
|
|
super.onReady();
|
|
loading();
|
|
speak(true);
|
|
}
|
|
|
|
@override
|
|
void onClose() async {
|
|
await SpeechConvert().stop(showLoading: false);
|
|
aboveScrollController.dispose();
|
|
underScrollController.dispose();
|
|
super.onClose();
|
|
}
|
|
|
|
/// 旋转 180 度
|
|
void onRotate() {
|
|
angle.value -= 0.5;
|
|
}
|
|
|
|
Future<void> speak(bool isUnder, {int? speakType}) async {
|
|
if (!SpeechConvert().hasSpeech) {
|
|
await SpeechConvert().init();
|
|
}
|
|
if (SpeechConvert().hasSpeech) {
|
|
if (isUnder) {
|
|
if (!selectedUnder.value) {
|
|
await SpeechConvert().stop();
|
|
}
|
|
selectedUnder.value = true;
|
|
_scrollToBottom();
|
|
SpeechConvert().start(
|
|
Translate().fromLanguageEntity.value.code,
|
|
_speechResult,
|
|
);
|
|
} else {
|
|
if (selectedUnder.value) {
|
|
await SpeechConvert().stop();
|
|
}
|
|
selectedUnder.value = false;
|
|
_scrollToBottom();
|
|
SpeechConvert().start(
|
|
Translate().toLanguageEntity.value.code,
|
|
_speechResult,
|
|
);
|
|
}
|
|
} else {
|
|
toast('Speech not available');
|
|
}
|
|
}
|
|
|
|
Future<void> _speechResult(SpeechRecognitionResult result) async {
|
|
Log.d('识别结果:${result.recognizedWords}');
|
|
if (ObjectUtils.isNotEmptyStr(result.recognizedWords)) {
|
|
if (selectedUnder.value) {
|
|
underText.value += '${result.recognizedWords}\n';
|
|
var translateText = await _translation(result.recognizedWords);
|
|
Log.d('翻译结果:${result.recognizedWords}');
|
|
if (ObjectUtils.isNotEmptyStr(translateText)) {
|
|
aboveText.value += '$translateText\n';
|
|
}
|
|
} else {
|
|
aboveText.value += '${result.recognizedWords}\n';
|
|
var translateText = await _translation(result.recognizedWords);
|
|
if (ObjectUtils.isNotEmptyStr(translateText)) {
|
|
underText.value += '$translateText\n';
|
|
}
|
|
}
|
|
_scrollToBottom();
|
|
}
|
|
}
|
|
|
|
Future<String> _translation(String sourceText, {int? translationType}) async {
|
|
try {
|
|
String from = selectedUnder.value
|
|
? Translate().fromLanguageEntity.value.code
|
|
: Translate().toLanguageEntity.value.code;
|
|
String to = selectedUnder.value
|
|
? Translate().toLanguageEntity.value.code
|
|
: Translate().fromLanguageEntity.value.code;
|
|
Translation translate = await _translator.translate(
|
|
sourceText,
|
|
from: from,
|
|
to: to,
|
|
);
|
|
return translate.text;
|
|
} catch (e) {
|
|
Log.d('Translation failed,${e.toString()}');
|
|
}
|
|
return '';
|
|
}
|
|
|
|
void _scrollToBottom() {
|
|
if (aboveScrollController.hasClients) {
|
|
aboveScrollController.animateTo(
|
|
aboveScrollController.position.maxScrollExtent,
|
|
duration: const Duration(milliseconds: 200),
|
|
curve: Curves.easeOut,
|
|
);
|
|
}
|
|
if (underScrollController.hasClients) {
|
|
underScrollController.animateTo(
|
|
underScrollController.position.maxScrollExtent,
|
|
duration: const Duration(milliseconds: 200),
|
|
curve: Curves.easeOut,
|
|
);
|
|
}
|
|
}
|
|
}
|