-
Notifications
You must be signed in to change notification settings - Fork 847
支持清理游戏文件 #5814
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
支持清理游戏文件 #5814
Changes from all commits
a8b40c4
d60bb2e
a29d193
dbdd6ff
bca62ef
007a103
7ed8f52
06dd28e
9cc49fb
4bb5305
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -18,7 +18,9 @@ | |||||||||||||||
| package org.jackhuang.hmcl.ui.versions; | ||||||||||||||||
|
|
||||||||||||||||
| import com.jfoenix.controls.JFXButton; | ||||||||||||||||
| import com.jfoenix.controls.JFXSpinner; | ||||||||||||||||
| import javafx.application.Platform; | ||||||||||||||||
| import javafx.scene.layout.StackPane; | ||||||||||||||||
| import javafx.stage.FileChooser; | ||||||||||||||||
| import org.jackhuang.hmcl.auth.Account; | ||||||||||||||||
| import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount; | ||||||||||||||||
|
|
@@ -42,17 +44,22 @@ | |||||||||||||||
| import org.jackhuang.hmcl.ui.export.ExportWizardProvider; | ||||||||||||||||
| import org.jackhuang.hmcl.util.StringUtils; | ||||||||||||||||
| import org.jackhuang.hmcl.util.TaskCancellationAction; | ||||||||||||||||
| import org.jackhuang.hmcl.util.i18n.I18n; | ||||||||||||||||
| import org.jackhuang.hmcl.util.io.FileUtils; | ||||||||||||||||
| import org.jackhuang.hmcl.util.platform.OperatingSystem; | ||||||||||||||||
|
|
||||||||||||||||
| import java.io.IOException; | ||||||||||||||||
| import java.net.URI; | ||||||||||||||||
| import java.nio.file.Files; | ||||||||||||||||
| import java.nio.file.Path; | ||||||||||||||||
| import java.util.ArrayList; | ||||||||||||||||
| import java.util.List; | ||||||||||||||||
| import java.util.Set; | ||||||||||||||||
| import java.util.concurrent.CancellationException; | ||||||||||||||||
| import java.util.concurrent.CompletableFuture; | ||||||||||||||||
| import java.util.function.Consumer; | ||||||||||||||||
| import java.util.stream.Collectors; | ||||||||||||||||
| import java.util.stream.Stream; | ||||||||||||||||
|
|
||||||||||||||||
| import static org.jackhuang.hmcl.util.i18n.I18n.i18n; | ||||||||||||||||
| import static org.jackhuang.hmcl.util.logging.Logger.LOG; | ||||||||||||||||
|
|
@@ -194,6 +201,125 @@ public static void updateGameAssets(Profile profile, String version) { | |||||||||||||||
| executor.start(); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| public static void cleanGameFiles(Profile profile) { | ||||||||||||||||
| var dialogBuilder = new MessageDialogPane.Builder(i18n("game.clean.content", i18n("game.clean.loading")), i18n("message.question"), MessageDialogPane.MessageType.QUESTION); | ||||||||||||||||
| var spinner = new JFXSpinner(); | ||||||||||||||||
| spinner.getStyleClass().add("small-spinner"); | ||||||||||||||||
|
|
||||||||||||||||
| StackPane buttonPane = new StackPane(); | ||||||||||||||||
|
|
||||||||||||||||
| JFXButton okButton = new JFXButton(i18n("button.yes")); | ||||||||||||||||
| okButton.getStyleClass().add("dialog-accept"); | ||||||||||||||||
|
|
||||||||||||||||
| dialogBuilder.addAction(buttonPane); | ||||||||||||||||
| dialogBuilder.addCancel(null); | ||||||||||||||||
|
|
||||||||||||||||
| var dialog = dialogBuilder.build(); | ||||||||||||||||
|
|
||||||||||||||||
| Task.supplyAsync(() -> { | ||||||||||||||||
| var repository = profile.getRepository(); | ||||||||||||||||
| var versions = repository.getVersions(); | ||||||||||||||||
|
|
||||||||||||||||
| Set<String> activeAssets = versions.parallelStream() | ||||||||||||||||
| .flatMap(version -> { | ||||||||||||||||
| try { | ||||||||||||||||
| var index = repository.getAssetIndex(version.getId(), version.getAssetIndex().getId()); | ||||||||||||||||
| return index.getObjects().values().stream().map(AssetObject::getLocation); | ||||||||||||||||
| } catch (IOException ignored) { | ||||||||||||||||
| return Stream.empty(); | ||||||||||||||||
| } | ||||||||||||||||
| }) | ||||||||||||||||
| .collect(Collectors.toSet()); | ||||||||||||||||
|
|
||||||||||||||||
| Set<String> activeLibraries = versions.parallelStream() | ||||||||||||||||
| .flatMap(version -> version.getLibraries().stream()) | ||||||||||||||||
|
||||||||||||||||
| .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
AI
Mar 21, 2026
There was a problem hiding this comment.
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.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -73,4 +73,16 @@ public String formatSpeed(long bytes) { | |||||
| return supportedLocale.i18n("download.speed.megabyte_per_second", (double) bytes / (1024 * 1024)); | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| public String formatSize(long bytes) { | ||||||
| if (bytes < 1024) { | ||||||
| return supportedLocale.i18n("download.size.byte", bytes); | ||||||
| } else if (bytes < 1024 * 1024) { | ||||||
| return supportedLocale.i18n("download.size.kibibyte", (double) bytes / 1024); | ||||||
| } 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)); | ||||||
|
||||||
| return supportedLocale.i18n("download.size.gibabyte", (double) bytes / (1024 * 1024 * 1024)); | |
| return supportedLocale.i18n("download.size.gibibyte", (double) bytes / (1024 * 1024 * 1024)); |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -379,6 +379,10 @@ download.javafx.notes=We are currently downloading dependencies for HMCL from th | |||||
| Note: If your download speed is too slow, you can try switching to another mirror. | ||||||
| download.javafx.component=Downloading module "%s" | ||||||
| download.javafx.prepare=Preparing to download | ||||||
| download.size.byte=%d B | ||||||
| download.size.kibibyte=%.1f KiB | ||||||
| download.size.megabyte=%.1f MiB | ||||||
| download.size.gibabyte=%.1f GiB | ||||||
|
||||||
| download.size.gibabyte=%.1f GiB | |
| download.size.gibibyte=%.1f GiB |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -372,6 +372,10 @@ download.javafx=正在下載必要的執行時元件 | |||||
| download.javafx.notes=正在透過網路下載 HMCL 必要的執行時元件。\n點擊「切換下載源」按鈕查看詳情以及選取下載源。點擊「取消」按鈕停止並退出。\n注意:如果下載速度過慢,請嘗試切換下載源。 | ||||||
| download.javafx.component=正在下載元件「%s」 | ||||||
| download.javafx.prepare=準備開始下載 | ||||||
| download.size.byte=%d B | ||||||
| download.size.kibibyte=%.1f KiB | ||||||
| download.size.megabyte=%.1f MiB | ||||||
| download.size.gibabyte=%.1f GiB | ||||||
|
||||||
| download.size.gibabyte=%.1f GiB | |
| download.size.gibibyte=%.1f GiB |
Copilot
AI
Mar 21, 2026
There was a problem hiding this comment.
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.
| game.clean.loading=统计中... | |
| game.clean.loading=統計中... |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -374,6 +374,10 @@ download.javafx=正在下载必要的运行时组件…… | |||||
| download.javafx.notes=正在通过网络下载 HMCL 必要的运行时组件。\n点击“切换下载源”按钮查看详情以及选择下载源。点击“取消”按钮停止并退出。\n注意:若下载速度过慢,请尝试切换下载源。 | ||||||
| download.javafx.component=正在下载模块“%s” | ||||||
| download.javafx.prepare=准备开始下载 | ||||||
| download.size.byte=%d B | ||||||
| download.size.kibibyte=%.1f KiB | ||||||
| download.size.megabyte=%.1f MiB | ||||||
| download.size.gibabyte=%.1f GiB | ||||||
|
||||||
| download.size.gibabyte=%.1f GiB | |
| download.size.gibibyte=%.1f GiB |
There was a problem hiding this comment.
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 anActionEventhandler on the provided node to close the dialog. Passing a container (buttonPane) means theActionEventfromokButtonwill 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.