Drop modpack file to install

This commit is contained in:
huanghongxun 2018-10-11 13:32:11 +08:00
parent b4738f383b
commit 355fc04069
8 changed files with 152 additions and 58 deletions

View File

@ -30,6 +30,7 @@ import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
@ -42,16 +43,24 @@ import org.jackhuang.hmcl.ui.construct.PopupMenu;
import org.jackhuang.hmcl.ui.construct.RipplerContainer;
import org.jackhuang.hmcl.ui.construct.TwoLineListItem;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
import org.jackhuang.hmcl.ui.versions.GameItem;
import org.jackhuang.hmcl.ui.versions.Versions;
import org.jackhuang.hmcl.upgrade.RemoteVersion;
import org.jackhuang.hmcl.upgrade.UpdateChecker;
import org.jackhuang.hmcl.upgrade.UpdateHandler;
import org.jackhuang.hmcl.util.Logging;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.javafx.MultiStepBinding;
import org.jackhuang.hmcl.util.versioning.VersionNumber;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Level;
import java.util.stream.Collectors;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
@ -126,6 +135,29 @@ public final class MainPage extends StackPane implements DecoratorPage {
});
Profiles.registerVersionsListener(this::loadVersions);
setOnDragOver(event -> {
if (event.getGestureSource() != this && event.getDragboard().hasFiles()) {
if (event.getDragboard().getFiles().stream().anyMatch(it -> "zip".equals(FileUtils.getExtension(it))))
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}
event.consume();
});
setOnDragDropped(event -> {
List<File> files = event.getDragboard().getFiles();
if (files != null) {
List<File> modpacks = files.stream()
.filter(it -> "zip".equals(FileUtils.getExtension(it)))
.collect(Collectors.toList());
if (!modpacks.isEmpty()) {
File modpack = modpacks.get(0);
Controllers.getDecorator().startWizard(new ModpackInstallWizardProvider(modpack), i18n("install.modpack"));
event.setDropCompleted(true);
}
}
event.consume();
});
}
private void loadVersions(Profile profile) {

View File

@ -0,0 +1,78 @@
package org.jackhuang.hmcl.ui.download;
import javafx.scene.Node;
import org.jackhuang.hmcl.download.DownloadProvider;
import org.jackhuang.hmcl.game.ModpackHelper;
import org.jackhuang.hmcl.mod.Modpack;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.ui.wizard.WizardController;
import org.jackhuang.hmcl.ui.wizard.WizardProvider;
import java.io.File;
import java.util.Map;
import static org.jackhuang.hmcl.util.Lang.tryCast;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class ModpackInstallWizardProvider implements WizardProvider {
private Profile profile;
private final File file;
public ModpackInstallWizardProvider() {
this(null);
}
public ModpackInstallWizardProvider(File modpackFile) {
this.file = modpackFile;
}
@Override
public void start(Map<String, Object> settings) {
profile = Profiles.getSelectedProfile();
if (file != null)
settings.put(ModpackPage.MODPACK_FILE, file);
settings.put(PROFILE, profile);
}
private Task finishModpackInstallingAsync(Map<String, Object> settings) {
if (!settings.containsKey(ModpackPage.MODPACK_FILE))
return null;
File selected = tryCast(settings.get(ModpackPage.MODPACK_FILE), File.class).orElse(null);
Modpack modpack = tryCast(settings.get(ModpackPage.MODPACK_MANIFEST), Modpack.class).orElse(null);
String name = tryCast(settings.get(ModpackPage.MODPACK_NAME), String.class).orElse(null);
if (selected == null || modpack == null || name == null) return null;
return ModpackHelper.getInstallTask(profile, selected, name, modpack)
.then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name)));
}
@Override
public Object finish(Map<String, Object> settings) {
settings.put("success_message", i18n("install.success"));
settings.put("failure_message", i18n("install.failed"));
return finishModpackInstallingAsync(settings);
}
@Override
public Node createPage(WizardController controller, int step, Map<String, Object> settings) {
switch (step) {
case 0:
return new ModpackPage(controller);
default:
throw new IllegalStateException("error step " + step + ", settings: " + settings + ", pages: " + controller.getPages());
}
}
@Override
public boolean cancel() {
return true;
}
public static final String PROFILE = "PROFILE";
}

View File

@ -32,6 +32,7 @@ import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.WebStage;
import org.jackhuang.hmcl.ui.construct.MessageBox;
import org.jackhuang.hmcl.ui.construct.Validator;
import org.jackhuang.hmcl.ui.wizard.WizardController;
import org.jackhuang.hmcl.ui.wizard.WizardPage;
@ -39,7 +40,9 @@ import org.jackhuang.hmcl.util.StringUtils;
import java.io.File;
import java.util.Map;
import java.util.Optional;
import static org.jackhuang.hmcl.util.Lang.tryCast;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public final class ModpackPage extends StackPane implements WizardPage {
@ -75,31 +78,41 @@ public final class ModpackPage extends StackPane implements WizardPage {
Profile profile = (Profile) controller.getSettings().get("PROFILE");
FileChooser chooser = new FileChooser();
chooser.setTitle(i18n("modpack.choose"));
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n("modpack"), "*.zip"));
File selectedFile = chooser.showOpenDialog(Controllers.getStage());
if (selectedFile == null) Platform.runLater(controller::onEnd);
else {
File selectedFile;
Optional<File> filePath = tryCast(controller.getSettings().get(MODPACK_FILE), File.class);
if (filePath.isPresent()) {
selectedFile = filePath.get();
} else {
FileChooser chooser = new FileChooser();
chooser.setTitle(i18n("modpack.choose"));
chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter(i18n("modpack"), "*.zip"));
selectedFile = chooser.showOpenDialog(Controllers.getStage());
if (selectedFile == null) {
Platform.runLater(controller::onEnd);
return;
}
controller.getSettings().put(MODPACK_FILE, selectedFile);
}
try {
manifest = ModpackHelper.readModpackManifest(selectedFile);
controller.getSettings().put(MODPACK_MANIFEST, manifest);
lblName.setText(manifest.getName());
lblVersion.setText(manifest.getVersion());
lblAuthor.setText(manifest.getAuthor());
txtModpackName.setText(manifest.getName() + (StringUtils.isBlank(manifest.getVersion()) ? "" : "-" + manifest.getVersion()));
lblModpackLocation.setText(selectedFile.getAbsolutePath());
txtModpackName.getValidators().addAll(
new Validator(i18n("install.new_game.already_exists"), str -> !profile.getRepository().hasVersion(str) && StringUtils.isNotBlank(str)),
new Validator(i18n("version.forbidden_name"), str -> !profile.getRepository().forbidsVersion(str))
);
txtModpackName.textProperty().addListener(e -> btnInstall.setDisable(!txtModpackName.validate()));
try {
manifest = ModpackHelper.readModpackManifest(selectedFile);
controller.getSettings().put(MODPACK_MANIFEST, manifest);
lblName.setText(manifest.getName());
lblVersion.setText(manifest.getVersion());
lblAuthor.setText(manifest.getAuthor());
txtModpackName.setText(manifest.getName() + (StringUtils.isBlank(manifest.getVersion()) ? "" : "-" + manifest.getVersion()));
} catch (UnsupportedModpackException e) {
txtModpackName.setText(i18n("modpack.task.install.error"));
btnInstall.setDisable(true);
}
} catch (UnsupportedModpackException e) {
Controllers.dialog(i18n("modpack.task.install.error"), i18n("message.error"), MessageBox.ERROR_MESSAGE);
Platform.runLater(controller::onEnd);
}
}

View File

@ -21,8 +21,6 @@ import javafx.scene.Node;
import org.jackhuang.hmcl.download.DownloadProvider;
import org.jackhuang.hmcl.download.GameBuilder;
import org.jackhuang.hmcl.download.RemoteVersion;
import org.jackhuang.hmcl.game.ModpackHelper;
import org.jackhuang.hmcl.mod.Modpack;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.task.Schedulers;
@ -30,18 +28,14 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.ui.wizard.WizardController;
import org.jackhuang.hmcl.ui.wizard.WizardProvider;
import java.io.File;
import java.util.Map;
import static org.jackhuang.hmcl.util.Lang.tryCast;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public final class DownloadWizardProvider implements WizardProvider {
public final class VanillaInstallWizardProvider implements WizardProvider {
private Profile profile;
private final int type;
public DownloadWizardProvider(int type) {
this.type = type;
public VanillaInstallWizardProvider() {
}
@Override
@ -70,29 +64,12 @@ public final class DownloadWizardProvider implements WizardProvider {
.then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name)));
}
private Task finishModpackInstallingAsync(Map<String, Object> settings) {
if (!settings.containsKey(ModpackPage.MODPACK_FILE))
return null;
File selected = tryCast(settings.get(ModpackPage.MODPACK_FILE), File.class).orElse(null);
Modpack modpack = tryCast(settings.get(ModpackPage.MODPACK_MANIFEST), Modpack.class).orElse(null);
String name = tryCast(settings.get(ModpackPage.MODPACK_NAME), String.class).orElse(null);
if (selected == null || modpack == null || name == null) return null;
return ModpackHelper.getInstallTask(profile, selected, name, modpack)
.then(Task.of(Schedulers.javafx(), () -> profile.setSelectedVersion(name)));
}
@Override
public Object finish(Map<String, Object> settings) {
settings.put("success_message", i18n("install.success"));
settings.put("failure_message", i18n("install.failed"));
switch (type) {
case 0: return finishVersionDownloadingAsync(settings);
case 1: return finishModpackInstallingAsync(settings);
default: return null;
}
return finishVersionDownloadingAsync(settings);
}
@Override
@ -100,14 +77,7 @@ public final class DownloadWizardProvider implements WizardProvider {
DownloadProvider provider = profile.getDependency().getDownloadProvider();
switch (step) {
case 0:
switch (type) {
case 0:
return new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer.game")), "", provider, "game", () -> controller.onNext(new InstallersPage(controller, profile.getRepository(), provider)));
case 1:
return new ModpackPage(controller);
default:
throw new IllegalStateException("Error step " + step + ", subStep " + type + ", settings: " + settings + ", pages: " + controller.getPages());
}
return new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer.game")), "", provider, "game", () -> controller.onNext(new InstallersPage(controller, profile.getRepository(), provider)));
default:
throw new IllegalStateException("error step " + step + ", settings: " + settings + ", pages: " + controller.getPages());
}

View File

@ -33,7 +33,8 @@ import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.WeakListenerHolder;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.ui.download.DownloadWizardProvider;
import org.jackhuang.hmcl.ui.download.ModpackInstallWizardProvider;
import org.jackhuang.hmcl.ui.download.VanillaInstallWizardProvider;
import org.jackhuang.hmcl.util.i18n.I18n;
import org.jackhuang.hmcl.util.versioning.VersionNumber;
@ -99,11 +100,11 @@ public class GameList extends Control implements DecoratorPage {
}
public void addNewGame() {
Controllers.getDecorator().startWizard(new DownloadWizardProvider(0), i18n("install.new_game"));
Controllers.getDecorator().startWizard(new VanillaInstallWizardProvider(), i18n("install.new_game"));
}
public void importModpack() {
Controllers.getDecorator().startWizard(new DownloadWizardProvider(1), i18n("install.modpack"));
Controllers.getDecorator().startWizard(new ModpackInstallWizardProvider(), i18n("install.modpack"));
}
public void refresh() {

View File

@ -217,7 +217,7 @@ modpack.name=Modpack Name
modpack.not_a_valid_name=Not a valid modpack name
modpack.scan=Scanning this modpack
modpack.task.install=Import Modpack
modpack.task.install.error=Failed to install the modpack. Maybe the files is incorrect, or a management issue occurred.
modpack.task.install.error=This modpack file cannot be recognized. Only Curse, MultiMC modpacks are supported.
modpack.task.install.will=Install the modpack:
modpack.type.curse=Curse
modpack.type.curse.completion=Install relative files to Curse modpack

View File

@ -217,7 +217,7 @@ modpack.name=整合包名稱
modpack.not_a_valid_name=整合包名稱無效
modpack.scan=解析整合包
modpack.task.install=匯入整合包
modpack.task.install.error=安裝失敗,可能是整合包格式錯誤或操作檔案失敗
modpack.task.install.error=無法識別該整合包,目前僅支持導入 Curse、MultiMC、HMCL 整合包
modpack.task.install.will=將會安裝整合包:
modpack.type.curse=Curse
modpack.type.curse.completion=下載 Curse 整合包相關檔案

View File

@ -217,7 +217,7 @@ modpack.name=整合包名称
modpack.not_a_valid_name=不是一个有效的整合包名称
modpack.scan=解析整合包
modpack.task.install=导入整合包
modpack.task.install.error=安装失败,可能是整合包格式不正确或操作文件失败
modpack.task.install.error=无法识别该整合包,目前仅支持导入 Curse、MultiMC、HMCL 整合包
modpack.task.install.will=将会安装整合包:
modpack.type.curse=Curse
modpack.type.curse.completion=下载 Curse 整合包相关文件