refactor(task): fix stage progress.
This commit is contained in:
@@ -35,8 +35,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class HMCLModpackInstallTask extends Task<Void> {
|
||||
private final File zipFile;
|
||||
@@ -107,13 +105,5 @@ public final class HMCLModpackInstallTask extends Task<Void> {
|
||||
dependencies.add(libraryTask.thenComposeAsync(repository::saveAsync));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getStages() {
|
||||
return Stream.concat(
|
||||
dependents.stream().flatMap(task -> task.getStages().stream()),
|
||||
Stream.of("hmcl.modpack")
|
||||
).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static final String MODPACK_TYPE = "HMCL";
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ import java.nio.file.FileSystem;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
@@ -167,7 +168,8 @@ public final class ModpackHelper {
|
||||
};
|
||||
|
||||
return new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name)
|
||||
.whenComplete(Schedulers.defaultScheduler(), success, failure);
|
||||
.whenComplete(Schedulers.defaultScheduler(), success, failure)
|
||||
.withStagesHint(Arrays.asList("hmcl.modpack", "hmcl.modpack.download"));
|
||||
}
|
||||
|
||||
public static boolean isExternalGameNameConflicts(String name) {
|
||||
@@ -223,7 +225,8 @@ public final class ModpackHelper {
|
||||
public static Task<Void> getUpdateTask(Profile profile, ServerModpackManifest manifest, Charset charset, String name, ModpackConfiguration<?> configuration) throws UnsupportedModpackException {
|
||||
switch (configuration.getType()) {
|
||||
case ServerModpackRemoteInstallTask.MODPACK_TYPE:
|
||||
return new ModpackUpdateTask(profile.getRepository(), name, new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name));
|
||||
return new ModpackUpdateTask(profile.getRepository(), name, new ServerModpackRemoteInstallTask(profile.getDependency(), manifest, name))
|
||||
.withStagesHint(Arrays.asList("hmcl.modpack", "hmcl.modpack.download"));
|
||||
default:
|
||||
throw new UnsupportedModpackException();
|
||||
}
|
||||
|
||||
@@ -275,6 +275,16 @@ public final class Controllers {
|
||||
return pane;
|
||||
}
|
||||
|
||||
public static TaskExecutorDialogPane taskDialog(Task<?> task, String title, Consumer<Region> onCancel) {
|
||||
TaskExecutor executor = task.executor();
|
||||
TaskExecutorDialogPane pane = new TaskExecutorDialogPane(onCancel);
|
||||
pane.setTitle(title);
|
||||
pane.setExecutor(executor);
|
||||
dialog(pane);
|
||||
executor.start();
|
||||
return pane;
|
||||
}
|
||||
|
||||
public static void navigate(Node node) {
|
||||
decorator.getNavigator().navigate(node, ContainerAnimations.FADE.getAnimationProducer());
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.jackhuang.hmcl.ui.FXUtils.runInFX;
|
||||
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
@@ -96,7 +97,7 @@ public final class TaskListPane extends StackPane {
|
||||
|
||||
@Override
|
||||
public void onReady(Task<?> task) {
|
||||
if (task instanceof Task.StageTask) {
|
||||
if (task.getStage() != null) {
|
||||
Platform.runLater(() -> {
|
||||
stageNodes.stream().filter(x -> x.stage.equals(task.getStage())).findAny().ifPresent(StageNode::begin);
|
||||
});
|
||||
@@ -150,7 +151,7 @@ public final class TaskListPane extends StackPane {
|
||||
|
||||
@Override
|
||||
public void onFinished(Task<?> task) {
|
||||
if (task instanceof Task.StageTask) {
|
||||
if (task.getStage() != null) {
|
||||
Platform.runLater(() -> {
|
||||
stageNodes.stream().filter(x -> x.stage.equals(task.getStage())).findAny().ifPresent(StageNode::succeed);
|
||||
});
|
||||
@@ -167,7 +168,7 @@ public final class TaskListPane extends StackPane {
|
||||
|
||||
@Override
|
||||
public void onFailed(Task<?> task, Throwable throwable) {
|
||||
if (task instanceof Task.StageTask) {
|
||||
if (task.getStage() != null) {
|
||||
Platform.runLater(() -> {
|
||||
stageNodes.stream().filter(x -> x.stage.equals(task.getStage())).findAny().ifPresent(StageNode::fail);
|
||||
});
|
||||
@@ -181,14 +182,29 @@ public final class TaskListPane extends StackPane {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPropertiesUpdate(Map<String, Map<String, Object>> stageProperties) {
|
||||
stageProperties.forEach((stage, properties) -> {
|
||||
int count = tryCast(properties.get("count"), Integer.class).orElse(0),
|
||||
total = tryCast(properties.get("total"), Integer.class).orElse(0);
|
||||
if (total > 0)
|
||||
Platform.runLater(() ->
|
||||
stageNodes.stream().filter(x -> x.stage.equals(stage)).findAny().ifPresent(stageNode -> stageNode.updateCounter(count, total)));
|
||||
});
|
||||
public void onPropertiesUpdate(Task<?> task) {
|
||||
if (task instanceof Task.CountTask) {
|
||||
runInFX(() -> {
|
||||
stageNodes.stream()
|
||||
.filter(x -> x.stage.equals(((Task.CountTask) task).getCountStage()))
|
||||
.findAny()
|
||||
.ifPresent(StageNode::count);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (task.getStage() != null) {
|
||||
int total = tryCast(task.getProperties().get("total"), Integer.class).orElse(0);
|
||||
runInFX(() -> {
|
||||
stageNodes.stream()
|
||||
.filter(x -> x.stage.equals(task.getStage()))
|
||||
.findAny()
|
||||
.ifPresent(stageNode -> {
|
||||
stageNode.setTotal(total);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -197,6 +213,8 @@ public final class TaskListPane extends StackPane {
|
||||
private final String stage;
|
||||
private final Label title = new Label();
|
||||
private final String message;
|
||||
private int count = 0;
|
||||
private int total = 0;
|
||||
private boolean started = false;
|
||||
|
||||
public StageNode(String stage) {
|
||||
@@ -242,6 +260,15 @@ public final class TaskListPane extends StackPane {
|
||||
setLeft(FXUtils.limitingSize(SVG.check(Theme.blackFillBinding(), 14, 14), 14, 14));
|
||||
}
|
||||
|
||||
public void count() {
|
||||
updateCounter(++count, total);
|
||||
}
|
||||
|
||||
public void setTotal(int total) {
|
||||
this.total = total;
|
||||
updateCounter(count, total);
|
||||
}
|
||||
|
||||
public void updateCounter(int count, int total) {
|
||||
if (total > 0)
|
||||
title.setText(String.format("%s - %d/%d", message, count, total));
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui.versions;
|
||||
|
||||
import org.jackhuang.hmcl.mod.LocalMod;
|
||||
import org.jackhuang.hmcl.mod.RemoteMod;
|
||||
import org.jackhuang.hmcl.mod.RemoteModRepository;
|
||||
import org.jackhuang.hmcl.mod.curse.CurseForgeRemoteModRepository;
|
||||
@@ -76,11 +77,6 @@ public class ModDownloadListPage extends DownloadListPage {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<RemoteMod.Version> getRemoteVersionByLocalFile(Path file) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Category> getCategories() throws IOException {
|
||||
if ("mods.modrinth".equals(downloadSource.get())) {
|
||||
@@ -89,6 +85,21 @@ public class ModDownloadListPage extends DownloadListPage {
|
||||
return CurseForgeRemoteModRepository.MODS.getCategories();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<RemoteMod.Version> getRemoteVersionByLocalFile(LocalMod localMod, Path file) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteMod getModById(String id) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<RemoteMod.Version> getRemoteVersionsById(String id) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,16 +32,14 @@ import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.ui.Controllers;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.ui.ListPageBase;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
|
||||
import org.jackhuang.hmcl.util.Logging;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -176,6 +174,27 @@ public final class ModListPage extends ListPageBase<ModListPageSkin.ModInfoObjec
|
||||
FXUtils.openFolder(new File(profile.getRepository().getRunDirectory(versionId), "mods"));
|
||||
}
|
||||
|
||||
public void checkUpdates() {
|
||||
Controllers.taskDialog(
|
||||
Task.composeAsync(() -> {
|
||||
Optional<String> gameVersion = profile.getRepository().getGameVersion(versionId);
|
||||
if (gameVersion.isPresent()) {
|
||||
return new ModUpdateTask(gameVersion.get(), modManager.getMods());
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.whenComplete(Schedulers.javafx(), (result, exception) -> {
|
||||
if (exception != null) {
|
||||
Controllers.dialog("Failed to check updates", "failed", MessageDialogPane.MessageType.ERROR);
|
||||
} else {
|
||||
Controllers.dialog(new ModUpdatesDialog(result));
|
||||
}
|
||||
})
|
||||
.withStagesHint(Collections.singletonList("mods.check_updates"))
|
||||
, i18n("update.checking"), pane -> {
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isModded() {
|
||||
return modded.get();
|
||||
}
|
||||
|
||||
@@ -92,7 +92,9 @@ class ModListPageSkin extends SkinBase<ModListPage> {
|
||||
createToolbarButton2(i18n("mods.disable"), SVG::close, () ->
|
||||
skinnable.disableSelected(listView.getSelectionModel().getSelectedItems())),
|
||||
createToolbarButton2(i18n("folder.mod"), SVG::folderOpen, () ->
|
||||
skinnable.openModFolder()));
|
||||
skinnable.openModFolder()),
|
||||
createToolbarButton2(i18n("mods.check_updates"), SVG::update, () ->
|
||||
skinnable.checkUpdates()));
|
||||
root.getContent().add(toolbar);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui.versions;
|
||||
|
||||
import org.jackhuang.hmcl.mod.LocalMod;
|
||||
import org.jackhuang.hmcl.mod.curse.CurseForgeRemoteModRepository;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ModUpdateTask extends Task<List<LocalMod.ModUpdate>> {
|
||||
|
||||
private final String gameVersion;
|
||||
private final Collection<LocalMod> mods;
|
||||
private final Collection<Task<LocalMod.ModUpdate>> dependents;
|
||||
|
||||
public ModUpdateTask(String gameVersion, Collection<LocalMod> mods) {
|
||||
this.gameVersion = gameVersion;
|
||||
this.mods = mods;
|
||||
|
||||
dependents = mods.stream()
|
||||
.map(mod -> Task.supplyAsync(() -> {
|
||||
return mod.checkUpdates(gameVersion, CurseForgeRemoteModRepository.MODS);
|
||||
}).setSignificance(TaskSignificance.MAJOR).withCounter("mods.check_updates"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
setStage("mods.check_updates");
|
||||
getProperties().put("total", dependents.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doPreExecute() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preExecute() throws Exception {
|
||||
notifyPropertiesChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends Task<?>> getDependents() {
|
||||
return dependents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRelyingOnDependents() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws Exception {
|
||||
setResult(dependents.stream()
|
||||
.filter(task -> task.getResult() != null)
|
||||
.map(Task::getResult)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Hello Minecraft! Launcher
|
||||
* Copyright (C) 2021 huangyuhui <huanghongxun2008@126.com> and contributors
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui.versions;
|
||||
|
||||
import com.jfoenix.controls.JFXListView;
|
||||
import org.jackhuang.hmcl.mod.LocalMod;
|
||||
import org.jackhuang.hmcl.mod.curse.CurseAddon;
|
||||
import org.jackhuang.hmcl.mod.modrinth.ModrinthRemoteModRepository;
|
||||
import org.jackhuang.hmcl.ui.construct.DialogPane;
|
||||
import org.jackhuang.hmcl.ui.construct.MDListCell;
|
||||
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
public class ModUpdatesDialog extends DialogPane {
|
||||
|
||||
public ModUpdatesDialog(List<LocalMod.ModUpdate> updates) {
|
||||
setTitle(i18n("mods.check_updates"));
|
||||
|
||||
JFXListView<LocalMod.ModUpdate> listView = new JFXListView<>();
|
||||
listView.getItems().setAll(updates);
|
||||
listView.setCellFactory(l -> new ModUpdateCell(listView));
|
||||
setBody(listView);
|
||||
}
|
||||
|
||||
public static class ModUpdateCell extends MDListCell<LocalMod.ModUpdate> {
|
||||
TwoLineListItem content = new TwoLineListItem();
|
||||
|
||||
public ModUpdateCell(JFXListView<LocalMod.ModUpdate> listView) {
|
||||
super(listView);
|
||||
|
||||
getContainer().getChildren().setAll(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateControl(LocalMod.ModUpdate item, boolean empty) {
|
||||
if (empty) return;
|
||||
ModTranslations.Mod mod = ModTranslations.getModById(item.getLocalMod().getId());
|
||||
content.setTitle(mod != null ? mod.getDisplayName() : item.getCurrentVersion().getName());
|
||||
content.setSubtitle(item.getLocalMod().getFileName());
|
||||
content.getTags().setAll();
|
||||
|
||||
if (item.getCurrentVersion().getSelf() instanceof CurseAddon.LatestFile) {
|
||||
content.getTags().add("Curseforge");
|
||||
} else if (item.getCurrentVersion().getSelf() instanceof ModrinthRemoteModRepository.ModVersion) {
|
||||
content.getTags().add("Modrinth");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ public class JavaRuntimeDownloadTask extends Task<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Task<?>> getDependencies() {
|
||||
public Collection<? extends Task<?>> getDependencies() {
|
||||
return super.getDependencies();
|
||||
}
|
||||
|
||||
|
||||
@@ -580,6 +580,7 @@ mods.add=Install mods
|
||||
mods.add.failed=Failed to install mods %s.
|
||||
mods.add.success=Successfully installed mods %s.
|
||||
mods.category=Category
|
||||
mods.check_updates=Check updates
|
||||
mods.choose_mod=Choose your mods
|
||||
mods.curseforge=CurseForge
|
||||
mods.dependencies=Dependencies
|
||||
|
||||
@@ -580,6 +580,7 @@ mods.add=新增模組
|
||||
mods.add.failed=新增模組 %s 失敗。
|
||||
mods.add.success=成功新增模組 %s。
|
||||
mods.category=類別
|
||||
mods.check_updates=檢查模組更新
|
||||
mods.choose_mod=選擇模組
|
||||
mods.curseforge=CurseForge
|
||||
mods.dependencies=前置 Mod
|
||||
|
||||
@@ -580,6 +580,7 @@ mods.add=添加模组
|
||||
mods.add.failed=添加模组 %s 失败。
|
||||
mods.add.success=成功添加模组 %s。
|
||||
mods.category=类别
|
||||
mods.check_updates=检查模组更新
|
||||
mods.choose_mod=选择模组
|
||||
mods.curseforge=CurseForge
|
||||
mods.dependencies=前置 Mod
|
||||
|
||||
Reference in New Issue
Block a user