diff --git a/lib/common/helper/log_helper.dart b/lib/common/helper/log_helper.dart index ded2d69..537d87f 100644 --- a/lib/common/helper/log_helper.dart +++ b/lib/common/helper/log_helper.dart @@ -1,6 +1,8 @@ import 'dart:convert'; import 'dart:io'; +import 'package:hive/hive.dart'; + import '../utils/base_utils.dart'; class SCLoggerHelper { @@ -48,33 +50,59 @@ class SCLoggerHelper { List withVersion = const ["LIVE"]}) async { List scInstallPaths = []; - for (var v in withVersion) { - for (var i = listData.length - 1; i > 0; i--) { - final m = listData[i]; - final info = m["[browser][info] "]; - if (info is String) { - String installPath = ""; - if (info.contains("Installing Star Citizen $v")) { - installPath = "${info.split(" at ")[1]}\\$v"; - } - if (info.contains("Launching Star Citizen $v from")) { - installPath = info - .replaceAll("Launching Star Citizen $v from (", "") - .replaceAll(")", ""); - } - if (installPath.isNotEmpty && !scInstallPaths.contains(installPath)) { - if (!checkExists) { - dPrint("find installPath == $installPath"); - scInstallPaths.add(installPath); - } else if (await File("$installPath/Bin64/StarCitizen.exe") - .exists() && - await File("$installPath/Data.p4k").exists()) { - dPrint("find installPath == $installPath"); - scInstallPaths.add(installPath); + checkAndAddPath(String path, bool checkExists) async { + if (path.isNotEmpty && !scInstallPaths.contains(path)) { + if (!checkExists) { + dPrint("find installPath == $path"); + scInstallPaths.add(path); + } else if (await File("$path/Bin64/StarCitizen.exe").exists() && + await File("$path/Data.p4k").exists()) { + dPrint("find installPath == $path"); + scInstallPaths.add(path); + } + } + } + + final confBox = await Hive.openBox("app_conf"); + final path = confBox.get("custom_game_path"); + if (path != null && path != "") { + for (var v in withVersion) { + await checkAndAddPath("$path\\$v", checkExists); + } + } + + try { + for (var v in withVersion) { + for (var i = listData.length - 1; i > 0; i--) { + final m = listData[i]; + final info = m["[browser][info] "]; + if (info is String) { + String installPath = ""; + if (info.contains("Installing Star Citizen $v")) { + installPath = "${info.split(" at ")[1]}\\$v"; } + if (info.contains("Launching Star Citizen $v from")) { + installPath = info + .replaceAll("Launching Star Citizen $v from (", "") + .replaceAll(")", ""); + } + await checkAndAddPath(installPath, checkExists); } } } + } catch (e) { + dPrint(e); + if (scInstallPaths.isEmpty) rethrow; + } + + if (scInstallPaths.isNotEmpty) { + // 动态检测更多位置 + for (var fileName in List.from(scInstallPaths)) { + for (var v in withVersion) { + await checkAndAddPath( + fileName.toString().replaceAll("\\$v", ""), true); + } + } } return scInstallPaths; diff --git a/lib/common/helper/system_helper.dart b/lib/common/helper/system_helper.dart index d626792..094b18e 100644 --- a/lib/common/helper/system_helper.dart +++ b/lib/common/helper/system_helper.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:hive/hive.dart'; import 'package:starcitizen_doctor/common/utils/base_utils.dart'; class SystemHelper { @@ -79,6 +80,14 @@ class SystemHelper { /// 获取 RSI 启动器 目录 static Future getRSILauncherPath() async { + final confBox = await Hive.openBox("app_conf"); + final path = confBox.get("custom_launcher_path"); + if (path != null && path != "") { + if (await File(path).exists()) { + return path; + } + } + Map envVars = Platform.environment; final programDataPath = envVars["programdata"]; final rsiFilePath = diff --git a/lib/ui/settings/settings_ui.dart b/lib/ui/settings/settings_ui.dart index 6d5f1d1..01d5383 100644 --- a/lib/ui/settings/settings_ui.dart +++ b/lib/ui/settings/settings_ui.dart @@ -23,15 +23,34 @@ class SettingUI extends BaseUI { subTitle: "已设置的核心数量:${model.inputGameLaunchECore} ( 设置需要忽略的处理器的能效心数量,盒子将在使用启动游戏功能时为您修改游戏所运行的CPU参数,当为 0 时不启用此功能 )", onTap: model.setGameLaunchECore), - ] else - const Text("暂无设置项"), + const SizedBox(height: 12), + ], + makeSettingsItem( + const Icon(FluentIcons.folder_open), "设置启动器文件(RSI Launcher.exe)", + subTitle: model.customLauncherPath != null + ? "${model.customLauncherPath}" + : "手动设置启动器位置,建议仅在无法自动扫描安装位置时使用", + onTap: model.setLauncherPath, + onDel: () { + model.delName("custom_launcher_path"); + }), + const SizedBox(height: 12), + makeSettingsItem( + const Icon(FluentIcons.game), "设置游戏文件 (StarCitizen.exe)", + subTitle: model.customGamePath != null + ? "${model.customGamePath}" + : "手动设置游戏安装位置,建议仅在无法自动扫描安装位置时使用", + onTap: model.setGamePath, + onDel: () { + model.delName("custom_game_path"); + }), ], ), ); } Widget makeSettingsItem(Widget icon, String title, - {String? subTitle, VoidCallback? onTap}) { + {String? subTitle, VoidCallback? onTap, VoidCallback? onDel}) { return Button( onPressed: onTap, child: Padding( @@ -57,10 +76,19 @@ class SettingUI extends BaseUI { style: TextStyle( fontSize: 12, color: Colors.white.withOpacity(.6)), ) - ], + ] ], ), ), + if (onDel != null) ...[ + Button( + onPressed: onDel, + child: const Padding( + padding: EdgeInsets.all(6), + child: Icon(FluentIcons.delete), + )), + const SizedBox(width: 12), + ], const Icon(FluentIcons.chevron_right), ], ), diff --git a/lib/ui/settings/settings_ui_model.dart b/lib/ui/settings/settings_ui_model.dart index 12f5260..912418a 100644 --- a/lib/ui/settings/settings_ui_model.dart +++ b/lib/ui/settings/settings_ui_model.dart @@ -1,3 +1,4 @@ +import 'package:file_picker/file_picker.dart'; import 'package:flutter/services.dart'; import 'package:hive/hive.dart'; import 'package:local_auth/local_auth.dart'; @@ -13,6 +14,9 @@ class SettingUIModel extends BaseUIModel { bool isEnableAutoLoginPwd = false; String inputGameLaunchECore = "0"; + String? customLauncherPath; + String? customGamePath; + @override loadData() async { final LocalAuthentication localAuth = LocalAuthentication(); @@ -22,6 +26,7 @@ class SettingUIModel extends BaseUIModel { _updateAutoLoginAccount(); _updateGameLaunchECore(); } + _loadCustomPath(); } Future onResetAutoLogin() async { @@ -65,4 +70,58 @@ class SettingUIModel extends BaseUIModel { userBox.get("gameLaunch_eCore_count", defaultValue: "0"); notifyListeners(); } + + Future setLauncherPath() async { + final r = await FilePicker.platform.pickFiles( + dialogTitle: "请选择RSI启动器位置(RSI Launcher.exe)", + type: FileType.custom, + allowedExtensions: ["exe"]); + if (r == null || r.files.firstOrNull?.path == null) return; + final fileName = r.files.first.path!; + if (fileName.endsWith("\\RSI Launcher.exe")) { + await _saveCustomPath("custom_launcher_path", fileName); + showToast(context!, "设置成功,在对应页面点击刷新即可扫描出新路径"); + reloadData(); + } else { + showToast(context!, "路径有误!"); + } + } + + Future setGamePath() async { + final r = await FilePicker.platform.pickFiles( + dialogTitle: "请选择游戏安装位置(StarCitizen.exe)", + type: FileType.custom, + allowedExtensions: ["exe"]); + if (r == null || r.files.firstOrNull?.path == null) return; + final fileName = r.files.first.path!; + dPrint(fileName); + final fileNameRegExp = + RegExp(r"^(.*\\StarCitizen\\.*\\)Bin64\\StarCitizen\.exe$"); + if (fileNameRegExp.hasMatch(fileName)) { + RegExp pathRegex = RegExp(r"\\[^\\]+\\Bin64\\StarCitizen\.exe$"); + String extractedPath = fileName.replaceFirst(pathRegex, ''); + await _saveCustomPath("custom_game_path", extractedPath); + showToast(context!, "设置成功,在对应页面点击刷新即可扫描出新路径"); + reloadData(); + } else { + showToast(context!, "路径有误!"); + } + } + + _saveCustomPath(String pathKey, String dir) async { + final confBox = await Hive.openBox("app_conf"); + await confBox.put(pathKey, dir); + } + + _loadCustomPath() async { + final confBox = await Hive.openBox("app_conf"); + customLauncherPath = confBox.get("custom_launcher_path"); + customGamePath = confBox.get("custom_game_path"); + } + + Future delName(String key) async { + final confBox = await Hive.openBox("app_conf"); + await confBox.delete(key); + reloadData(); + } } diff --git a/lib/ui/tools/tools_ui_model.dart b/lib/ui/tools/tools_ui_model.dart index d3ef9bb..8ab1912 100644 --- a/lib/ui/tools/tools_ui_model.dart +++ b/lib/ui/tools/tools_ui_model.dart @@ -191,16 +191,16 @@ class ToolsUIModel extends BaseUIModel { scInstalledPath = scInstallPaths.first; } } catch (e) { + dPrint(e); showToast(context!, "解析 log 文件失败!\n请尝试使用 RSI Launcher log 修复 工具!"); } notifyListeners(); if (rsiLauncherInstalledPath == "") { - showToast(context!, - "未找到 RSI 启动器,请尝试重新安装。 \n\n下载链接:https://robertsspaceindustries.com/download"); + showToast(context!, "未找到 RSI 启动器,请尝试重新安装,或在设置中手动添加。"); } if (scInstalledPath == "") { - showToast(context!, "未找到星际公民游戏安装位置,请至少完成一次游戏启动操作。"); + showToast(context!, "未找到星际公民游戏安装位置,请至少完成一次游戏启动操作 或在设置中手动添加。"); } }