import 'dart:io'; import 'dart:convert'; import 'package:get/get.dart'; import 'package:naiyouwl/app/clash/mode/config.dart'; import 'package:naiyouwl/app/const/const.dart'; import 'package:path/path.dart' as path; import 'package:yaml/yaml.dart'; import 'package:yaml_edit/yaml_edit.dart'; import '../common/LogHelper.dart'; import '../common/constants.dart'; final Map _defaultConfig = { 'selected': 'example.yaml', 'updateInterval': 86400, 'updateSubsAtStart': false, 'setSystemProxy': false, 'startAtLogin': false, 'breakConnections': false, 'language': 'zh_CN', 'servicePort': 9899, 'dnsPort': ":1053", }; final Map _defaultVersionConfig = { 'serviceVersion': '1.0.0', 'coreVersion': '1.18.8', 'appVersion': kVersion, }; class ConfigController extends GetxController { var config = GuiConfig.fromJson(_defaultConfig).obs; var versionConfig = VersionConfig.fromJson(_defaultVersionConfig).obs; var isInitialized = false.obs; var clashCoreApiAddress = '127.0.0.1:9799'.obs; var clashCoreApiSecret = ''.obs; var clashCoreDns = ''.obs; var clashCoreTunEnable = false.obs; var mixedPort = 9788.obs; var apiAddressPort = 9799.obs; var servicePort = 9899.obs; var dnsPort = kDnsListenPort.obs; Future initConfig() async { try { if (await Paths.config.exists()) { if (await Files.versionConfig.exists()) { final localVersionConfig = json.decode(await Files.versionConfig.readAsString()); final localAppVersion = localVersionConfig['appVersion']; if (compareVersions(localAppVersion, kVersion) < 0) { await Paths.config.delete(recursive: true); await Paths.config.create(recursive: true); } } else { await Paths.config.delete(recursive: true); await Paths.config.create(recursive: true); } } // 创建用户配置目录 if (!await Paths.config.exists()) { await Paths.config.create(recursive: true); } // 复制资源文件到配置目录 await _copyAssetToConfig(Files.assetsCountryMmdb, Files.configCountryMmdb); await _copyAssetToConfig(Files.assetsGeoIP, Files.configGeoIP); await _copyAssetToConfig(Files.assetsGeosite, Files.configGeosite); if (Platform.isWindows) { await _copyAssetToConfig(Files.assetsWintun, Files.configWintun); } // 设置默认语言 final locale = Get.deviceLocale!; _defaultConfig['language'] = '${locale.languageCode}_${locale.countryCode}'; // 读取或创建配置文件 if (await Files.configConfig.exists()) { final local = json.decode(await Files.configConfig.readAsString()); config.value = GuiConfig.fromJson({..._defaultConfig, ...local}); } else { config.value = GuiConfig.fromJson(_defaultConfig); } // 读取或创建版本配置文件 if (await Files.versionConfig.exists()) { final local = json.decode(await Files.versionConfig.readAsString()); versionConfig.value = VersionConfig.fromJson({..._defaultVersionConfig, ...local}); } else { versionConfig.value = VersionConfig.fromJson(_defaultVersionConfig); } print(Files.configConfig.path); // 保存 GuiConfig 到 gui_config.json await saveGuiConfig(); // 保存 VersionConfig 到 version_config.json await saveVersionConfig(); isInitialized.value = true; } catch (e) { LogHelper().e("配置初始化失败: $e"); isInitialized.value = false; rethrow; } } Future saveConfig() async { // 保存 GuiConfig 到 gui_config.json await saveGuiConfig(); // 保存 VersionConfig 到 version_config.json await saveVersionConfig(); } // 比较两个版本号 int compareVersions(String v1, String v2) { var parts1 = v1.split('.'); var parts2 = v2.split('.'); for (int i = 0; i < 3; i++) { int p1 = int.parse(parts1[i]); int p2 = int.parse(parts2[i]); if (p1 != p2) { return p1 - p2; } } return 0; } // 返回一个可修改的 GUI 配置对象 GuiConfig getEditableGuiConfig() { return config.value; } // 更新 GUI 配置 Future updateGuiConfig(GuiConfig updatedConfig) async { config.value = updatedConfig; await saveGuiConfig(); } // 返回一个可修改的版本配置对象 VersionConfig getEditableVersionConfig() { return versionConfig.value; } // 更新版本配置 Future updateVersionConfig(VersionConfig updatedVersionConfig) async { versionConfig.value = updatedVersionConfig; await saveVersionConfig(); } // 示例使用方法: // var editableConfig = getEditableGuiConfig(); // editableConfig.language = 'en_US'; // editableConfig.startAtLogin = true; // await updateGuiConfig(editableConfig); Future saveGuiConfig() async { await Files.configConfig.writeAsString(json.encode(config.value.toJson())); } Future saveVersionConfig() async { await Files.versionConfig.writeAsString(json.encode(versionConfig.value.toJson())); } Future _copyAssetToConfig(File source, File destination) async { if (!await destination.exists()) { await source.copy(destination.path); } } Future readClashCoreApi() async { final configStr = await File(path.join(Paths.config.path, config.value.selected)).readAsString(); final yamlEditor = YamlEditor(configStr); final configMap = yamlEditor.parseAt([]) as YamlMap; clashCoreApiAddress.value = configMap['external-controller'] as String? ?? '127.0.0.1:9090'; print("clash api address ${clashCoreApiAddress.value}"); clashCoreApiSecret.value = (configMap['secret'] as String? ?? ''); mixedPort.value = (configMap['mixed-port'] as int? ?? 9788); var tun = (configMap['tun'] as YamlMap?)?['enable']; clashCoreTunEnable.value = tun == null ? false : tun; clashCoreDns.value = ''; var dnsEnable = (configMap['dns'] as YamlMap?)?['enable']; if(dnsEnable != null) { final dns = ((configMap['dns'] as YamlMap)['listen'] as String? ?? '').split(':'); if (dns.length == 2) { final ip = dns[0]; final port = dns[1]; if (port == '53') { clashCoreDns.value = ip == '0.0.0.0' ? '127.0.0.1' : ip; } } } } // 在 GlobalController 中可以这样使用 bool get initialized => isInitialized.value; }