add: allow removing libraries in vanilla installation

This commit is contained in:
huanghongxun
2020-03-16 22:49:15 +08:00
parent bde76707f3
commit 6a982b2a5c
7 changed files with 193 additions and 196 deletions

View File

@@ -20,7 +20,6 @@ package org.jackhuang.hmcl.ui.download;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.control.Label;
import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.DownloadProvider;
import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.LibraryAnalyzer;
import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.RemoteVersion;
@@ -51,9 +50,20 @@ class AdditionalInstallersPage extends InstallersPage {
txtName.setText(version.getId()); txtName.setText(version.getId());
txtName.setEditable(false); txtName.setEditable(false);
btnInstall.disableProperty().bind(Bindings.createBooleanBinding( installable.bind(Bindings.createBooleanBinding(
() -> !compatible.get() || !txtName.validate(), () -> compatible.get() && txtName.validate(),
txtName.textProperty(), compatible)); txtName.textProperty(), compatible));
InstallerPageItem[] libraries = new InstallerPageItem[]{game, fabric, forge, liteLoader, optiFine};
for (InstallerPageItem library : libraries) {
String libraryId = library.id;
if (libraryId.equals("game")) continue;
library.removeAction.set(e -> {
controller.getSettings().put(libraryId, new UpdateInstallerWizardProvider.RemoveVersionAction(libraryId));
reload();
});
}
} }
@Override @Override
@@ -67,11 +77,13 @@ class AdditionalInstallersPage extends InstallersPage {
} }
private String getVersion(String id) { private String getVersion(String id) {
return Optional.ofNullable(controller.getSettings().get(id)).map(it -> (RemoteVersion) it).map(RemoteVersion::getSelfVersion).orElse(null); return Optional.ofNullable(controller.getSettings().get(id))
.flatMap(it -> Lang.tryCast(it, RemoteVersion.class))
.map(RemoteVersion::getSelfVersion).orElse(null);
} }
@Override @Override
public void onNavigate(Map<String, Object> settings) { protected void reload() {
LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version.resolvePreservingPatches(repository)); LibraryAnalyzer analyzer = LibraryAnalyzer.analyze(version.resolvePreservingPatches(repository));
String game = analyzer.getVersion(MINECRAFT).orElse(null); String game = analyzer.getVersion(MINECRAFT).orElse(null);
String fabric = analyzer.getVersion(FABRIC).orElse(null); String fabric = analyzer.getVersion(FABRIC).orElse(null);
@@ -79,26 +91,28 @@ class AdditionalInstallersPage extends InstallersPage {
String liteLoader = analyzer.getVersion(LITELOADER).orElse(null); String liteLoader = analyzer.getVersion(LITELOADER).orElse(null);
String optiFine = analyzer.getVersion(OPTIFINE).orElse(null); String optiFine = analyzer.getVersion(OPTIFINE).orElse(null);
Label[] labels = new Label[]{lblGame, lblFabric, lblForge, lblLiteLoader, lblOptiFine}; InstallerPageItem[] libraries = new InstallerPageItem[]{this.game, this.fabric, this.forge, this.liteLoader, this.optiFine};
String[] libraryIds = new String[]{"game", "fabric", "forge", "liteloader", "optifine"};
String[] versions = new String[]{game, fabric, forge, liteLoader, optiFine}; String[] versions = new String[]{game, fabric, forge, liteLoader, optiFine};
String currentGameVersion = Lang.nonNull(getVersion("game"), game); String currentGameVersion = Lang.nonNull(getVersion("game"), game);
boolean compatible = true; boolean compatible = true;
for (int i = 0; i < libraryIds.length; ++i) { for (int i = 0; i < libraries.length; ++i) {
String libraryId = libraryIds[i]; String libraryId = libraries[i].id;
String libraryVersion = Lang.nonNull(getVersion(libraryId), versions[i]); String libraryVersion = Lang.nonNull(getVersion(libraryId), versions[i]);
boolean alreadyInstalled = versions[i] != null; boolean alreadyInstalled = versions[i] != null && !(controller.getSettings().get(libraryId) instanceof UpdateInstallerWizardProvider.RemoveVersionAction);
if (!"game".equals(libraryId) && currentGameVersion != null && !currentGameVersion.equals(game) && getVersion(libraryId) == null && alreadyInstalled) { if (!"game".equals(libraryId) && currentGameVersion != null && !currentGameVersion.equals(game) && getVersion(libraryId) == null && alreadyInstalled) {
// For third-party libraries, if game version is being changed, and the library is not being reinstalled, // For third-party libraries, if game version is being changed, and the library is not being reinstalled,
// warns the user that we should update the library. // warns the user that we should update the library.
labels[i].setText(i18n("install.installer.change_version", i18n("install.installer." + libraryId), libraryVersion)); libraries[i].label.set(i18n("install.installer.change_version", i18n("install.installer." + libraryId), libraryVersion));
libraries[i].removable.set(true);
compatible = false; compatible = false;
} else if (alreadyInstalled || controller.getSettings().containsKey(libraryId)) { } else if (alreadyInstalled || getVersion(libraryId) != null) {
labels[i].setText(i18n("install.installer.version", i18n("install.installer." + libraryId)) + ": " + libraryVersion); libraries[i].label.set(i18n("install.installer.version", i18n("install.installer." + libraryId)) + ": " + libraryVersion);
libraries[i].removable.set(true);
} else { } else {
labels[i].setText(i18n("install.installer.not_installed", i18n("install.installer." + libraryId))); libraries[i].label.set(i18n("install.installer.not_installed", i18n("install.installer." + libraryId)));
libraries[i].removable.set(false);
} }
} }
this.compatible.set(compatible); this.compatible.set(compatible);

View File

@@ -21,15 +21,27 @@ import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXTextField; import com.jfoenix.controls.JFXTextField;
import com.jfoenix.effects.JFXDepthManager; import com.jfoenix.effects.JFXDepthManager;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.event.EventHandler;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.Node; import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.control.Control;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.layout.StackPane; import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.download.DownloadProvider; import org.jackhuang.hmcl.download.DownloadProvider;
import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.download.RemoteVersion;
import org.jackhuang.hmcl.game.GameRepository; import org.jackhuang.hmcl.game.GameRepository;
import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.SVG;
import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.construct.Validator;
import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardController;
import org.jackhuang.hmcl.ui.wizard.WizardPage; import org.jackhuang.hmcl.ui.wizard.WizardPage;
@@ -40,74 +52,40 @@ import java.util.Map;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class InstallersPage extends StackPane implements WizardPage { public class InstallersPage extends Control implements WizardPage {
protected final WizardController controller; protected final WizardController controller;
@FXML protected InstallerPageItem game = new InstallerPageItem("game");
protected VBox list; protected InstallerPageItem fabric = new InstallerPageItem("fabric");
protected InstallerPageItem forge = new InstallerPageItem("forge");
@FXML protected InstallerPageItem liteLoader = new InstallerPageItem("liteloader");
protected Node btnGame; protected InstallerPageItem optiFine = new InstallerPageItem("optifine");
protected JFXTextField txtName = new JFXTextField();
@FXML protected BooleanProperty installable = new SimpleBooleanProperty();
protected Node btnFabric;
@FXML
protected Node btnForge;
@FXML
protected Node btnLiteLoader;
@FXML
protected Node btnOptiFine;
@FXML
protected Label lblGame;
@FXML
protected Label lblFabric;
@FXML
protected Label lblForge;
@FXML
protected Label lblLiteLoader;
@FXML
protected Label lblOptiFine;
@FXML
protected JFXTextField txtName;
@FXML
protected JFXButton btnInstall;
public InstallersPage(WizardController controller, GameRepository repository, String gameVersion, DownloadProvider downloadProvider) { public InstallersPage(WizardController controller, GameRepository repository, String gameVersion, DownloadProvider downloadProvider) {
this.controller = controller; this.controller = controller;
FXUtils.loadFXML(this, "/assets/fxml/download/installers.fxml");
Validator hasVersion = new Validator(s -> !repository.hasVersion(s) && StringUtils.isNotBlank(s)); Validator hasVersion = new Validator(s -> !repository.hasVersion(s) && StringUtils.isNotBlank(s));
hasVersion.setMessage(i18n("install.new_game.already_exists")); hasVersion.setMessage(i18n("install.new_game.already_exists"));
Validator nameValidator = new Validator(OperatingSystem::isNameValid); Validator nameValidator = new Validator(OperatingSystem::isNameValid);
nameValidator.setMessage(i18n("install.new_game.malformed")); nameValidator.setMessage(i18n("install.new_game.malformed"));
txtName.getValidators().addAll(hasVersion, nameValidator); txtName.getValidators().addAll(hasVersion, nameValidator);
btnInstall.disableProperty().bind(Bindings.createBooleanBinding(() -> !txtName.validate(), installable.bind(Bindings.createBooleanBinding(() -> txtName.validate(),
txtName.textProperty())); txtName.textProperty()));
txtName.setText(gameVersion); txtName.setText(gameVersion);
Node[] buttons = new Node[]{btnGame, btnFabric, btnForge, btnLiteLoader, btnOptiFine}; InstallerPageItem[] libraries = new InstallerPageItem[]{game, fabric, forge, liteLoader, optiFine};
String[] libraryIds = new String[]{"game", "fabric", "forge", "liteloader", "optifine"};
for (Node node : list.getChildren()) { for (InstallerPageItem library : libraries) {
JFXDepthManager.setDepth(node, 1); String libraryId = library.id;
}
for (int i = 0; i < libraryIds.length; ++i) {
String libraryId = libraryIds[i];
if (libraryId.equals("game")) continue; if (libraryId.equals("game")) continue;
buttons[i].setOnMouseClicked(e -> library.action.set(e ->
controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, downloadProvider, libraryId, () -> controller.onPrev(false)))); controller.onNext(new VersionsPage(controller, i18n("install.installer.choose", i18n("install.installer." + libraryId)), gameVersion, downloadProvider, libraryId, () -> controller.onPrev(false))));
library.removeAction.set(e -> {
controller.getSettings().remove(libraryId);
reload();
});
} }
} }
@@ -120,18 +98,24 @@ public class InstallersPage extends StackPane implements WizardPage {
return ((RemoteVersion) controller.getSettings().get(id)).getSelfVersion(); return ((RemoteVersion) controller.getSettings().get(id)).getSelfVersion();
} }
protected void reload() {
InstallerPageItem[] libraries = new InstallerPageItem[]{game, fabric, forge, liteLoader, optiFine};
for (InstallerPageItem library : libraries) {
String libraryId = library.id;
if (controller.getSettings().containsKey(libraryId)) {
library.label.set(i18n("install.installer.version", i18n("install.installer." + libraryId)) + ": " + getVersion(libraryId));
library.removable.set(true);
} else {
library.label.setValue(i18n("install.installer.not_installed", i18n("install.installer." + libraryId)));
library.removable.set(false);
}
}
}
@Override @Override
public void onNavigate(Map<String, Object> settings) { public void onNavigate(Map<String, Object> settings) {
Label[] labels = new Label[]{lblGame, lblFabric, lblForge, lblLiteLoader, lblOptiFine}; reload();
String[] libraryIds = new String[]{"game", "fabric", "forge", "liteloader", "optifine"};
for (int i = 0; i < libraryIds.length; ++i) {
String libraryId = libraryIds[i];
if (controller.getSettings().containsKey(libraryId))
labels[i].setText(i18n("install.installer.version", i18n("install.installer." + libraryId)) + ": " + getVersion(libraryId));
else
labels[i].setText(i18n("install.installer.not_installed", i18n("install.installer." + libraryId)));
}
} }
@Override @Override
@@ -143,4 +127,108 @@ public class InstallersPage extends StackPane implements WizardPage {
controller.getSettings().put("name", txtName.getText()); controller.getSettings().put("name", txtName.getText());
controller.onFinish(); controller.onFinish();
} }
@Override
protected Skin<?> createDefaultSkin() {
return new InstallersPageSkin(this);
}
protected static class InstallerPageItem {
String id;
StringProperty label = new SimpleStringProperty();
BooleanProperty removable = new SimpleBooleanProperty();
ObjectProperty<EventHandler<? super MouseEvent>> removeAction = new SimpleObjectProperty<>();
ObjectProperty<EventHandler<? super MouseEvent>> action = new SimpleObjectProperty<>();
public InstallerPageItem(String id) {
this.id = id;
}
}
protected static class InstallersPageSkin extends SkinBase<InstallersPage> {
protected static class InstallersPageItemSkin extends BorderPane {
final ImageView imageView;
final Label label;
InstallersPageItemSkin(String imageUrl, InstallerPageItem item, boolean clickable) {
setPadding(new Insets(8));
getStyleClass().add("card");
setLeft(imageView = new ImageView(new Image(imageUrl, 32, 32, true, true)));
setCenter(label = new Label());
label.textProperty().bind(item.label);
BorderPane.setMargin(label, new Insets(0, 0, 0, 8));
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
if (clickable) {
HBox right = new HBox();
right.setAlignment(Pos.CENTER_RIGHT);
setRight(right);
JFXButton closeButton = new JFXButton();
closeButton.setGraphic(SVG.close(Theme.blackFillBinding(), -1, -1));
right.getChildren().add(closeButton);
closeButton.getStyleClass().add("toggle-icon4");
closeButton.visibleProperty().bind(item.removable);
closeButton.onMouseClickedProperty().bind(item.removeAction);
onMouseClickedProperty().bind(item.action);
JFXButton arrowButton = new JFXButton();
arrowButton.setGraphic(SVG.arrowRight(Theme.blackFillBinding(), -1, -1));
arrowButton.onMouseClickedProperty().bind(item.action);
arrowButton.getStyleClass().add("toggle-icon4");
right.getChildren().add(arrowButton);
setCursor(Cursor.HAND);
}
}
}
/**
* Constructor for all SkinBase instances.
*
* @param control The control for which this Skin should attach to.
*/
protected InstallersPageSkin(InstallersPage control) {
super(control);
BorderPane root = new BorderPane();
root.setPadding(new Insets(16));
VBox list = new VBox(8);
root.setCenter(list);
{
HBox versionNamePane = new HBox(8);
versionNamePane.setAlignment(Pos.CENTER_LEFT);
versionNamePane.getStyleClass().add("card");
versionNamePane.setPadding(new Insets(20, 8, 20, 16));
versionNamePane.getChildren().add(new Label(i18n("archive.name")));
control.txtName.setMaxWidth(300);
versionNamePane.getChildren().add(control.txtName);
list.getChildren().add(versionNamePane);
}
InstallersPageItemSkin game = new InstallersPageItemSkin("/assets/img/grass.png", control.game, false);
InstallersPageItemSkin fabric = new InstallersPageItemSkin("/assets/img/fabric.png", control.fabric, true);
InstallersPageItemSkin forge = new InstallersPageItemSkin("/assets/img/forge.png", control.forge, true);
InstallersPageItemSkin liteLoader = new InstallersPageItemSkin("/assets/img/chicken.png", control.liteLoader, true);
InstallersPageItemSkin optiFine = new InstallersPageItemSkin("/assets/img/command.png", control.optiFine, true);
list.getChildren().addAll(game, fabric, forge, liteLoader, optiFine);
list.getChildren().forEach(node -> JFXDepthManager.setDepth(node, 1));
{
JFXButton installButton = new JFXButton(i18n("button.install"));
installButton.disableProperty().bind(control.installable.not());
installButton.getStyleClass().add("jfx-button-raised");
installButton.setButtonType(JFXButton.ButtonType.RAISED);
installButton.setPrefWidth(100);
installButton.setPrefHeight(40);
installButton.setOnMouseClicked(e -> control.onInstall());
BorderPane.setAlignment(installButton, Pos.CENTER_RIGHT);
root.setBottom(installButton);
}
getChildren().setAll(root);
}
}
} }

View File

@@ -84,6 +84,8 @@ public final class UpdateInstallerWizardProvider implements WizardProvider {
if ("game".equals(remoteVersion.getLibraryId())) { if ("game".equals(remoteVersion.getLibraryId())) {
stages.add("hmcl.install.assets"); stages.add("hmcl.install.assets");
} }
} else if (value instanceof RemoveVersionAction) {
ret = ret.thenComposeAsync(version -> dependencyManager.removeLibraryAsync(version, ((RemoveVersionAction) value).libraryId));
} }
} }
@@ -102,7 +104,7 @@ public final class UpdateInstallerWizardProvider implements WizardProvider {
String newGameVersion = ((RemoteVersion) settings.get(libraryId)).getSelfVersion(); String newGameVersion = ((RemoteVersion) settings.get(libraryId)).getSelfVersion();
controller.onNext(new AdditionalInstallersPage(newGameVersion, version, controller, profile.getRepository(), provider)); controller.onNext(new AdditionalInstallersPage(newGameVersion, version, controller, profile.getRepository(), provider));
} else { } else {
Controllers.confirmDialog(i18n("install.change_version.confirm", i18n("install.installer." + libraryId), oldLibraryVersion, ((RemoteVersion) settings.get(libraryId)).getSelfVersion()), Controllers.confirm(i18n("install.change_version.confirm", i18n("install.installer." + libraryId), oldLibraryVersion, ((RemoteVersion) settings.get(libraryId)).getSelfVersion()),
i18n("install.change_version"), controller::onFinish, controller::onCancel); i18n("install.change_version"), controller::onFinish, controller::onCancel);
} }
}); });
@@ -167,4 +169,12 @@ public final class UpdateInstallerWizardProvider implements WizardProvider {
Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageDialogPane.MessageType.ERROR, next); Controllers.dialog(StringUtils.getStackTrace(exception), i18n("install.failed"), MessageDialogPane.MessageType.ERROR, next);
} }
} }
public static class RemoveVersionAction {
private final String libraryId;
public RemoveVersionAction(String libraryId) {
this.libraryId = libraryId;
}
}
} }

View File

@@ -122,6 +122,7 @@ public class InstallerListPage extends ListPageBase<InstallerItem> {
private void doInstallOffline(File file) { private void doInstallOffline(File file) {
Task<?> task = profile.getDependency().installLibraryAsync(version, file.toPath()) Task<?> task = profile.getDependency().installLibraryAsync(version, file.toPath())
.thenComposeAsync(profile.getRepository()::save)
.thenComposeAsync(profile.getRepository().refreshVersionsAsync()); .thenComposeAsync(profile.getRepository().refreshVersionsAsync());
task.setName(i18n("install.installer.install_offline")); task.setName(i18n("install.installer.install_offline"));
TaskExecutor executor = task.executor(new TaskListener() { TaskExecutor executor = task.executor(new TaskListener() {

View File

@@ -1,93 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.*?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.image.Image?>
<?import javafx.geometry.Insets?>
<fx:root xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
type="StackPane" style="-fx-padding: 16;">
<fx:define>
<Insets fx:id="insets" left="8" />
</fx:define>
<BorderPane>
<center>
<VBox fx:id="list" spacing="8">
<HBox spacing="8" alignment="CENTER_LEFT" styleClass="card" style="-fx-padding: 20 8 20 16">
<Label text="%archive.name" />
<JFXTextField fx:id="txtName" maxWidth="300"/>
</HBox>
<BorderPane fx:id="btnGame" styleClass="card" style="-fx-padding: 8">
<left>
<ImageView>
<Image url="/assets/img/grass.png" requestedHeight="32" requestedWidth="32" smooth="true" />
</ImageView>
</left>
<center>
<Label fx:id="lblGame" BorderPane.margin="$insets" BorderPane.alignment="CENTER_LEFT" />
</center>
</BorderPane>
<BorderPane fx:id="btnFabric" styleClass="card" style="-fx-padding: 8; -fx-cursor: HAND">
<left>
<ImageView>
<Image url="/assets/img/fabric.png" requestedHeight="32" requestedWidth="32" smooth="true" />
</ImageView>
</left>
<center>
<Label fx:id="lblFabric" BorderPane.margin="$insets" BorderPane.alignment="CENTER_LEFT" />
</center>
<right>
<fx:include BorderPane.alignment="CENTER_RIGHT" source="/assets/svg/arrow-right.fxml"/>
</right>
</BorderPane>
<BorderPane fx:id="btnForge" styleClass="card" style="-fx-padding: 8; -fx-cursor: HAND">
<left>
<ImageView>
<Image url="/assets/img/forge.png" requestedHeight="32" requestedWidth="32" smooth="true" />
</ImageView>
</left>
<center>
<Label fx:id="lblForge" BorderPane.margin="$insets" BorderPane.alignment="CENTER_LEFT" />
</center>
<right>
<fx:include BorderPane.alignment="CENTER_RIGHT" source="/assets/svg/arrow-right.fxml"/>
</right>
</BorderPane>
<BorderPane fx:id="btnLiteLoader" styleClass="card" style="-fx-padding: 8; -fx-cursor: HAND">
<left>
<ImageView>
<Image url="/assets/img/chicken.png" requestedHeight="32" requestedWidth="32" smooth="true" />
</ImageView>
</left>
<center>
<Label fx:id="lblLiteLoader" BorderPane.margin="$insets" BorderPane.alignment="CENTER_LEFT" />
</center>
<right>
<fx:include BorderPane.alignment="CENTER_RIGHT" source="/assets/svg/arrow-right.fxml"/>
</right>
</BorderPane>
<BorderPane fx:id="btnOptiFine" styleClass="card" style="-fx-padding: 8; -fx-cursor: HAND">
<left>
<ImageView>
<Image url="/assets/img/command.png" requestedHeight="32" requestedWidth="32" smooth="true" />
</ImageView>
</left>
<center>
<Label fx:id="lblOptiFine" BorderPane.margin="$insets" BorderPane.alignment="CENTER_LEFT" />
</center>
<right>
<fx:include BorderPane.alignment="CENTER_RIGHT" source="/assets/svg/arrow-right.fxml"/>
</right>
</BorderPane>
</VBox>
</center>
<bottom>
<HBox alignment="CENTER_RIGHT">
<JFXButton fx:id="btnInstall" onMouseClicked="#onInstall" prefWidth="100" prefHeight="40"
buttonType="RAISED" text="%button.install" styleClass="jfx-button-raised"/>
</HBox>
</bottom>
</BorderPane>
</fx:root>

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXButton?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.*?>
<fx:root xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
type="BorderPane">
<center>
<VBox BorderPane.alignment="CENTER">
<Label fx:id="lblInstallerArtifact" style="-fx-font-size: 15;" />
<Label fx:id="lblInstallerVersion" style="-fx-font-size: 10;" />
</VBox>
</center>
<right>
<JFXButton onMouseClicked="#onDelete" styleClass="toggle-icon4" BorderPane.alignment="CENTER">
<graphic>
<fx:include source="/assets/svg/close-black.fxml"/>
</graphic>
</JFXButton>
</right>
</fx:root>

View File

@@ -132,8 +132,7 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
throw new UnsupportedLibraryInstallerException(); throw new UnsupportedLibraryInstallerException();
}) })
.thenApplyAsync(oldVersion::addPatch) .thenApplyAsync(oldVersion::addPatch);
.thenComposeAsync(repository::save);
} }
public static class UnsupportedLibraryInstallerException extends Exception { public static class UnsupportedLibraryInstallerException extends Exception {