|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; |
|
|
|
import 'package:flutter/services.dart'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'package:get_storage/get_storage.dart'; |
|
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart'; |
|
|
|
|
|
|
|
import '../../../data/services/volcano_translation_service.dart'; |
|
|
|
import '../../../data/services/language_manager.dart'; |
|
|
|
@ -318,75 +319,169 @@ class TextTranslationController extends GetxController { |
|
|
|
translatedText.value = ''; |
|
|
|
} |
|
|
|
|
|
|
|
/// 显示语言选择对话框 |
|
|
|
/// 显示语言选择对话框(统一与其它翻译模式的样式) |
|
|
|
void showLanguageSelector({required bool isSourceLanguage}) { |
|
|
|
Get.bottomSheet( |
|
|
|
Container( |
|
|
|
height: Get.height * 0.6, |
|
|
|
decoration: const BoxDecoration( |
|
|
|
color: Colors.white, |
|
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)), |
|
|
|
), |
|
|
|
child: Column( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
padding: const EdgeInsets.all(16), |
|
|
|
child: Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
isSourceLanguage |
|
|
|
? 'sourceLanguage'.tr |
|
|
|
: 'targetLanguage'.tr, |
|
|
|
style: const TextStyle( |
|
|
|
fontSize: 18, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
), |
|
|
|
final isDarkMode = Theme.of(Get.context!).brightness == Brightness.dark; |
|
|
|
|
|
|
|
Get.dialog(Dialog( |
|
|
|
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(16.r), // 统一圆角尺寸 |
|
|
|
), |
|
|
|
alignment: |
|
|
|
isSourceLanguage ? Alignment.centerLeft : Alignment.centerRight, |
|
|
|
insetPadding: EdgeInsets.symmetric(horizontal: 10.w), |
|
|
|
child: SizedBox( |
|
|
|
width: 0.4.sw, |
|
|
|
child: Padding( |
|
|
|
padding: EdgeInsets.all(12.w), |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
// 标题区域 |
|
|
|
Padding( |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 8.w), |
|
|
|
child: Text( |
|
|
|
isSourceLanguage |
|
|
|
? 'selectSourceLanguage'.tr // 翻译键代表的中文文本内容 |
|
|
|
: 'selectTargetLanguage'.tr, // 翻译键代表的中文文本内容 |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
IconButton( |
|
|
|
onPressed: () => Get.back(), |
|
|
|
icon: const Icon(Icons.close), |
|
|
|
), |
|
|
|
), |
|
|
|
SizedBox(height: 16.h), |
|
|
|
|
|
|
|
// 语言列表区域 |
|
|
|
Container( |
|
|
|
constraints: BoxConstraints(maxHeight: 0.5.sh), |
|
|
|
child: SingleChildScrollView( |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: List.generate( |
|
|
|
isSourceLanguage |
|
|
|
? (supportedLanguages.length + 1) |
|
|
|
: supportedLanguages.length, |
|
|
|
(index) { |
|
|
|
// 源语言下首项为“自动检测” |
|
|
|
final displayText = isSourceLanguage && index == 0 |
|
|
|
? 'autoDetect'.tr // 翻译键代表的中文文本内容 |
|
|
|
: (isSourceLanguage |
|
|
|
? supportedLanguages[index - 1] |
|
|
|
: supportedLanguages[index]); |
|
|
|
final valueText = isSourceLanguage && index == 0 |
|
|
|
? '自动检测' |
|
|
|
: (isSourceLanguage |
|
|
|
? supportedLanguages[index - 1] |
|
|
|
: supportedLanguages[index]); |
|
|
|
|
|
|
|
final isSelected = isSourceLanguage |
|
|
|
? valueText == sourceLanguageChineseName.value |
|
|
|
: valueText == targetLanguageChineseName.value; |
|
|
|
|
|
|
|
return GestureDetector( |
|
|
|
onTap: () { |
|
|
|
if (isSourceLanguage) { |
|
|
|
setSourceLanguage(valueText); |
|
|
|
} else { |
|
|
|
setTargetLanguage(valueText); |
|
|
|
} |
|
|
|
Get.back(); |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
margin: EdgeInsets.only(bottom: 10.h), |
|
|
|
padding: EdgeInsets.all(10.w), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isSelected |
|
|
|
? (isDarkMode |
|
|
|
? const Color(0xFF6200EE) |
|
|
|
.withOpacity(0.2) |
|
|
|
: Colors.blue.withOpacity(0.1)) |
|
|
|
: (isDarkMode |
|
|
|
? Colors.white.withOpacity(0.05) |
|
|
|
: Colors.grey[200]!), |
|
|
|
borderRadius: BorderRadius.circular(12.r), |
|
|
|
border: Border.all( |
|
|
|
color: isSelected |
|
|
|
? (isDarkMode |
|
|
|
? const Color(0xFF6200EE) |
|
|
|
: Colors.blue) |
|
|
|
: (isDarkMode |
|
|
|
? Colors.white.withOpacity(0.05) |
|
|
|
: Colors.grey[200]!), |
|
|
|
width: 1, |
|
|
|
), |
|
|
|
), |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
// 语言名称(中文名直接显示不进行翻译) |
|
|
|
Expanded( |
|
|
|
child: Text( |
|
|
|
displayText, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: isDarkMode |
|
|
|
? Colors.white |
|
|
|
: Colors.black87, |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
// 选中指示器 |
|
|
|
Container( |
|
|
|
width: 24.w, |
|
|
|
height: 24.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isSelected |
|
|
|
? (isDarkMode |
|
|
|
? const Color(0xFF6200EE) |
|
|
|
: Colors.blue) |
|
|
|
: (isDarkMode |
|
|
|
? Colors.white.withOpacity(0.1) |
|
|
|
: Colors.grey[300]), |
|
|
|
shape: BoxShape.circle, |
|
|
|
), |
|
|
|
child: isSelected |
|
|
|
? Icon( |
|
|
|
Icons.check, |
|
|
|
size: 16.w, |
|
|
|
color: Colors.white, |
|
|
|
) |
|
|
|
: null, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
}, |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
const Divider(height: 1), |
|
|
|
Expanded( |
|
|
|
child: ListView.builder( |
|
|
|
itemCount: (isSourceLanguage |
|
|
|
? (supportedLanguages.length + 1) |
|
|
|
: supportedLanguages.length), |
|
|
|
itemBuilder: (context, index) { |
|
|
|
final language = isSourceLanguage |
|
|
|
? (index == 0 |
|
|
|
? '自动检测' |
|
|
|
: supportedLanguages[index - 1]) |
|
|
|
: supportedLanguages[index]; |
|
|
|
final isSelected = isSourceLanguage |
|
|
|
? language == sourceLanguageChineseName.value |
|
|
|
: language == targetLanguageChineseName.value; |
|
|
|
|
|
|
|
return ListTile( |
|
|
|
title: Text(language), |
|
|
|
trailing: isSelected |
|
|
|
? const Icon(Icons.check, color: Colors.blue) |
|
|
|
: null, |
|
|
|
onTap: () { |
|
|
|
if (isSourceLanguage) { |
|
|
|
setSourceLanguage(language); |
|
|
|
} else { |
|
|
|
setTargetLanguage(language); |
|
|
|
} |
|
|
|
Get.back(); |
|
|
|
}, |
|
|
|
); |
|
|
|
}, |
|
|
|
SizedBox(height: 16.h), |
|
|
|
|
|
|
|
// 取消按钮 |
|
|
|
Align( |
|
|
|
alignment: Alignment.centerRight, |
|
|
|
child: TextButton( |
|
|
|
onPressed: () => Get.back(), |
|
|
|
child: Text( |
|
|
|
'cancel'.tr, // 翻译键代表的中文文本内容 |
|
|
|
style: TextStyle( |
|
|
|
color: |
|
|
|
isDarkMode ? const Color(0xFF6200EE) : Colors.blue, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
isScrollControlled: true, |
|
|
|
); |
|
|
|
)); |
|
|
|
} |
|
|
|
} |
|
|
|
|