You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

663 lines
22 KiB

import 'dart:async';
import 'package:agent_service/agent_service.dart';
import 'package:get/get.dart';
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:get_storage/get_storage.dart';
import 'package:logger/logger.dart';
import 'package:package_info_plus/package_info_plus.dart';
import '../../../core/themes/theme_service.dart';
import '../../../core/translations/app_translations.dart';
import '../../../data/services/network/dio_manager.dart';
import '../../../data/services/speech_factory.dart';
import '../../../routes/app_routes.dart';
import '../models/language_model.dart';
import '../../../data/services/ble_manager.dart';
import '../../../data/services/language_manager.dart';
import '../../../data/services/version_update_service.dart';
import '../../common/widgets/version_update_dialog.dart';
class SettingsController extends GetxController {
// 语言设置
final List<LanguageModel> languageList = [
LanguageModel(
name: 'followingSystem', alias: '', value: 'system'), // 跟随系统.tr
LanguageModel(name: 'english', alias: 'English', value: 'en_US'), // 英语.tr
LanguageModel(name: 'chinese', alias: '中文', value: 'zh_CN'), // 中文.tr
LanguageModel(
name: 'traditionalChinese', alias: '繁體中文', value: 'zh_TW'), // 添加繁体中文
LanguageModel(
name: 'traditionalChineseHK', alias: '繁體中文(HK)', value: 'zh_HK'), // 添加香港繁体中文
LanguageModel(
name: 'spanish', alias: 'Español', value: 'es_ES'), // 添加西班牙语选项
LanguageModel(
name: 'portuguese', alias: 'Português', value: 'pt_PT'), // 添加葡萄牙语
LanguageModel(name: 'japanese', alias: '日本語', value: 'ja_JP'), // 添加日语选项
LanguageModel(name: 'korean', alias: '한국어', value: 'ko_KR'), // 添加韩语选项
LanguageModel(name: 'french', alias: 'Français', value: 'fr_FR'), // 添加法语选项
LanguageModel(name: 'german', alias: 'Deutsch', value: 'de_DE'), // 添加德语选项
LanguageModel(name: 'russian', alias: 'Русский', value: 'ru_RU'), // 添加俄语选项
LanguageModel(name: 'arabic', alias: 'العربية', value: 'ar_SA'), // 阿拉伯语
LanguageModel(name: 'persian', alias: 'فارسی', value: 'fa_IR'), // 波斯语
LanguageModel(
name: 'vietnamese', alias: 'Tiếng Việt', value: 'vi_VN'), // 添加越南语选项
LanguageModel(
name: 'italian', alias: 'Italiano', value: 'it_IT'), // 添加意大利语选项
LanguageModel(
name: 'hindi', alias: 'हिन्दी', value: 'hi_IN'), // 添加印度语(印地语)选项
LanguageModel(
name: 'indonesian',
alias: 'Bahasa Indonesia',
value: 'id_ID'), // 添加印尼语选项
LanguageModel(name: 'thai', alias: 'ไทย', value: 'th_TH'), // 添加泰语选项
LanguageModel(
name: 'malay', alias: 'Bahasa Melayu', value: 'ms_MY'), // 添加马来语选项
LanguageModel(name: 'turkish', alias: 'Türkçe', value: 'tr_TR'), // 添加土耳其语选项
LanguageModel(name: 'polish', alias: 'Polski', value: 'pl_PL'), // 添加波兰语选项
LanguageModel(name: 'filipino', alias: 'Filipino', value: 'tl_PH'), // 菲律宾语
LanguageModel(name: 'dutch', alias: 'Nederlands', value: 'nl_NL'), // 荷兰语
LanguageModel(name: 'swedish', alias: 'Svenska', value: 'sv_SE'), // 瑞典语
LanguageModel(name: 'danish', alias: 'Dansk', value: 'da_DK'), // 丹麦语
LanguageModel(name: 'finnish', alias: 'Suomi', value: 'fi_FI'), // 芬兰语
LanguageModel(name: 'czech', alias: 'Čeština', value: 'cs_CZ'), // 捷克语
LanguageModel(name: 'hungarian', alias: 'Magyar', value: 'hu_HU'), // 匈牙利语
LanguageModel(name: 'norwegian', alias: 'Norsk', value: 'nb_NO'), // 挪威语
LanguageModel(name: 'romanian', alias: 'Română', value: 'ro_RO'), // 罗马尼亚语
LanguageModel(
name: 'ukrainian', alias: 'Українська', value: 'uk_UA'), // 乌克兰语
LanguageModel(name: 'greek', alias: 'Ελληνικά', value: 'el_GR'), // 希腊语
LanguageModel(
name: 'bulgarian', alias: 'Български', value: 'bg_BG'), // 保加利亚语
LanguageModel(name: 'croatian', alias: 'Hrvatski', value: 'hr_HR'), // 克罗地亚语
LanguageModel(name: 'slovak', alias: 'Slovenský', value: 'sk_SK'), // 斯洛伐克语
LanguageModel(
name: 'slovenian', alias: 'Slovenščina', value: 'sl_SI'), // 斯洛文尼亚语
LanguageModel(
name: 'lithuanian', alias: 'Lietuvių', value: 'lt_LT'), // 立陶宛语
LanguageModel(name: 'latvian', alias: 'Latviešu', value: 'lv_LV'), // 拉脱维亚语
LanguageModel(name: 'estonian', alias: 'Eesti', value: 'et_EE'), // 爱沙尼亚语
LanguageModel(
name: 'serbian', alias: 'Srpski', value: 'sr_RS'), // 塞尔维亚语(拉丁)
LanguageModel(name: 'icelandic', alias: 'Íslenska', value: 'is_IS'), // 冰岛语
];
Rx<LanguageModel> language = LanguageModel().obs;
final GetStorage _storage = GetStorage();
// 主题服务
final ThemeService _themeService = ThemeService();
// 是否是暗黑模式
final RxBool isDarkMode = false.obs;
// 翻译语言对
final RxString sourceLanguage = '中文'.obs;
final RxString targetLanguage = '英文'.obs;
final List<String> availableLanguages = [
'中文',
'英文',
'日文',
'韩文',
'法文',
'德文',
'西班牙文',
'俄文'
];
// 语音服务类型
final Rx<SpeechServiceType> speechServiceType = SpeechServiceType.azure.obs;
final List<Map<String, dynamic>> availableSpeechServices = [
{
'type': SpeechServiceType.azure,
'name': 'azureVoiceService', // Azure 语音服务.tr
'description': 'azureVoiceServiceInfo' // 微软云端语音服务,支持高质量语音合成和识别.tr
},
{
'type': SpeechServiceType.flutter,
'name': 'flutterVoiceService', // Flutter 本地语音服务.tr
'description': 'flutterVoiceServiceInfo' // 设备本地语音服务,无需联网即可使用.tr
},
];
RxString timbreName = 'defaultTimbre'.obs;
//用户信息
// static const String userKey = 'user_info';
// final Rx<User> userInfo = User.instance.obs; //使用单例实例
// 添加版本信息变量
final appVersion = ''.obs;
final buildNumber = ''.obs;
bool isCheckingUpdate = false; //状态锁,防止重复检查
DateTime? lastCheckTime; // 添加上次检查时间记录
// 隐藏功能变量
int _clickCount = 0; // 点击计数
DateTime? _lastClickTime; // 上次点击时间
final RxBool showDebugInfo = false.obs; // 是否显示调试信息
@override
void onInit() {
super.onInit();
// 获取系统语言
_getLanguage();
_getTimbre();
// 从存储中加载上次保存的主题设置
final savedDarkMode = _themeService.isSavedDarkMode();
// 设置当前主题状态
isDarkMode.value = savedDarkMode;
// 获取当前语音服务类型
_loadCurrentSpeechServiceType();
//获取用户信息
// loadUserInfo();
// 获取应用版本信息
getAppVersion();
}
// 获取应用版本信息的方法
Future<void> getAppVersion() async {
try {
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
appVersion.value = packageInfo.version;
buildNumber.value = packageInfo.buildNumber;
} catch (e) {
appVersion.value = '未知';
buildNumber.value = '0';
}
}
// void loadUserInfo() {
// final userJson = _storage.read(userKey);
// Logger().d('加载用户信息: $userJson');
// if (userJson != null) {
// userInfo.value = User.instance;
// Logger().d('用户信息已加载: ${userInfo.value.toJson()}');
// if (userInfo.value.avatar.isNotEmpty) {
// Logger().d('开始下载头像');
// _downloadAndSaveAvatar(userInfo.value.avatar);
// } else {
// Logger().d('用户没有头像');
// }
// } else {
// Logger().d('没有找到用户信息');
// }
// }
// Future<void> saveUserInfo() async {
// await _storage.write(userKey, userInfo.value.toJson());
// }
// 下载并保存远程头像
// Future<void> _downloadAndSaveAvatar(String url) async {
// try {
// Logger().d('开始下载头像: $url');
// final dio = Dio(BaseOptions(
// headers: {
// 'accept': '*/*',
// 'Authorization': _storage.read<String>("logintoken"),
// },
// ));
// final response = await dio.get(
// url,
// options: Options(responseType: ResponseType.bytes),
// );
// Logger().d('下载状态: ${response.statusCode}');
// if (response.statusCode == 200) {
// // 保存到应用文档目录
// final appDir = await getApplicationSupportDirectory();
// final fileName =
// '/UserAvatar/avatar_${DateTime.now().millisecondsSinceEpoch}.jpg';
// final localPath = '${appDir.path}/$fileName';
// // 确保目录存在
// final file = File(localPath);
// await file.parent.create(recursive: true);
// await file.writeAsBytes(response.data);
// // 更新本地头像路径
// //localAvatar.value = localPath;
// await _storage.write('local_avatar', localPath);
// Logger().d('头像已下载到本地: $localPath');
// //Get.snackbar('头像', '头像已下载到本地');
// }
// } catch (e) {
// Logger().e('下载头像失败: $e');
// }
// }
// Future<void> updateUserAvatar() async {
// final XFile? image = await _picker.pickImage(
// source: ImageSource.gallery,
// maxWidth: 800,
// maxHeight: 800,
// imageQuality: 85,
// );
// if (image != null) {
// userInfo.update((user) {
// if (user != null) {
// user.avatar = image.path;
// }
// });
// await saveUserInfo();
// }
// }
// Future<void> updateUserName(String name) async {
// if (name.trim().isNotEmpty) {
// userInfo.update((user) {
// if (user != null) {
// user.name = name.trim();
// }
// });
// await saveUserInfo();
// }
// }
// Future<void> updateDeviceName(String deviceName) async {
// userInfo.update((user) {
// if (user != null) {
// user.deviceName = deviceName;
// }
// });
// await saveUserInfo();
// }
// }
void _getLanguage() {
String? languageValue = _storage.read('language');
LanguageModel data = languageList.firstWhere(
(element) => element.value == languageValue,
orElse: () => languageList[0],
);
language.value = data;
}
// 获取音色
void _getTimbre() {
List? timbreList = _storage.read('timbreList');
String? timbre = _storage.read('timbre');
if (timbreList != null && timbre != null) {
Map data = timbreList.firstWhere(
(element) => element['type'] == timbre,
orElse: () => {},
);
if (data.isNotEmpty) {
timbreName.value = data['name'];
}
}
}
/// 设置语言
Future<void> setLanguage(LanguageModel data) async {
try {
// 如果用户选择的语言与当前语言一致,则直接返回,避免重复设置
// print('lxm--设置语言: ${data.value}');
// print('lxm--当前语言: ${language.value.value}');
if (data.value == language.value.value) {
return;
}
Locale? targetLocale;
// print('lxm--设置语言: ${data.value}');
if (data.value != 'system') {
// 用户手动选择的语言
List languageList = data.value.split('_');
targetLocale = Locale(languageList[0], languageList[1]);
} else {
// 跟随系统语言,使用智能匹配
targetLocale = Get.deviceLocale;
if (targetLocale != null) {
// 智能匹配系统语言到支持的语言
targetLocale = AppTranslations.getMatchedLocale(targetLocale);
}
}
if (targetLocale != null) {
Get.updateLocale(targetLocale);
print("设置语言: ${data.value} -> ${targetLocale.toString()}");
} else {
// 如果无法确定目标语言,使用智能fallback
targetLocale = AppTranslations.getSmartFallbackLocale();
Get.updateLocale(targetLocale);
print("使用fallback语言: ${targetLocale.toString()}");
}
// 保存用户选择
language.value = data;
await _storage.write('language', data.value);
// 更新agent服务的语音识别语言设置
await _updateAgentLanguageSettings(data);
// 显示语言切换成功提示
// Get.snackbar(
// 'success'.tr,
// 'languageChanged'.tr, // 需要在语言文件中添加这个key
// snackPosition: SnackPosition.TOP,
// duration: const Duration(seconds: 2),
// );
// 延迟一下确保语言更新完成,然后重新进入应用
await Future.delayed(const Duration(milliseconds: 500));
// 重新进入应用 - 回到启动页面重新初始化
Get.offAllNamed(Routes.splash);
Get.back();
} catch (e) {
print("设置语言时出错: $e");
// Get.snackbar(
// 'error'.tr,
// 'languageChangeFailed'.tr, // 需要在语言文件中添加这个key
// snackPosition: SnackPosition.TOP,
// backgroundColor: Colors.red.withValues(alpha: 0.8),
// colorText: Colors.white,
// );
}
}
/// 更新agent服务的语音识别语言设置
Future<void> _updateAgentLanguageSettings(LanguageModel languageModel) async {
try {
final languageManager = Get.find<LanguageManager>();
List<String> supportedLanguages = [];
// 根据选择的语言设置对应的ASR语言代码
if (languageModel.value == 'system') {
// 跟随系统语言
final deviceLocale = Get.deviceLocale;
if (deviceLocale != null) {
final lang = deviceLocale.languageCode;
final country = deviceLocale.countryCode;
if (country != null && country.isNotEmpty) {
supportedLanguages.add('$lang-$country');
} else {
// 根据语言代码映射到对应的ASR代码
final asrCode = languageManager.getAsrCodeByShortCode(lang);
if (asrCode != null) {
supportedLanguages.add(asrCode);
} else {
supportedLanguages.add('en-US'); // 默认英语
}
}
} else {
supportedLanguages.add('en-US'); // 默认英语
}
} else {
// 根据选择的语言值映射到ASR代码
final parts = languageModel.value.split('_');
if (parts.length == 2) {
final asrCode = languageManager.getAsrCodeByShortCode(parts[0]);
if (asrCode != null) {
supportedLanguages.add(asrCode);
} else {
// 直接使用语言-国家格式
supportedLanguages.add('${parts[0]}-${parts[1]}');
}
}
}
// 确保至少有一个语言
if (supportedLanguages.isEmpty) {
supportedLanguages.add('en-US');
}
Logger().i('更新agent服务语音识别语言: ${supportedLanguages.join(', ')}');
// 调用agent服务更新语言设置
final success =
await AgentService.setSupportedLanguages(supportedLanguages);
if (success) {
Logger().i('agent服务语言设置更新成功');
} else {
Logger().w('agent服务语言设置更新失败');
}
} catch (e) {
Logger().e('更新agent服务语言设置时出错: $e');
}
}
// 加载当前语音服务类型
void _loadCurrentSpeechServiceType() {
try {
final factory = Get.find<SpeechFactory>();
speechServiceType.value = factory.currentServiceType;
} catch (e) {
// 如果找不到SpeechFactory实例,使用默认值
}
}
// 切换主题
Future<void> toggleTheme() async {
// 切换暗黑模式状态
isDarkMode.value = !isDarkMode.value;
// 更新全局主题
Get.changeThemeMode(isDarkMode.value ? ThemeMode.dark : ThemeMode.light);
// 保存用户选择的主题设置 - 确保立即写入存储
await _themeService.saveThemeMode(isDarkMode.value);
}
// 设置语音服务类型
void setSpeechServiceType(SpeechServiceType type) {
try {
final factory = Get.find<SpeechFactory>();
factory.setServiceType(type);
speechServiceType.value = type;
} catch (e) {
// 处理错误
}
}
void setSourceLanguage(String language) {
sourceLanguage.value = language;
}
void setTargetLanguage(String language) {
targetLanguage.value = language;
}
void swapLanguages() {
final temp = sourceLanguage.value;
sourceLanguage.value = targetLanguage.value;
targetLanguage.value = temp;
}
/// 清除BLE配对设备
// Future<void> clearBleDevices() async {
// // 显示确认对话框
// final confirmed = await Get.dialog<bool>(
// AlertDialog(
// title: const Text('清除配对设备'),
// content: const Text('确定要清除所有BLE配对设备吗?此操作不可撤销。'),
// actions: [
// TextButton(
// onPressed: () => Get.back(result: false),
// child: Text('cancel'.tr),
// ),
// TextButton(
// onPressed: () => Get.back(result: true),
// style: TextButton.styleFrom(
// foregroundColor: Colors.red,
// ),
// child: Text('confirm'.tr), //确认
// ),
// ],
// ),
// );
// if (confirmed == true) {
// try {
// final bleManager = Get.find<BleManager>();
// final result = await bleManager.clearPairedDevices();
// if (result) {
// Get.snackbar('成功', 'BLE配对设备已清除');
// } else {
// Get.snackbar('失败', '清除BLE配对设备失败');
// }
// } catch (e) {
// Get.snackbar('错误', '清除BLE配对设备时发生错误');
// }
// }
// }
/// 手动检查版本更新
Future<void> checkForUpdate() async {
// 检查是否在2秒内重复调用
final now = DateTime.now();
if (lastCheckTime != null && now.difference(lastCheckTime!).inSeconds < 2) {
// 在2秒内重复调用,直接返回
// Get.snackbar(
// 'checkUpdate'.tr,
// 'checkUpdateTooFrequent'.tr, // 检查更新过于频繁,请稍后再试
// snackPosition: SnackPosition.TOP,
// backgroundColor: Colors.orange.withValues(alpha: 0.8),
// colorText: Colors.white,
// );
return;
}
if (isCheckingUpdate) return;
isCheckingUpdate = true;
lastCheckTime = now; // 记录本次检查时间
// 用于跟踪我们的对话框
bool dialogShown = false;
try {
// 显示加载提示
dialogShown = true;
Get.dialog(
const Center(
child: CircularProgressIndicator(),
),
barrierDismissible: false,
);
final versionService = VersionUpdateService.to;
final updateInfo = await versionService.checkForUpdate();
// 关闭加载提示 - 使用精确的关闭方式
if (dialogShown) {
dialogShown = false;
// 直接关闭最顶层的对话框,不依赖状态判断
Navigator.of(Get.overlayContext!).pop();
}
if (updateInfo.hasUpdate) {
// 显示更新对话框
await VersionUpdateDialog.show(updateInfo);
} else {
// 显示已是最新版本的提示
Get.snackbar(
'checkUpdate'.tr,
'currentLatestVersion'
.tr //当前已是最新版本
.replaceAll('{version}', updateInfo.currentVersion),
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.green.withValues(alpha: 0.8),
colorText: Colors.white,
);
}
} catch (e) {
// 关闭加载提示 - 异常情况下的可靠关闭
if (dialogShown) {
dialogShown = false;
try {
// 尝试直接关闭
Navigator.of(Get.overlayContext!).pop();
} catch (popError) {
// 如果直接关闭失败,使用备用方案
if (Get.isDialogOpen == true) {
Get.back();
}
}
}
Get.snackbar(
'error'.tr,
'networkErrorRetry'.tr, // 网络错误,请稍后重试
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withValues(alpha: 0.8),
colorText: Colors.white,
);
} finally {
isCheckingUpdate = false;
}
}
/// 处理隐藏功能点击
void handleSecretTap() {
final now = DateTime.now();
// 如果距离上次点击超过2秒,重置计数
if (_lastClickTime != null &&
now.difference(_lastClickTime!).inSeconds > 2) {
_clickCount = 0;
}
_lastClickTime = now;
_clickCount++;
// 点击5次后显示版本信息
if (_clickCount >= 5) {
showDebugInfo.value = !showDebugInfo.value;
_clickCount = 0;
// Get.snackbar(
// showDebugInfo.value ? '调试信息已显示' : '调试信息已隐藏',
// '版本服务数据',
// snackPosition: SnackPosition.TOP,
// backgroundColor: Colors.blue.withOpacity(0.8),
// colorText: Colors.white,
// duration: const Duration(seconds: 1),
// );
}
}
/// 获取当前应用数据
String getSomeAppData() {
try {
final versionService = Get.find<VersionUpdateService>();
return '''
应用版本: ${versionService.cachedAppVersion}
构建号: ${versionService.cachedBuildNumber}
平台: ${versionService.cachedPlatform}
设备品牌: ${versionService.cachedDeviceBrand}
渠道: ${versionService.cachedChannel}
最新版本: ${versionService.cachedLatestVersion}
有更新: ${versionService.cachedHasUpdate}
强制更新: ${versionService.cachedIsForceUpdate}
更新链接: ${versionService.cachedUpdateUrl}
游客模式: ${versionService.cachedShowTourists}
最近版本检查时间: ${versionService.lastCheckTime ?? '未检查'}
国家地区编码: ${versionService.cachedCountryCode}
语言编码: ${versionService.cachedLanguageCode}
服务器地址: ${DioManager().baseUrl}
''';
} catch (e) {
return '获取版本服务数据失败: $e';
}
}
}