From c76bcb5d158b7c7913a30ff64a564a1f84fc5b3a Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Wed, 14 Feb 2018 13:29:08 +0800 Subject: [PATCH] show retry link when failed to fetch version list --- .../jackhuang/hmcl/game/ModpackHelper.java | 5 +- .../hmcl/ui/download/VersionsPage.java | 40 +++++++--- HMCL/src/main/resources/assets/css/root.css | 45 +---------- .../assets/fxml/download/dltype.fxml | 2 +- .../assets/fxml/download/versions.fxml | 6 +- .../resources/assets/lang/I18N.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + .../hmcl/download/DefaultGameBuilder.java | 11 +-- .../hmcl/task/FinalizedCallback.java | 24 ++++++ .../jackhuang/hmcl/task/FinalizedTask.java | 78 +++++++++++++++++++ .../java/org/jackhuang/hmcl/task/Task.java | 8 +- 11 files changed, 152 insertions(+), 69 deletions(-) create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java create mode 100644 HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java index 5e7390eff..a79a1ebd1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/ModpackHelper.java @@ -23,6 +23,7 @@ import org.jackhuang.hmcl.mod.*; import org.jackhuang.hmcl.setting.EnumGameDirectory; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.VersionSetting; +import org.jackhuang.hmcl.task.FinalizedCallback; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.util.Constants; import org.jackhuang.hmcl.util.FileUtils; @@ -84,13 +85,13 @@ public final class ModpackHelper { public static Task getInstallTask(Profile profile, File zipFile, String name, Modpack modpack) { profile.getRepository().markVersionAsModpack(name); - Task finalizeTask = Task.of(() -> { + FinalizedCallback finalizeTask = (variables, isDependentsSucceeded) -> { profile.getRepository().refreshVersions(); VersionSetting vs = profile.specializeVersionSetting(name); profile.getRepository().undoMark(name); if (vs != null) vs.setGameDirType(EnumGameDirectory.VERSION_FOLDER); - }); + }; if (modpack.getManifest() instanceof CurseManifest) return new CurseInstallTask(profile.getDependency(), zipFile, ((CurseManifest) modpack.getManifest()), name) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java index 9e035b003..5d40221b5 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/VersionsPage.java @@ -19,12 +19,15 @@ package org.jackhuang.hmcl.ui.download; import com.jfoenix.controls.JFXListView; import com.jfoenix.controls.JFXSpinner; +import javafx.application.Platform; import javafx.fxml.FXML; import javafx.scene.layout.StackPane; import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.VersionList; +import org.jackhuang.hmcl.task.Scheduler; import org.jackhuang.hmcl.task.Schedulers; +import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.task.TaskExecutor; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; @@ -33,7 +36,9 @@ import org.jackhuang.hmcl.ui.wizard.Refreshable; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public final class VersionsPage extends StackPane implements WizardPage, Refreshable { private final WizardController controller; @@ -45,7 +50,10 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh @FXML private JFXListView list; - @FXML private JFXSpinner spinner; + @FXML + private JFXSpinner spinner; + @FXML + private StackPane failedPane; private final TransitionHandler transitionHandler = new TransitionHandler(this); private final VersionList versionList; @@ -62,7 +70,6 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh this.versionList = downloadProvider.getVersionListById(libraryId); FXUtils.loadFXML(this, "/assets/fxml/download/versions.fxml"); - getChildren().setAll(spinner); list.getSelectionModel().selectedItemProperty().addListener((a, b, newValue) -> { controller.getSettings().put(libraryId, newValue.getRemoteVersion().getSelfVersion()); callback.run(); @@ -72,15 +79,23 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh @Override public void refresh() { - executor = versionList.refreshAsync(downloadProvider).subscribe(Schedulers.javafx(), () -> { - versionList.getVersions(gameVersion).stream() - .sorted(RemoteVersion.RemoteVersionComparator.INSTANCE) - .forEach(version -> { - list.getItems().add(new VersionsPageItem(version)); - }); + getChildren().setAll(spinner); + executor = versionList.refreshAsync(downloadProvider).finalized((variables, isDependentsSucceeded) -> { + if (isDependentsSucceeded) { + List items = versionList.getVersions(gameVersion).stream() + .sorted(RemoteVersion.RemoteVersionComparator.INSTANCE) + .map(VersionsPageItem::new).collect(Collectors.toList()); - transitionHandler.setContent(list, ContainerAnimations.FADE.getAnimationProducer()); - }); + Platform.runLater(() -> { + list.getItems().setAll(items); + transitionHandler.setContent(list, ContainerAnimations.FADE.getAnimationProducer()); + }); + } else { + Platform.runLater(() -> { + transitionHandler.setContent(failedPane, ContainerAnimations.FADE.getAnimationProducer()); + }); + } + }).executor().start(); } @Override @@ -94,4 +109,9 @@ public final class VersionsPage extends StackPane implements WizardPage, Refresh if (executor != null) executor.cancel(); } + + @FXML + private void onRefresh() { + refresh(); + } } diff --git a/HMCL/src/main/resources/assets/css/root.css b/HMCL/src/main/resources/assets/css/root.css index a440cfcfb..cc911de66 100644 --- a/HMCL/src/main/resources/assets/css/root.css +++ b/HMCL/src/main/resources/assets/css/root.css @@ -899,6 +899,7 @@ .jfx-spinner > .arc { -fx-stroke-width: 3.0; -fx-fill: transparent; + -fx-stroke: -fx-base-color; } .first-spinner { @@ -957,50 +958,6 @@ -fx-stroke-width: 5.0; } -.blue-spinner .arc { - -fx-stroke: #4285f4; -} - -.red-spinner .arc { - -fx-stroke: #db4437; -} - -.green-spinner .arc { - -fx-stroke: #f4b400; -} - -.yellow-spinner .arc { - -fx-stroke: -fx-base-check-color; -} - -.materialDesign-purple .arc { - -fx-stroke: #ab47bc; -} - -.materialDesign-blue .arc { - -fx-stroke: #2962ff; -} - -.materialDesign-cyan .arc { - -fx-stroke: #00b8d4; -} - -.materialDesign-green .arc { - -fx-stroke: #00c853; -} - -.materialDesign-yellow .arc { - -fx-stroke: #ffd600; -} - -.materialDesign-orange .arc { - -fx-stroke: #ff6d00; -} - -.materialDesign-red .arc { - -fx-stroke: #d50000; -} - /******************************************************************************* * * * JFX Combo Box * diff --git a/HMCL/src/main/resources/assets/fxml/download/dltype.fxml b/HMCL/src/main/resources/assets/fxml/download/dltype.fxml index 27e5d178c..5e077f6ac 100644 --- a/HMCL/src/main/resources/assets/fxml/download/dltype.fxml +++ b/HMCL/src/main/resources/assets/fxml/download/dltype.fxml @@ -29,7 +29,7 @@ - + diff --git a/HMCL/src/main/resources/assets/fxml/download/versions.fxml b/HMCL/src/main/resources/assets/fxml/download/versions.fxml index a57c3c79c..8ca452019 100644 --- a/HMCL/src/main/resources/assets/fxml/download/versions.fxml +++ b/HMCL/src/main/resources/assets/fxml/download/versions.fxml @@ -3,11 +3,15 @@ + - + + + diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 927b94217..bdec414d7 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -105,6 +105,7 @@ crash.user_fault=Your OS or Java environment may not be properly installed resul download=Download download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) download.failed=Failed to download +download.failed.refresh=Unable to load version list. Click here to retry. download.mojang=Mojang download.not_200=Failed to download, the response code is %s. download.source=Download Source 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 07de1caa7..1174f9fba 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -105,6 +105,7 @@ crash.user_fault=您的系统或Java环境可能安装不当导致本软件崩 download=下载 download.BMCL=BMCLAPI (bangbang93, http://bmclapi.bangbang93.com/) download.failed=下载失败 +download.failed.refresh=加载版本列表失败,点击此处重试。 download.mojang=官方 download.not_200=下载失败,HTTP状态码:%s. download.source=下载源 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java index 1e69d16cb..da9a920c0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/download/DefaultGameBuilder.java @@ -62,7 +62,7 @@ public class DefaultGameBuilder extends GameBuilder { downloadGameAsync(gameVersion, version), new GameLibrariesTask(dependencyManager, version) // Game libraries will be downloaded for multiple times partly, this time is for vanilla libraries. ).with(new VersionJsonSaveTask(dependencyManager.getGameRepository(), version)); // using [with] because download failure here are tolerant. - + if (toolVersions.containsKey("forge")) result = result.then(libraryTaskHelper(gameVersion, "forge")); if (toolVersions.containsKey("liteloader")) @@ -70,12 +70,9 @@ public class DefaultGameBuilder extends GameBuilder { if (toolVersions.containsKey("optifine")) result = result.then(libraryTaskHelper(gameVersion, "optifine")); return result; - }).finalized(new Task() { - @Override - public void execute() { - if (!isDependentsSucceeded()) - dependencyManager.getGameRepository().getVersionRoot(name).delete(); - } + }).finalized((variables, isDependentsSucceeded) -> { + if (!isDependentsSucceeded) + dependencyManager.getGameRepository().getVersionRoot(name).delete(); }); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java new file mode 100644 index 000000000..89fb9d791 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedCallback.java @@ -0,0 +1,24 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2017 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.task; + +import org.jackhuang.hmcl.util.AutoTypingMap; + +public interface FinalizedCallback { + void execute(AutoTypingMap variables, boolean isDependentsSucceeded) throws Exception; +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java new file mode 100644 index 000000000..c2b3ac82a --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FinalizedTask.java @@ -0,0 +1,78 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2017 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hmcl.task; + +import org.jackhuang.hmcl.util.AutoTypingMap; +import org.jackhuang.hmcl.util.ExceptionalFunction; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * A task that combines two tasks and make sure [pred] runs before succ. + * + * @author huangyuhui + */ +final class FinalizedTask extends Task { + + private final Collection dependents; + private final FinalizedCallback callback; + private final Scheduler scheduler; + + /** + * A task that combines two tasks and make sure pred runs before succ. + * + * @param pred the task that runs before succ. + * @param callback a callback that returns the task runs after pred, succ will be executed asynchronously. You can do something that relies on the result of pred. + */ + public FinalizedTask(Task pred, Scheduler scheduler, FinalizedCallback callback) { + this.dependents = Collections.singleton(pred); + this.scheduler = scheduler; + this.callback = callback; + + setSignificance(TaskSignificance.MODERATE); + setName(callback.toString()); + } + + @Override + public Scheduler getScheduler() { + return scheduler; + } + + @Override + public void execute() throws Exception { + setName(callback.toString()); + callback.execute(getVariables(), isDependentsSucceeded()); + + if (!isDependentsSucceeded()) + throw new SilentException(); + } + + @Override + public Collection getDependents() { + return dependents; + } + + @Override + public boolean isRelyingOnDependents() { + return false; + } +} + diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java index ee2552b13..ec8dc050f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.java @@ -260,12 +260,12 @@ public abstract class Task { return new CoupleTask<>(this, b, false, false); } - public final Task finalized(Task b) { - return finalized(convert(b)); + public final Task finalized(FinalizedCallback b) { + return finalized(Schedulers.defaultScheduler(), b); } - public final Task finalized(ExceptionalFunction, Task, ?> b) { - return new CoupleTask<>(this, b, false, true); + public final Task finalized(Scheduler scheduler, FinalizedCallback b) { + return new FinalizedTask(this, scheduler, b); } public static Task empty() {