Skip to content

支持清理游戏文件#5814

Open
CiiLu wants to merge 10 commits intoHMCL-dev:mainfrom
CiiLu:cleanroom!
Open

支持清理游戏文件#5814
CiiLu wants to merge 10 commits intoHMCL-dev:mainfrom
CiiLu:cleanroom!

Conversation

@CiiLu
Copy link
Contributor

@CiiLu CiiLu commented Mar 20, 2026

image

@zkitefly
Copy link
Member

zkitefly commented Mar 20, 2026

image

应该优化一下 0 mb 的提示?

@CiiLu CiiLu marked this pull request as draft March 21, 2026 03:11
@CiiLu CiiLu marked this pull request as ready for review March 21, 2026 03:27
@Glavo Glavo requested a review from Copilot March 21, 2026 13:19
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 为启动器新增“清理游戏文件”能力:在版本列表页提供入口,统计可清理文件占用空间并提示用户确认后执行清理,同时补充了文件大小格式化与相关本地化文案。

Changes:

  • 新增游戏文件清理入口与实现(扫描冗余 assets/libraries、日志/缓存、natives 目录等并删除)。
  • 增加文件大小的本地化格式化能力(I18n.formatSize / Translator.formatSize + 对应多语言 key)。
  • UI 支持动态更新 MessageDialog 文本,并新增清理图标与多语言文案。

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties 添加 size 格式化 key 与“清理游戏文件”文案(简中)
HMCL/src/main/resources/assets/lang/I18N_zh.properties 添加 size 格式化 key 与“清理游戏文件”文案(繁中)
HMCL/src/main/resources/assets/lang/I18N.properties 添加 size 格式化 key 与“清理游戏文件”文案(英文)
HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/translator/Translator.java 新增 formatSize(long),使用 i18n key 格式化大小
HMCL/src/main/java/org/jackhuang/hmcl/util/i18n/I18n.java 暴露 I18n.formatSize(long) 静态入口
HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/Versions.java 实现清理逻辑与统计/确认对话框交互
HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/GameListPage.java 在版本列表页工具栏新增“清理游戏文件”按钮入口
HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/MessageDialogPane.java 支持 setText 动态更新对话框文本
HMCL/src/main/java/org/jackhuang/hmcl/ui/SVG.java 新增 CLEAN 图标枚举值

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

JFXButton okButton = new JFXButton(i18n("button.yes"));
okButton.getStyleClass().add("dialog-accept");

dialogBuilder.addAction(buttonPane);
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MessageDialogPane.Builder#addAction(Node) registers an ActionEvent handler on the provided node to close the dialog. Passing a container (buttonPane) means the ActionEvent from okButton will bubble up and close the dialog immediately on click, preventing the intended “show spinner while deleting, then close” flow. Prefer adding the actual button as the action node (and suppress auto-close), or expose/update the dialog action area via an API instead of wrapping with a pane.

Suggested change
dialogBuilder.addAction(buttonPane);
dialogBuilder.addAction(okButton);

Copilot uses AI. Check for mistakes.
.collect(Collectors.toSet());

Set<String> activeLibraries = versions.parallelStream()
.flatMap(version -> version.getLibraries().stream())
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

activeLibraries is derived from version.getLibraries() only, but HMCL stores extra libraries in version.getPatches() (e.g., modpack/loader patches). Those patched libraries live under libraries/ too, so this cleanup can misclassify them as unused and delete required files. Build activeLibraries from the resolved version (e.g., resolvePreservingPatches(...)) or explicitly include libraries from patches when collecting paths.

Suggested change
.flatMap(version -> version.getLibraries().stream())
.flatMap(version -> {
Stream<Library> baseLibraries = version.getLibraries().stream();
Stream<Library> patchedLibraries = version.getPatches().stream()
.flatMap(patch -> patch.getLibraries().stream());
return Stream.concat(baseLibraries, patchedLibraries);
})

Copilot uses AI. Check for mistakes.
Comment on lines +254 to +259
try (var walker = Files.walk(repository.getVersionRoot(v.getId()), 1)) {
unusedFolders.addAll(walker
.filter(it -> {
var name = it.getFileName().toString();
return Files.isDirectory(it) && (name.startsWith("natives-") || name.endsWith("-natives"));
}).toList());
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Files.walk(versionRoot, 1) includes versionRoot itself. If a user’s version id happens to start with natives- or end with -natives, this filter will treat the entire version directory as a “natives” folder and enqueue all its files for deletion. Use Files.list(versionRoot) (children only) or add an explicit !it.equals(versionRoot) guard before applying the name predicate.

Copilot uses AI. Check for mistakes.
} else if (bytes < 1024 * 1024 * 1024) {
return supportedLocale.i18n("download.size.megabyte", (double) bytes / (1024 * 1024));
} else {
return supportedLocale.i18n("download.size.gibabyte", (double) bytes / (1024 * 1024 * 1024));
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The i18n key name download.size.gibabyte appears to be a typo (GiB is “gibibyte”, matching the existing kibibyte/megabyte naming). Since this is newly introduced, consider renaming the key (and all translations/usages) to download.size.gibibyte to avoid confusion and keep key naming consistent.

Suggested change
return supportedLocale.i18n("download.size.gibabyte", (double) bytes / (1024 * 1024 * 1024));
return supportedLocale.i18n("download.size.gibibyte", (double) bytes / (1024 * 1024 * 1024));

Copilot uses AI. Check for mistakes.
download.size.byte=%d B
download.size.kibibyte=%.1f KiB
download.size.megabyte=%.1f MiB
download.size.gibabyte=%.1f GiB
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The i18n key name download.size.gibabyte appears to be a typo (GiB is “gibibyte”, matching the existing kibibyte/megabyte naming). Since this is newly introduced, consider renaming the key to download.size.gibibyte (and update all locales/usages) for consistency.

Suggested change
download.size.gibabyte=%.1f GiB
download.size.gibibyte=%.1f GiB

Copilot uses AI. Check for mistakes.
download.size.byte=%d B
download.size.kibibyte=%.1f KiB
download.size.megabyte=%.1f MiB
download.size.gibabyte=%.1f GiB
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The i18n key name download.size.gibabyte appears to be a typo (GiB is “gibibyte”, matching the kibibyte/megabyte naming). Since this is newly introduced, consider renaming the key to download.size.gibibyte (and update all locales/usages) for consistency.

Suggested change
download.size.gibabyte=%.1f GiB
download.size.gibibyte=%.1f GiB

Copilot uses AI. Check for mistakes.
download.size.byte=%d B
download.size.kibibyte=%.1f KiB
download.size.megabyte=%.1f MiB
download.size.gibabyte=%.1f GiB
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The i18n key name download.size.gibabyte appears to be a typo (GiB is “gibibyte”, matching the kibibyte/megabyte naming). Since this is newly introduced, consider renaming the key to download.size.gibibyte (and update all locales/usages) for consistency.

Suggested change
download.size.gibabyte=%.1f GiB
download.size.gibibyte=%.1f GiB

Copilot uses AI. Check for mistakes.

game=遊戲
game.clean=清理遊戲文件
game.clean.loading=统计中...
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the Traditional Chinese locale file, but the new string uses the Simplified character “统计”. Consider changing it to Traditional (“統計”) to keep the locale consistent.

Suggested change
game.clean.loading=统计中...
game.clean.loading=統計中...

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants