feat: move auth servers to sidebar

This commit is contained in:
Haowei Wen
2021-09-06 10:53:22 +08:00
parent d521d10a85
commit 56bd2e0d95
10 changed files with 109 additions and 231 deletions

0
HMCL/.attach_pid426462 Normal file
View File

View File

@@ -36,7 +36,6 @@ import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.task.TaskExecutor;
import org.jackhuang.hmcl.ui.account.AccountListPage;
import org.jackhuang.hmcl.ui.account.AuthlibInjectorServersPage;
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
import org.jackhuang.hmcl.ui.construct.InputDialogPane;
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
@@ -85,7 +84,6 @@ public final class Controllers {
});
return gameListPage;
});
private static AuthlibInjectorServersPage serversPage = null;
private static Lazy<RootPage> rootPage = new Lazy<>(RootPage::new);
private static DecoratorController decorator;
private static Lazy<ModDownloadListPage> modDownloadListPage = new Lazy<>(() -> {
@@ -100,6 +98,7 @@ public final class Controllers {
AccountListPage accountListPage = new AccountListPage();
accountListPage.selectedAccountProperty().bindBidirectional(Accounts.selectedAccountProperty());
accountListPage.accountsProperty().bindContent(Accounts.accountsProperty());
accountListPage.authServersProperty().bindContentBidirectional(config().getAuthlibInjectorServers());
return accountListPage;
});
private static Lazy<MultiplayerPage> multiplayerPage = new Lazy<>(MultiplayerPage::new);
@@ -131,13 +130,6 @@ public final class Controllers {
return rootPage.get();
}
// FXThread
public static AuthlibInjectorServersPage getServersPage() {
if (serversPage == null)
serversPage = new AuthlibInjectorServersPage();
return serversPage;
}
// FXThread
public static ModDownloadListPage getModpackDownloadListPage() {
return modDownloadListPage.get();
@@ -287,7 +279,6 @@ public final class Controllers {
public static void shutdown() {
rootPage = null;
versionPage = null;
serversPage = null;
gameListPage = null;
settingsPage = null;
modDownloadListPage = null;

View File

@@ -438,4 +438,10 @@ public final class SVG {
"M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z",
fill, width, height);
}
public static Node server(ObjectBinding<? extends Paint> fill, double width, double height) {
return createSVGPath(
"M13,19H14A1,1 0 0,1 15,20H22V22H15A1,1 0 0,1 14,23H10A1,1 0 0,1 9,22H2V20H9A1,1 0 0,1 10,19H11V17H4A1,1 0 0,1 3,16V12A1,1 0 0,1 4,11H20A1,1 0 0,1 21,12V16A1,1 0 0,1 20,17H13V19M4,3H20A1,1 0 0,1 21,4V8A1,1 0 0,1 20,9H4A1,1 0 0,1 3,8V4A1,1 0 0,1 4,3M9,7H10V5H9V7M9,15H10V13H9V15M5,5V7H7V5H5M5,13V15H7V13H5Z",
fill, width, height);
}
}

View File

@@ -17,24 +17,31 @@
*/
package org.jackhuang.hmcl.ui.account;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXScrollPane;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Skin;
import javafx.scene.control.SkinBase;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.setting.Accounts;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.ui.ListPageBase;
import org.jackhuang.hmcl.ui.SVG;
import org.jackhuang.hmcl.ui.construct.AdvancedListBox;
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
import org.jackhuang.hmcl.ui.construct.ClassTitle;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.util.i18n.I18n;
import org.jackhuang.hmcl.util.javafx.BindingMapping;
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
import static org.jackhuang.hmcl.ui.versions.VersionPage.wrap;
@@ -44,6 +51,7 @@ import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.createSelectedIt
public class AccountListPage extends ListPageBase<AccountListItem> implements DecoratorPage {
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(State.fromTitle(i18n("account.manage"), -1));
private final ListProperty<Account> accounts = new SimpleListProperty<>(this, "accounts", FXCollections.observableArrayList());
private final ListProperty<AuthlibInjectorServer> authServers = new SimpleListProperty<>(this, "authServers", FXCollections.observableArrayList());
private final ObjectProperty<Account> selectedAccount;
public AccountListPage() {
@@ -64,50 +72,98 @@ public class AccountListPage extends ListPageBase<AccountListItem> implements De
return state.getReadOnlyProperty();
}
public ListProperty<AuthlibInjectorServer> authServersProperty() {
return authServers;
}
@Override
protected Skin<?> createDefaultSkin() {
return new AccountListPageSkin(this);
}
private static class AccountListPageSkin extends SkinBase<AccountListPage> {
private final ObservableList<AdvancedListItem> authServerItems;
public AccountListPageSkin(AccountListPage skinnable) {
super(skinnable);
BorderPane root = new BorderPane();
{
AdvancedListBox sideBar = new AdvancedListBox()
.startCategory(i18n("account.create"))
.addNavigationDrawerItem(settingsItem -> {
settingsItem.setTitle(i18n("account.methods.offline"));
settingsItem.setLeftGraphic(wrap(SVG.account(null, 20, 20)));
settingsItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_OFFLINE)));
})
.addNavigationDrawerItem(settingsItem -> {
settingsItem.setTitle(i18n("account.methods.yggdrasil"));
settingsItem.setLeftGraphic(wrap(SVG.mojang(null, 20, 20)));
settingsItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_MOJANG)));
})
.addNavigationDrawerItem(settingsItem -> {
settingsItem.setTitle(i18n("account.methods.microsoft"));
settingsItem.setLeftGraphic(wrap(SVG.microsoft(null, 20, 20)));
settingsItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_MICROSOFT)));
})
.addNavigationDrawerItem(settingsItem -> {
settingsItem.setTitle(i18n("account.methods.authlib_injector"));
if (I18n.hasKey("account.methods.authlib_injector.subtitle")) {
settingsItem.setSubtitle(i18n("account.methods.authlib_injector.subtitle"));
}
settingsItem.setLeftGraphic(wrap(SVG.gear(null, 20, 20)));
settingsItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_AUTHLIB_INJECTOR)));
})
.addNavigationDrawerItem(settingsItem -> {
settingsItem.setTitle(i18n("account.create"));
settingsItem.setLeftGraphic(wrap(SVG.plus(null, 20, 20)));
settingsItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane()));
});
FXUtils.setLimitWidth(sideBar, 200);
root.setLeft(sideBar);
VBox left = new VBox();
left.getStyleClass().add("advanced-list-box-content");
left.getChildren().add(new ClassTitle(i18n("account.create")));
AdvancedListItem offlineItem = new AdvancedListItem();
offlineItem.getStyleClass().add("navigation-drawer-item");
offlineItem.setActionButtonVisible(false);
offlineItem.setTitle(i18n("account.methods.offline"));
offlineItem.setLeftGraphic(wrap(SVG.account(Theme.blackFillBinding(), 24, 24)));
offlineItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_OFFLINE)));
left.getChildren().add(offlineItem);
AdvancedListItem mojangItem = new AdvancedListItem();
mojangItem.getStyleClass().add("navigation-drawer-item");
mojangItem.setActionButtonVisible(false);
mojangItem.setTitle(i18n("account.methods.yggdrasil"));
mojangItem.setLeftGraphic(wrap(SVG.mojang(Theme.blackFillBinding(), 24, 24)));
mojangItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_MOJANG)));
left.getChildren().add(mojangItem);
AdvancedListItem microsoftItem = new AdvancedListItem();
microsoftItem.getStyleClass().add("navigation-drawer-item");
microsoftItem.setActionButtonVisible(false);
microsoftItem.setTitle(i18n("account.methods.microsoft"));
microsoftItem.setLeftGraphic(wrap(SVG.microsoft(Theme.blackFillBinding(), 24, 24)));
microsoftItem.setOnAction(e -> Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_MICROSOFT)));
left.getChildren().add(microsoftItem);
left.getChildren().add(new ClassTitle(i18n("account.methods.authlib_injector")));
{
VBox wrapper = new VBox();
FXUtils.setLimitWidth(wrapper, 200);
VBox box = new VBox();
authServerItems = MappedObservableList.create(skinnable.authServersProperty(), server -> {
AdvancedListItem item = new AdvancedListItem();
item.getStyleClass().add("navigation-drawer-item");
item.setLeftGraphic(SVG.server(null, 20, 20));
item.setOnAction(e -> Controllers.dialog(new CreateAccountPane(server)));
JFXButton btnRemove = new JFXButton();
btnRemove.setOnAction(e -> skinnable.authServersProperty().remove(server));
btnRemove.getStyleClass().add("toggle-icon4");
btnRemove.setGraphic(SVG.close(Theme.blackFillBinding(), 14, 14));
item.setRightGraphic(btnRemove);
ObservableValue<String> title = BindingMapping.of(server, AuthlibInjectorServer::getName);
String url = server.getUrl();
item.titleProperty().bind(title);
item.subtitleProperty().set(url);
Tooltip tooltip = new Tooltip();
tooltip.textProperty().bind(Bindings.format("%s (%s)", title, url));
FXUtils.installFastTooltip(item, tooltip);
return item;
});
Bindings.bindContent(box.getChildren(), authServerItems);
AdvancedListItem addAuthServerItem = new AdvancedListItem();
addAuthServerItem.getStyleClass().add("navigation-drawer-item");
addAuthServerItem.setTitle(i18n("account.injector.add"));
addAuthServerItem.setActionButtonVisible(false);
addAuthServerItem.setLeftGraphic(SVG.plusCircleOutline(Theme.blackFillBinding(), 24, 24));
addAuthServerItem.setOnAction(e -> Controllers.dialog(new AddAuthlibInjectorServerPane()));
wrapper.getChildren().addAll(box, addAuthServerItem);
left.getChildren().add(new ScrollPane(wrapper));
}
FXUtils.setLimitWidth(left, 200);
root.setLeft(left);
}
ScrollPane scrollPane = new ScrollPane();

View File

@@ -1,67 +0,0 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2020 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.account;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.effects.JFXDepthManager;
import javafx.beans.binding.Bindings;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.SVG;
import java.util.function.Consumer;
public final class AuthlibInjectorServerItem extends BorderPane {
private final AuthlibInjectorServer server;
private final Label lblServerName = new Label();
private final Label lblServerUrl = new Label();
public AuthlibInjectorServerItem(AuthlibInjectorServer server, Consumer<AuthlibInjectorServerItem> deleteCallback) {
this.server = server;
lblServerName.setStyle("-fx-font-size: 15;");
lblServerUrl.setStyle("-fx-font-size: 10;");
VBox center = new VBox();
BorderPane.setAlignment(center, Pos.CENTER);
center.getChildren().addAll(lblServerName, lblServerUrl);
setCenter(center);
JFXButton right = new JFXButton();
right.setOnMouseClicked(e -> deleteCallback.accept(this));
right.getStyleClass().add("toggle-icon4");
BorderPane.setAlignment(right, Pos.CENTER);
right.setGraphic(SVG.close(Theme.blackFillBinding(), 15, 15));
setRight(right);
setStyle("-fx-background-radius: 2; -fx-background-color: white; -fx-padding: 8;");
JFXDepthManager.setDepth(this, 1);
lblServerName.textProperty().bind(Bindings.createStringBinding(server::getName, server));
lblServerUrl.setText(server.getUrl());
}
public AuthlibInjectorServer getServer() {
return server;
}
}

View File

@@ -1,56 +0,0 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2020 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.account;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.ObservableList;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
import org.jackhuang.hmcl.ui.Controllers;
import org.jackhuang.hmcl.ui.ListPage;
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class AuthlibInjectorServersPage extends ListPage<AuthlibInjectorServerItem> implements DecoratorPage {
private final ReadOnlyObjectWrapper<State> state = new ReadOnlyObjectWrapper<>(State.fromTitle(i18n("account.injector.manage.title")));
private final ObservableList<AuthlibInjectorServerItem> serverItems;
public AuthlibInjectorServersPage() {
serverItems = MappedObservableList.create(config().getAuthlibInjectorServers(), this::createServerItem);
Bindings.bindContent(itemsProperty(), serverItems);
}
private AuthlibInjectorServerItem createServerItem(AuthlibInjectorServer server) {
return new AuthlibInjectorServerItem(server,
item -> config().getAuthlibInjectorServers().remove(item.getServer()));
}
@Override
public void add() {
Controllers.dialog(new AddAuthlibInjectorServerPane());
}
@Override
public ReadOnlyObjectWrapper<State> stateProperty() {
return state;
}
}

View File

@@ -78,7 +78,7 @@ public class CreateAccountPane extends JFXDialogLayout {
private TaskExecutor loginTask;
public CreateAccountPane() {
this(null);
this((AccountFactory<?>) null);
}
public CreateAccountPane(AccountFactory<?> factory) {
@@ -170,6 +170,11 @@ public class CreateAccountPane extends JFXDialogLayout {
setPrefWidth(560);
}
public CreateAccountPane(AuthlibInjectorServer authserver) {
this(Accounts.FACTORY_AUTHLIB_INJECTOR);
((AccountDetailsInputPane) detailsPane).selectAuthServer(authserver);
}
private void onAccept() {
spinner.showSpinner();
lblErrorMessage.setText("");
@@ -322,15 +327,7 @@ public class CreateAccountPane extends JFXDialogLayout {
Controllers.dialog(new AddAuthlibInjectorServerPane());
});
JFXButton btnManageServers = new JFXButton();
btnManageServers.setGraphic(SVG.gear(null, 20, 20));
btnManageServers.getStyleClass().add("toggle-icon4");
btnManageServers.setOnAction(e -> {
fireEvent(new DialogCloseEvent());
Controllers.navigate(Controllers.getServersPage());
});
HBox boxServers = new HBox(cboServers, linksContainer, btnAddServer, btnManageServers);
HBox boxServers = new HBox(cboServers, linksContainer, btnAddServer);
add(boxServers, 1, rowIndex);
rowIndex++;
@@ -422,6 +419,10 @@ public class CreateAccountPane extends JFXDialogLayout {
public BooleanBinding validProperty() {
return valid;
}
public void selectAuthServer(AuthlibInjectorServer authserver) {
cboServers.getSelectionModel().select(authserver);
}
}
private static class DialogCharacterSelector extends BorderPane implements CharacterSelector {

View File

@@ -62,7 +62,6 @@ public class AdvancedListItemSkin extends SkinBase<AdvancedListItem> {
HBox right = new HBox();
right.setAlignment(Pos.CENTER);
right.setMouseTransparent(true);
right.getStyleClass().add("toggle-icon4");
FXUtils.setLimitWidth(right, 40);
FXUtils.onChangeAndOperate(skinnable.rightGraphicProperty(),

View File

@@ -1,52 +0,0 @@
/*
* Hello Minecraft! Launcher
* Copyright (C) 2020 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.profile;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import org.jackhuang.hmcl.setting.Profile;
import org.jackhuang.hmcl.setting.Profiles;
import org.jackhuang.hmcl.setting.Theme;
import org.jackhuang.hmcl.ui.SVG;
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
import static org.jackhuang.hmcl.ui.FXUtils.newImage;
public class ProfileAdvancedListItem extends AdvancedListItem {
private ObjectProperty<Profile> profile = new SimpleObjectProperty<Profile>() {
@Override
protected void invalidated() {
Profile profile = get();
if (profile == null) {
} else {
setTitle(Profiles.getProfileDisplayName(profile));
setSubtitle(profile.getGameDir().toString());
}
}
};
public ProfileAdvancedListItem() {
setLeftGraphic(createImageView(newImage("/assets/img/craft_table.png")).getKey());
setRightGraphic(SVG.viewList(Theme.blackFillBinding(), -1, -1));
}
public ObjectProperty<Profile> profileProperty() {
return profile;
}
}

View File

@@ -162,7 +162,7 @@
}
.advanced-list-box-content {
-fx-padding: 12 0 12 0;
-fx-padding: 12 0 0 0;
-fx-spacing: 0;
}