From 66ead87d47cacd1f1162c5adf5b88d20c22c81fe Mon Sep 17 00:00:00 2001 From: xkeyC <3334969096@qq.com> Date: Tue, 23 Dec 2025 17:54:15 +0800 Subject: [PATCH] feat: Introduce shader cache cleaning options ('Keep Latest', 'Clean All') via a new dialog and refactor cleaning logic with new localization. close: https://github.com/StarCitizenToolBox/app/issues/173 --- lib/generated/intl/messages_en.dart | 7 ++ lib/generated/intl/messages_ja.dart | 7 ++ lib/generated/intl/messages_ru.dart | 9 ++ lib/generated/intl/messages_zh_CN.dart | 7 ++ lib/generated/intl/messages_zh_TW.dart | 7 ++ lib/generated/l10n.dart | 30 +++++++ lib/l10n/intl_en.arb | 8 +- lib/l10n/intl_ja.arb | 8 +- lib/l10n/intl_ru.arb | 8 +- lib/l10n/intl_zh_CN.arb | 5 +- lib/l10n/intl_zh_TW.arb | 5 +- lib/ui/tools/tools_ui_model.dart | 120 +++++++++++++++++++++++-- 12 files changed, 208 insertions(+), 13 deletions(-) diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 1fbb3e6..e7c2223 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -2406,6 +2406,13 @@ class MessageLookup extends MessageLookupByLibrary { "tools_rsi_launcher_enhance_working_msg2": MessageLookupByLibrary.simpleMessage( "Installing patch, this will take some time depending on your computer\'s performance...", ), + "tools_shader_clean_all": MessageLookupByLibrary.simpleMessage("Clean All"), + "tools_shader_clean_dialog_title": MessageLookupByLibrary.simpleMessage( + "Clear Shader Cache", + ), + "tools_shader_clean_keep_latest": MessageLookupByLibrary.simpleMessage( + "Keep Latest", + ), "tools_unp4k_action_cancel_multi_select": MessageLookupByLibrary.simpleMessage("Cancel Multi-Select"), "tools_unp4k_action_deselect_all": MessageLookupByLibrary.simpleMessage( diff --git a/lib/generated/intl/messages_ja.dart b/lib/generated/intl/messages_ja.dart index 57970fb..5b57ab6 100644 --- a/lib/generated/intl/messages_ja.dart +++ b/lib/generated/intl/messages_ja.dart @@ -2036,6 +2036,13 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage( "パッチをインストール中、これはコンピュータのパフォーマンスによって時間がかかります...", ), + "tools_shader_clean_all": MessageLookupByLibrary.simpleMessage("すべてクリア"), + "tools_shader_clean_dialog_title": MessageLookupByLibrary.simpleMessage( + "シェーダーキャッシュをクリア", + ), + "tools_shader_clean_keep_latest": MessageLookupByLibrary.simpleMessage( + "最新を保持", + ), "tools_unp4k_missing_runtime": MessageLookupByLibrary.simpleMessage( "ランタイムがありません", ), diff --git a/lib/generated/intl/messages_ru.dart b/lib/generated/intl/messages_ru.dart index 36da3a0..4a740fe 100644 --- a/lib/generated/intl/messages_ru.dart +++ b/lib/generated/intl/messages_ru.dart @@ -2293,6 +2293,15 @@ class MessageLookup extends MessageLookupByLibrary { "tools_rsi_launcher_enhance_working_msg2": MessageLookupByLibrary.simpleMessage( "Установка патча, это займет некоторое время в зависимости от производительности вашего компьютера...", ), + "tools_shader_clean_all": MessageLookupByLibrary.simpleMessage( + "Очистить всё", + ), + "tools_shader_clean_dialog_title": MessageLookupByLibrary.simpleMessage( + "Очистить кеш шейдеров", + ), + "tools_shader_clean_keep_latest": MessageLookupByLibrary.simpleMessage( + "Сохранить последнее", + ), "tools_unp4k_missing_runtime": MessageLookupByLibrary.simpleMessage( "Отсутствует среда выполнения", ), diff --git a/lib/generated/intl/messages_zh_CN.dart b/lib/generated/intl/messages_zh_CN.dart index 43a4ca5..8dad938 100644 --- a/lib/generated/intl/messages_zh_CN.dart +++ b/lib/generated/intl/messages_zh_CN.dart @@ -2044,6 +2044,13 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("生成补丁 ..."), "tools_rsi_launcher_enhance_working_msg2": MessageLookupByLibrary.simpleMessage("安装补丁,这需要一点时间,取决于您的计算机性能 ..."), + "tools_shader_clean_all": MessageLookupByLibrary.simpleMessage("全部清理"), + "tools_shader_clean_dialog_title": MessageLookupByLibrary.simpleMessage( + "清理着色器缓存", + ), + "tools_shader_clean_keep_latest": MessageLookupByLibrary.simpleMessage( + "保留最新", + ), "tools_unp4k_action_cancel_multi_select": MessageLookupByLibrary.simpleMessage("取消多选"), "tools_unp4k_action_deselect_all": MessageLookupByLibrary.simpleMessage( diff --git a/lib/generated/intl/messages_zh_TW.dart b/lib/generated/intl/messages_zh_TW.dart index 85f48cf..925f009 100644 --- a/lib/generated/intl/messages_zh_TW.dart +++ b/lib/generated/intl/messages_zh_TW.dart @@ -1907,6 +1907,13 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("生成補丁 ..."), "tools_rsi_launcher_enhance_working_msg2": MessageLookupByLibrary.simpleMessage("安裝補丁,這需要一點時間,取決於您的電腦性能 ..."), + "tools_shader_clean_all": MessageLookupByLibrary.simpleMessage("全部清理"), + "tools_shader_clean_dialog_title": MessageLookupByLibrary.simpleMessage( + "清理著色器緩存", + ), + "tools_shader_clean_keep_latest": MessageLookupByLibrary.simpleMessage( + "保留最新", + ), "tools_unp4k_missing_runtime": MessageLookupByLibrary.simpleMessage( "缺少運行庫", ), diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 7f3251d..9be0454 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -9546,6 +9546,36 @@ class S { args: [year], ); } + + /// `Clear Shader Cache` + String get tools_shader_clean_dialog_title { + return Intl.message( + 'Clear Shader Cache', + name: 'tools_shader_clean_dialog_title', + desc: '', + args: [], + ); + } + + /// `Keep Latest` + String get tools_shader_clean_keep_latest { + return Intl.message( + 'Keep Latest', + name: 'tools_shader_clean_keep_latest', + desc: '', + args: [], + ); + } + + /// `Clean All` + String get tools_shader_clean_all { + return Intl.message( + 'Clean All', + name: 'tools_shader_clean_all', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 6d0e275..beda9ac 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1912,5 +1912,11 @@ "yearly_report_card_title": "{year} Yearly Report (Limited Time)", "@yearly_report_card_title": {}, "yearly_report_card_desc": "View your Star Citizen gameplay statistics for {year}. Data is from local logs, please check on your main computer.", - "@yearly_report_card_desc": {} + "@yearly_report_card_desc": {}, + "tools_shader_clean_dialog_title": "Clear Shader Cache", + "@tools_shader_clean_dialog_title": {}, + "tools_shader_clean_keep_latest": "Keep Latest", + "@tools_shader_clean_keep_latest": {}, + "tools_shader_clean_all": "Clean All", + "@tools_shader_clean_all": {} } diff --git a/lib/l10n/intl_ja.arb b/lib/l10n/intl_ja.arb index 50fc7b8..5b5a570 100644 --- a/lib/l10n/intl_ja.arb +++ b/lib/l10n/intl_ja.arb @@ -1734,5 +1734,11 @@ "yearly_report_card_title": "{year} 年間レポート(期間限定)", "@yearly_report_card_title": {}, "yearly_report_card_desc": "{year}年のStar Citizenプレイ統計を表示します。データはローカルログからのものです。メインのコンピュータで確認してください。", - "@yearly_report_card_desc": {} + "@yearly_report_card_desc": {}, + "tools_shader_clean_dialog_title": "シェーダーキャッシュをクリア", + "@tools_shader_clean_dialog_title": {}, + "tools_shader_clean_keep_latest": "最新を保持", + "@tools_shader_clean_keep_latest": {}, + "tools_shader_clean_all": "すべてクリア", + "@tools_shader_clean_all": {} } diff --git a/lib/l10n/intl_ru.arb b/lib/l10n/intl_ru.arb index 008494c..9dad5b4 100644 --- a/lib/l10n/intl_ru.arb +++ b/lib/l10n/intl_ru.arb @@ -1734,5 +1734,11 @@ "yearly_report_card_title": "Ежегодный отчет {year} (Ограниченное время)", "@yearly_report_card_title": {}, "yearly_report_card_desc": "Посмотрите статистику вашей игры в Star Citizen за {year} год. Данные из локальных логов, пожалуйста, проверяйте на основном компьютере.", - "@yearly_report_card_desc": {} + "@yearly_report_card_desc": {}, + "tools_shader_clean_dialog_title": "Очистить кеш шейдеров", + "@tools_shader_clean_dialog_title": {}, + "tools_shader_clean_keep_latest": "Сохранить последнее", + "@tools_shader_clean_keep_latest": {}, + "tools_shader_clean_all": "Очистить всё", + "@tools_shader_clean_all": {} } diff --git a/lib/l10n/intl_zh_CN.arb b/lib/l10n/intl_zh_CN.arb index 9d89a1a..4abc2b0 100644 --- a/lib/l10n/intl_zh_CN.arb +++ b/lib/l10n/intl_zh_CN.arb @@ -1328,5 +1328,8 @@ "yearly_report_powered_by": "由 SC 汉化盒子为您呈现", "yearly_report_disclaimer": "数据使用您的本地日志生成,不会发送到任何第三方。因跨版本 Log 改动较大,数据可能不完整,仅供娱乐。", "yearly_report_card_title": "{year} 年度报告(限时)", - "yearly_report_card_desc": "查看您在{year}年的星际公民游玩统计,数据来自本地 log ,请确保在常用电脑上查看。" + "yearly_report_card_desc": "查看您在{year}年的星际公民游玩统计,数据来自本地 log ,请确保在常用电脑上查看。", + "tools_shader_clean_dialog_title": "清理着色器缓存", + "tools_shader_clean_keep_latest": "保留最新", + "tools_shader_clean_all": "全部清理" } \ No newline at end of file diff --git a/lib/l10n/intl_zh_TW.arb b/lib/l10n/intl_zh_TW.arb index c101c4e..1d022ac 100644 --- a/lib/l10n/intl_zh_TW.arb +++ b/lib/l10n/intl_zh_TW.arb @@ -1670,5 +1670,8 @@ "yearly_report_powered_by": "由 SC工具箱為您呈現", "yearly_report_disclaimer": "數據使用您的本地日誌生成,不會發送到任何第三方。因跨版本 Log 改動較大,數據可能不完整,僅供娛樂。", "yearly_report_card_title": "{year} 年度報告(限時)", - "yearly_report_card_desc": "查看您在{year}年的星際公民遊玩統計,數據來自本地 log ,請確保在常用電腦上查看。" + "yearly_report_card_desc": "查看您在{year}年的星際公民遊玩統計,數據來自本地 log ,請確保在常用電腦上查看。", + "tools_shader_clean_dialog_title": "清理著色器緩存", + "tools_shader_clean_keep_latest": "保留最新", + "tools_shader_clean_all": "全部清理" } diff --git a/lib/ui/tools/tools_ui_model.dart b/lib/ui/tools/tools_ui_model.dart index 6063e27..d373909 100644 --- a/lib/ui/tools/tools_ui_model.dart +++ b/lib/ui/tools/tools_ui_model.dart @@ -544,27 +544,131 @@ class ToolsUIModel extends _$ToolsUIModel { state = state.copyWith(working: false); } + /// 清理着色器缓存(全部清理模式),保留最新两个文件夹的 GraphicsSettings static Future cleanShaderCache() async { + await _cleanShaderCacheWithMode(keepLatest: false); + } + + /// 清理着色器缓存(保留最新模式) + /// 保留最新文件夹的所有内容,保留第二新文件夹的 GraphicsSettings,清理其他 + static Future cleanShaderCacheKeepLatest() async { + await _cleanShaderCacheWithMode(keepLatest: true); + } + + /// 内部清理方法 + /// [keepLatest] true: 保留最新模式,false: 全部清理模式 + static Future _cleanShaderCacheWithMode({required bool keepLatest}) async { final gameShaderCachePath = await SCLoggerHelper.getShaderCachePath(); - final l = await Directory(gameShaderCachePath!).list(recursive: false).toList(); - for (var value in l) { - if (value is Directory) { - final dirName = value.path.split(Platform.pathSeparator).last; + if (gameShaderCachePath == null) return; + + final dir = Directory(gameShaderCachePath); + if (!await dir.exists()) return; + + // 获取所有 starcitizen_* 目录并按创建时间排序 + final scDirs = []; + final otherDirs = []; + + await for (var entity in dir.list(recursive: false)) { + if (entity is Directory) { + final dirName = entity.path.split(Platform.pathSeparator).last; if (dirName == "Crashes") continue; - // 对于 starcitizen_* 目录,手动遍历删除,保留 GraphicsSettings 文件夹 if (dirName.startsWith("starcitizen_")) { - await _cleanShaderCacheDirectory(value); + scDirs.add(entity); } else { - await value.delete(recursive: true); + otherDirs.add(entity); } } } + + // 按目录名(版本号)降序排序,最新的在前面 + scDirs.sort((a, b) { + final aName = a.path.split(Platform.pathSeparator).last; + final bName = b.path.split(Platform.pathSeparator).last; + return bName.compareTo(aName); + }); + + // 清理非 starcitizen_* 目录 + for (var d in otherDirs) { + try { + await d.delete(recursive: true); + } catch (e) { + dPrint("_cleanShaderCacheWithMode delete other dir error: $e"); + } + } + + // 根据模式清理 starcitizen_* 目录 + for (var i = 0; i < scDirs.length; i++) { + final scDir = scDirs[i]; + + if (keepLatest) { + // 保留最新模式: + // 第一个(最新):完全保留 + // 第二个:仅保留 GraphicsSettings + // 其他:仅保留 GraphicsSettings + if (i == 0) { + // 最新的文件夹完全保留,不做任何操作 + continue; + } else { + // 其他文件夹:清理内容,保留 GraphicsSettings + await _cleanShaderCacheDirectory(scDir); + } + } else { + // 全部清理模式: + // 前两个:仅保留 GraphicsSettings + // 其他:仅保留 GraphicsSettings + await _cleanShaderCacheDirectory(scDir); + } + } } Future _cleanShaderCache(BuildContext context) async { + // 显示对话框让用户选择清理模式 + final result = await showDialog( + context: context, + builder: (dialogContext) => ContentDialog( + title: Text(S.current.tools_shader_clean_dialog_title), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 12), + SizedBox( + width: double.infinity, + child: FilledButton( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Text(S.current.tools_shader_clean_keep_latest), + ), + onPressed: () => Navigator.pop(dialogContext, "keep_latest"), + ), + ), + const SizedBox(height: 12), + SizedBox( + width: double.infinity, + child: Button( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Text(S.current.tools_shader_clean_all), + ), + onPressed: () => Navigator.pop(dialogContext, "clean_all"), + ), + ), + ], + ), + actions: [Button(child: Text(S.current.app_common_tip_cancel), onPressed: () => Navigator.pop(dialogContext))], + ), + ); + + if (result == null || !context.mounted) return; + state = state.copyWith(working: true); - await cleanShaderCache(); + + if (result == "keep_latest") { + await cleanShaderCacheKeepLatest(); + } else { + await cleanShaderCache(); + } + if (!context.mounted) return; loadToolsCard(context, skipPathScan: true); state = state.copyWith(working: false);