diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java index 3feb91781b4..f69e83bbb10 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackFileSelectionPage.java @@ -29,8 +29,10 @@ import javafx.scene.layout.HBox; import org.jackhuang.hmcl.game.HMCLGameRepository; import org.jackhuang.hmcl.modpack.ModAdviser; +import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.construct.NoneMultipleSelectionModel; +import org.jackhuang.hmcl.ui.construct.SpinnerPane; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; import org.jackhuang.hmcl.util.Pair; @@ -44,6 +46,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; import static org.jackhuang.hmcl.util.Lang.mapOf; @@ -58,7 +61,7 @@ public final class ModpackFileSelectionPage extends BorderPane implements Wizard private final WizardController controller; private final String version; private final ModAdviser adviser; - private final ModpackFileTreeItem rootNode; + private ModpackFileTreeItem rootNode; public ModpackFileSelectionPage(WizardController controller, HMCLGameRepository repository, String version, ModAdviser adviser) { this.controller = controller; @@ -66,12 +69,17 @@ public ModpackFileSelectionPage(WizardController controller, HMCLGameRepository this.adviser = adviser; JFXTreeView treeView = new JFXTreeView<>(); - rootNode = getTreeItem(repository.getRunDirectory(version), "minecraft", 0); - treeView.setRoot(rootNode); treeView.setSelectionModel(new NoneMultipleSelectionModel<>()); onEscPressed(treeView, () -> controller.onPrev(true)); - setMargin(treeView, new Insets(10, 10, 5, 10)); - this.setCenter(treeView); + + SpinnerPane spinnerPane = new SpinnerPane(); + spinnerPane.setContent(treeView); + setMargin(spinnerPane, new Insets(10, 10, 5, 10)); + this.setCenter(spinnerPane); + + spinnerPane.setLoading(true); + loadRoot(repository, treeView, spinnerPane); + spinnerPane.setOnFailedAction((__) -> loadRoot(repository, treeView, spinnerPane)); HBox nextPane = new HBox(); nextPane.setPadding(new Insets(16, 16, 16, 0)); @@ -79,6 +87,7 @@ public ModpackFileSelectionPage(WizardController controller, HMCLGameRepository { JFXButton btnNext = FXUtils.newRaisedButton(i18n("wizard.next")); btnNext.setPrefSize(100, 40); + btnNext.disableProperty().bind(spinnerPane.loadingProperty()); btnNext.setOnAction(e -> onNext()); nextPane.getChildren().setAll(btnNext); @@ -87,6 +96,21 @@ public ModpackFileSelectionPage(WizardController controller, HMCLGameRepository this.setBottom(nextPane); } + private void loadRoot(HMCLGameRepository repository, JFXTreeView treeView, SpinnerPane spinnerPane) { + CompletableFuture + .supplyAsync(() -> getTreeItem(repository.getRunDirectory(version), "minecraft", 0), Schedulers.io()) + .whenCompleteAsync((modpackFileTreeItem, throwable) -> { + if (throwable != null) { + treeView.setRoot(rootNode = modpackFileTreeItem); + spinnerPane.setFailedReason(null); + } else { + LOG.warning("Failed to load modpack file tree. Please click here to retry."); + spinnerPane.setFailedReason(i18n("modpack.files.load_failed")); + } + spinnerPane.setLoading(false); + }, Schedulers.javafx()); + } + private ModpackFileTreeItem getTreeItem(Path file, String basePath, int level) { if (Files.notExists(file)) return null; @@ -176,6 +200,7 @@ public void cleanup(SettingsMap settings) { } private void onNext() { + if (rootNode == null) return; ArrayList list = new ArrayList<>(); getFilesNeeded(rootNode, "minecraft", list); controller.getSettings().put(MODPACK_FILE_SELECTION, list); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index a2b393f421e..56695e25187 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -990,6 +990,7 @@ modpack.files.config=Mod Configuration Files modpack.files.dumps=NEI Debug Output Files modpack.files.hmclversion_cfg=Launcher Configuration File modpack.files.liteconfig=LiteLoader Related Files +modpack.files.load_failed=Failed to load modpack file tree. Please click here to retry. modpack.files.mods=Mods modpack.files.mods.voxelmods=VoxelMods Options modpack.files.options_txt=Minecraft Option File diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 0574758c5a6..51fd97001fd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -797,6 +797,7 @@ modpack.files.config=模組設定檔案 modpack.files.dumps=NEI 除錯輸出檔案 modpack.files.hmclversion_cfg=啟動器設定檔案 modpack.files.liteconfig=LiteLoader 相關檔案 +modpack.files.load_failed=載入整合包檔案樹失敗,點選此處重試 modpack.files.mods=模組 modpack.files.mods.voxelmods=VoxelMods 設定,如小地圖 modpack.files.options_txt=遊戲設定 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 52cac07405c..40cbc0f96a1 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -802,6 +802,7 @@ modpack.files.config=模组配置文件 modpack.files.dumps=NEI 调试输出文件 modpack.files.hmclversion_cfg=启动器配置文件 modpack.files.liteconfig=LiteLoader 相关文件 +modpack.files.load_failed=加载整合包文件树失败,点击此处重试 modpack.files.mods=模组 modpack.files.mods.voxelmods=VoxelMods 配置,如小地图 modpack.files.options_txt=游戏设置