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 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 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 availableLanguages = [ '中文', '英文', '日文', '韩文', '法文', '德文', '西班牙文', '俄文' ]; // 语音服务类型 final Rx speechServiceType = SpeechServiceType.azure.obs; final List> 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 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 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 saveUserInfo() async { // await _storage.write(userKey, userInfo.value.toJson()); // } // 下载并保存远程头像 // Future _downloadAndSaveAvatar(String url) async { // try { // Logger().d('开始下载头像: $url'); // final dio = Dio(BaseOptions( // headers: { // 'accept': '*/*', // 'Authorization': _storage.read("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 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 updateUserName(String name) async { // if (name.trim().isNotEmpty) { // userInfo.update((user) { // if (user != null) { // user.name = name.trim(); // } // }); // await saveUserInfo(); // } // } // Future 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 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 _updateAgentLanguageSettings(LanguageModel languageModel) async { try { final languageManager = Get.find(); List 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(); speechServiceType.value = factory.currentServiceType; } catch (e) { // 如果找不到SpeechFactory实例,使用默认值 } } // 切换主题 Future 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(); 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 clearBleDevices() async { // // 显示确认对话框 // final confirmed = await Get.dialog( // 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(); // final result = await bleManager.clearPairedDevices(); // if (result) { // Get.snackbar('成功', 'BLE配对设备已清除'); // } else { // Get.snackbar('失败', '清除BLE配对设备失败'); // } // } catch (e) { // Get.snackbar('错误', '清除BLE配对设备时发生错误'); // } // } // } /// 手动检查版本更新 Future 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(); 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'; } } }