import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; import 'package:get_storage/get_storage.dart'; import '../../../core/themes/theme_service.dart'; import '../../../data/services/speech_factory.dart'; import '../models/language_model.dart'; import 'package:logger/logger.dart'; import '../../../data/services/ble_manager.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:permission_handler/permission_handler.dart'; import 'dart:async'; 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_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: '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; //状态锁,防止重复检查 // 权限相关 // 权限组,用于在UI中显示 final List> permissionGroups = [ { 'name': '通讯权限', 'icon': Icons.phone_android, 'permissions': [ {'type': Permission.phone, 'name': '电话', 'description': '用于拨打电话功能'}, {'type': Permission.sms, 'name': '短信', 'description': '用于发送短信功能'}, {'type': Permission.contacts, 'name': '通讯录', 'description': '用于访问联系人'} ] }, { 'name': '日程权限', 'icon': Icons.calendar_today, 'permissions': [ { 'type': Permission.calendarFullAccess, 'name': '日历写入', 'description': '用于创建日历事件和提醒' }, { 'type': Permission.calendarFullAccess, 'name': '日历完全访问', 'description': '用于读取和修改日历事件' } ] }, { 'name': '存储权限', 'icon': Icons.storage, 'permissions': [ {'type': Permission.storage, 'name': '存储', 'description': '用于保存录音和文件'}, {'type': Permission.photos, 'name': '照片', 'description': '用于选择和保存照片'} ] }, { 'name': '位置权限', 'icon': Icons.location_on, 'permissions': [ { 'type': Permission.location, 'name': '位置', 'description': '用于获取当前位置信息' }, { 'type': Permission.locationAlways, 'name': '后台位置', 'description': '用于后台获取位置信息' } ] }, { 'name': '媒体权限', 'icon': Icons.mic, 'permissions': [ { 'type': Permission.microphone, 'name': '麦克风', 'description': '用于语音识别和录音' }, {'type': Permission.bluetooth, 'name': '蓝牙', 'description': '用于连接蓝牙设备'} ] } ]; // 检查单个权限状态 // 打开应用设置 void openSettings() { openAppSettings(); } // 检查所有权限状态并返回结果 Future> checkAllPermissions() async { Map statuses = {}; for (var group in permissionGroups) { for (var perm in group['permissions']) { Permission permission = perm['type']; statuses[permission] = await permission.status; } } return statuses; } @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; print('版本信息: ${packageInfo.version}+${packageInfo.buildNumber}'); } catch (e) { appVersion.value = '未知'; buildNumber.value = '0'; print('获取版本信息失败: $e'); } } // 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']; } } } void setLanguage(LanguageModel data) { if (data.value != 'system') { List languageList = data.value.split('_'); Get.updateLocale(Locale(languageList[0], languageList[1])); } else { Get.updateLocale(Get.deviceLocale!); } language.value = data; _storage.write('language', data.value); Get.back(); } // 加载当前语音服务类型 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 { if (isCheckingUpdate) return; isCheckingUpdate = true; try { // 显示加载提示 Get.dialog( const Center( child: CircularProgressIndicator(), ), barrierDismissible: false, ); final versionService = VersionUpdateService.to; final updateInfo = await versionService.checkForUpdate(); // 关闭加载提示 Get.back(); if (updateInfo.hasUpdate) { // 显示更新对话框 await VersionUpdateDialog.show(updateInfo); } else { // 显示已是最新版本的提示 Get.snackbar( 'checkUpdate'.tr, 'currentLatestVersion' .tr //当前已是最新版本 .replaceAll('{version}', updateInfo.currentVersion), snackPosition: SnackPosition.TOP, backgroundColor: Colors.green.withOpacity(0.8), colorText: Colors.white, ); } } catch (e) { // 关闭加载提示 if (Get.isDialogOpen == true) { Get.back(closeOverlays: true); } Get.snackbar( 'error'.tr, 'networkErrorRetry'.tr, // 网络错误,请稍后重试 snackPosition: SnackPosition.TOP, backgroundColor: Colors.red.withOpacity(0.8), colorText: Colors.white, ); } finally { isCheckingUpdate = false; } } }