diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java index 2c441b699..453306eb2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -71,7 +71,7 @@ public final class Accounts { } private static AuthlibInjectorServer getOrCreateAuthlibInjectorServer(String url) { - return Settings.SETTINGS.authlibInjectorServers.stream() + return ConfigHolder.CONFIG.authlibInjectorServers.stream() .filter(server -> url.equals(server.getUrl())) .findFirst() .orElseGet(() -> { @@ -85,7 +85,7 @@ public final class Accounts { LOG.log(Level.WARNING, "Failed to migrate authlib injector server " + url, e); } - Settings.SETTINGS.authlibInjectorServers.add(server); + ConfigHolder.CONFIG.authlibInjectorServers.add(server); return server; }); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java index 916e6b786..3e2727be6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -17,12 +17,21 @@ */ package org.jackhuang.hmcl.setting; +import java.io.File; import java.util.Map; import java.util.TreeMap; +import org.hildan.fxgson.creators.ObservableListCreator; +import org.hildan.fxgson.creators.ObservableMapCreator; +import org.hildan.fxgson.creators.ObservableSetCreator; +import org.hildan.fxgson.factories.JavaFxPropertyTypeAdapterFactory; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; +import org.jackhuang.hmcl.util.FileTypeAdapter; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; import javafx.beans.property.BooleanProperty; @@ -36,9 +45,25 @@ import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.ObservableMap; +import javafx.collections.ObservableSet; public final class Config implements Cloneable { + private static final Gson CONFIG_GSON = new GsonBuilder() + .registerTypeAdapter(VersionSetting.class, VersionSetting.Serializer.INSTANCE) + .registerTypeAdapter(Profile.class, Profile.Serializer.INSTANCE) + .registerTypeAdapter(File.class, FileTypeAdapter.INSTANCE) + .registerTypeAdapter(ObservableList.class, new ObservableListCreator()) + .registerTypeAdapter(ObservableSet.class, new ObservableSetCreator()) + .registerTypeAdapter(ObservableMap.class, new ObservableMapCreator()) + .registerTypeAdapterFactory(new JavaFxPropertyTypeAdapterFactory(true, true)) + .setPrettyPrinting() + .create(); + + public static Config fromJson(String json) throws JsonParseException { + return CONFIG_GSON.fromJson(json, Config.class); + } + @SerializedName("last") public final StringProperty selectedProfile = new SimpleStringProperty(""); @@ -104,8 +129,12 @@ public final class Config implements Cloneable { public final ObservableList authlibInjectorServers = FXCollections.observableArrayList(); + public String toJson() { + return CONFIG_GSON.toJson(this); + } + @Override public Config clone() { - return Settings.GSON.fromJson(Settings.GSON.toJson(this), Config.class); + return fromJson(this.toJson()); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java new file mode 100644 index 000000000..88827939f --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java @@ -0,0 +1,65 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2018 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.setting; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.jackhuang.hmcl.util.Logging.LOG; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.logging.Level; + +import com.google.gson.JsonParseException; + +public final class ConfigHolder { + + private ConfigHolder() {} + + public static final String CONFIG_FILENAME = "hmcl.json"; + public static final Path CONFIG_PATH = Paths.get(CONFIG_FILENAME).toAbsolutePath(); + public static final Config CONFIG = initSettings(); + + private static Config initSettings() { + Config config = new Config(); + if (Files.exists(CONFIG_PATH)) { + try { + Config deserialized = Config.fromJson(new String(Files.readAllBytes(CONFIG_PATH), UTF_8)); + if (deserialized == null) { + LOG.finer("Settings file is empty, use the default settings."); + } else { + config = deserialized; + } + LOG.finest("Initialized settings."); + } catch (IOException | JsonParseException e) { + LOG.log(Level.WARNING, "Something happened wrongly when load settings.", e); + } + } + return config; + } + + static void saveConfig(Config config) { + try { + Files.write(CONFIG_PATH, config.toJson().getBytes(UTF_8)); + } catch (IOException ex) { + LOG.log(Level.SEVERE, "Failed to save config", ex); + } + } + +} diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java index dc7f3f7c0..2e87dfd2c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Settings.java @@ -17,21 +17,11 @@ */ package org.jackhuang.hmcl.setting; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - import javafx.beans.property.ObjectProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; -import javafx.collections.ObservableList; -import javafx.collections.ObservableMap; -import javafx.collections.ObservableSet; import javafx.scene.text.Font; -import org.hildan.fxgson.creators.ObservableListCreator; -import org.hildan.fxgson.creators.ObservableMapCreator; -import org.hildan.fxgson.creators.ObservableSetCreator; -import org.hildan.fxgson.factories.JavaFxPropertyTypeAdapterFactory; import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.AccountFactory; @@ -43,8 +33,6 @@ import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.i18n.Locales; -import java.io.File; -import java.io.IOException; import java.net.Authenticator; import java.net.InetSocketAddress; import java.net.PasswordAuthentication; @@ -60,21 +48,6 @@ import static org.jackhuang.hmcl.util.Lang.tryCast; import static org.jackhuang.hmcl.util.Logging.LOG; public class Settings { - public static final Gson GSON = new GsonBuilder() - .registerTypeAdapter(VersionSetting.class, VersionSetting.Serializer.INSTANCE) - .registerTypeAdapter(Profile.class, Profile.Serializer.INSTANCE) - .registerTypeAdapter(File.class, FileTypeAdapter.INSTANCE) - .registerTypeAdapter(ObservableList.class, new ObservableListCreator()) - .registerTypeAdapter(ObservableSet.class, new ObservableSetCreator()) - .registerTypeAdapter(ObservableMap.class, new ObservableMapCreator()) - .registerTypeAdapterFactory(new JavaFxPropertyTypeAdapterFactory(true, true)) - .setPrettyPrinting() - .create(); - - public static final String SETTINGS_FILE_NAME = "hmcl.json"; - public static final File SETTINGS_FILE = new File(SETTINGS_FILE_NAME).getAbsoluteFile(); - - public static final Config SETTINGS = initSettings(); public static final Settings INSTANCE = new Settings(); @@ -83,11 +56,12 @@ public class Settings { private final boolean firstLaunch; private Settings() { - firstLaunch = SETTINGS.firstLaunch.get(); + firstLaunch = ConfigHolder.CONFIG.firstLaunch.get(); + ConfigHolder.CONFIG.firstLaunch.set(false); loadProxy(); - for (Iterator> iterator = SETTINGS.accounts.iterator(); iterator.hasNext();) { + for (Iterator> iterator = ConfigHolder.CONFIG.accounts.iterator(); iterator.hasNext();) { Map settings = iterator.next(); AccountFactory factory = Accounts.ACCOUNT_FACTORY.get(tryCast(settings.get("type"), String.class).orElse("")); if (factory == null) { @@ -108,7 +82,7 @@ public class Settings { accounts.put(Accounts.getAccountId(account), account); } - SETTINGS.authlibInjectorServers.addListener(onInvalidating(this::removeDanglingAuthlibInjectorAccounts)); + ConfigHolder.CONFIG.authlibInjectorServers.addListener(onInvalidating(this::removeDanglingAuthlibInjectorAccounts)); checkProfileMap(); @@ -123,51 +97,26 @@ public class Settings { Lang.ignoringException(() -> Runtime.getRuntime().addShutdownHook(new Thread(this::save))); } - private static Config initSettings() { - Config c = new Config(); - if (SETTINGS_FILE.exists()) - try { - String str = FileUtils.readText(SETTINGS_FILE); - if (StringUtils.isBlank(str)) - Logging.LOG.finer("Settings file is empty, use the default settings."); - else { - Config d = GSON.fromJson(str, Config.class); - if (d != null) - c = d; - } - Logging.LOG.finest("Initialized settings."); - } catch (Exception e) { - Logging.LOG.log(Level.WARNING, "Something happened wrongly when load settings.", e); - } - return c; - } - public void save() { - try { - SETTINGS.accounts.clear(); - SETTINGS.firstLaunch.set(false); - for (Account account : accounts.values()) { - Map storage = account.toStorage(); - storage.put("type", Accounts.getAccountType(account)); - SETTINGS.accounts.add(storage); - } - - FileUtils.writeText(SETTINGS_FILE, GSON.toJson(SETTINGS)); - } catch (IOException ex) { - Logging.LOG.log(Level.SEVERE, "Failed to save config", ex); + ConfigHolder.CONFIG.accounts.clear(); + for (Account account : accounts.values()) { + Map storage = account.toStorage(); + storage.put("type", Accounts.getAccountType(account)); + ConfigHolder.CONFIG.accounts.add(storage); } + ConfigHolder.saveConfig(ConfigHolder.CONFIG); } public boolean isFirstLaunch() { return firstLaunch; } - private final StringProperty commonPath = new ImmediateStringProperty(this, "commonPath", SETTINGS.commonDirectory.get()) { + private final StringProperty commonPath = new ImmediateStringProperty(this, "commonPath", ConfigHolder.CONFIG.commonDirectory.get()) { @Override public void invalidated() { super.invalidated(); - SETTINGS.commonDirectory.set(get()); + ConfigHolder.CONFIG.commonDirectory.set(get()); save(); } }; @@ -184,7 +133,7 @@ public class Settings { this.commonPath.set(commonPath); } - private Locales.SupportedLocale locale = Locales.getLocaleByName(SETTINGS.localization.get()); + private Locales.SupportedLocale locale = Locales.getLocaleByName(ConfigHolder.CONFIG.localization.get()); public Locales.SupportedLocale getLocale() { return locale; @@ -192,7 +141,7 @@ public class Settings { public void setLocale(Locales.SupportedLocale locale) { this.locale = locale; - SETTINGS.localization.set(Locales.getNameByLocale(locale)); + ConfigHolder.CONFIG.localization.set(Locales.getNameByLocale(locale)); save(); } @@ -202,7 +151,7 @@ public class Settings { return proxy; } - private Proxy.Type proxyType = Proxies.getProxyType(SETTINGS.proxyType.get()); + private Proxy.Type proxyType = Proxies.getProxyType(ConfigHolder.CONFIG.proxyType.get()); public Proxy.Type getProxyType() { return proxyType; @@ -210,62 +159,62 @@ public class Settings { public void setProxyType(Proxy.Type proxyType) { this.proxyType = proxyType; - SETTINGS.proxyType.set(Proxies.PROXIES.indexOf(proxyType)); + ConfigHolder.CONFIG.proxyType.set(Proxies.PROXIES.indexOf(proxyType)); save(); loadProxy(); } public String getProxyHost() { - return SETTINGS.proxyHost.get(); + return ConfigHolder.CONFIG.proxyHost.get(); } public void setProxyHost(String proxyHost) { - SETTINGS.proxyHost.set(proxyHost); + ConfigHolder.CONFIG.proxyHost.set(proxyHost); save(); } public String getProxyPort() { - return SETTINGS.proxyPort.get(); + return ConfigHolder.CONFIG.proxyPort.get(); } public void setProxyPort(String proxyPort) { - SETTINGS.proxyPort.set(proxyPort); + ConfigHolder.CONFIG.proxyPort.set(proxyPort); save(); } public String getProxyUser() { - return SETTINGS.proxyUser.get(); + return ConfigHolder.CONFIG.proxyUser.get(); } public void setProxyUser(String proxyUser) { - SETTINGS.proxyUser.set(proxyUser); + ConfigHolder.CONFIG.proxyUser.set(proxyUser); save(); } public String getProxyPass() { - return SETTINGS.proxyPass.get(); + return ConfigHolder.CONFIG.proxyPass.get(); } public void setProxyPass(String proxyPass) { - SETTINGS.proxyPass.set(proxyPass); + ConfigHolder.CONFIG.proxyPass.set(proxyPass); save(); } public boolean hasProxy() { - return SETTINGS.hasProxy.get(); + return ConfigHolder.CONFIG.hasProxy.get(); } public void setHasProxy(boolean hasProxy) { - SETTINGS.hasProxy.set(hasProxy); + ConfigHolder.CONFIG.hasProxy.set(hasProxy); save(); } public boolean hasProxyAuth() { - return SETTINGS.hasProxyAuth.get(); + return ConfigHolder.CONFIG.hasProxyAuth.get(); } public void setHasProxyAuth(boolean hasProxyAuth) { - SETTINGS.hasProxyAuth.set(hasProxyAuth); + ConfigHolder.CONFIG.hasProxyAuth.set(hasProxyAuth); save(); } @@ -296,21 +245,21 @@ public class Settings { } public Font getFont() { - return Font.font(SETTINGS.fontFamily.get(), SETTINGS.fontSize.get()); + return Font.font(ConfigHolder.CONFIG.fontFamily.get(), ConfigHolder.CONFIG.fontSize.get()); } public void setFont(Font font) { - SETTINGS.fontFamily.set(font.getFamily()); - SETTINGS.fontSize.set(font.getSize()); + ConfigHolder.CONFIG.fontFamily.set(font.getFamily()); + ConfigHolder.CONFIG.fontSize.set(font.getSize()); save(); } public int getLogLines() { - return Math.max(SETTINGS.logLines.get(), 100); + return Math.max(ConfigHolder.CONFIG.logLines.get(), 100); } public void setLogLines(int logLines) { - SETTINGS.logLines.set(logLines); + ConfigHolder.CONFIG.logLines.set(logLines); save(); } @@ -326,7 +275,7 @@ public class Settings { private void removeDanglingAuthlibInjectorAccounts() { accounts.values().stream() .filter(AuthlibInjectorAccount.class::isInstance) - .filter(it -> !SETTINGS.authlibInjectorServers.contains(((AuthlibInjectorAccount) it).getServer())) + .filter(it -> !ConfigHolder.CONFIG.authlibInjectorServers.contains(((AuthlibInjectorAccount) it).getServer())) .collect(toList()) .forEach(this::deleteAccount); } @@ -336,14 +285,14 @@ public class Settings { ****************************************/ public DownloadProvider getDownloadProvider() { - return DownloadProviders.getDownloadProvider(SETTINGS.downloadType.get()); + return DownloadProviders.getDownloadProvider(ConfigHolder.CONFIG.downloadType.get()); } public void setDownloadProvider(DownloadProvider downloadProvider) { int index = DownloadProviders.DOWNLOAD_PROVIDERS.indexOf(downloadProvider); if (index == -1) throw new IllegalArgumentException("Unknown download provider: " + downloadProvider); - SETTINGS.downloadType.set(index); + ConfigHolder.CONFIG.downloadType.set(index); save(); } @@ -351,7 +300,7 @@ public class Settings { * ACCOUNTS * ****************************************/ - private final ImmediateObjectProperty selectedAccount = new ImmediateObjectProperty(this, "selectedAccount", accounts.get(SETTINGS.selectedAccount.get())) { + private final ImmediateObjectProperty selectedAccount = new ImmediateObjectProperty(this, "selectedAccount", accounts.get(ConfigHolder.CONFIG.selectedAccount.get())) { @Override public Account get() { Account a = super.get(); @@ -373,7 +322,7 @@ public class Settings { public void invalidated() { super.invalidated(); - SETTINGS.selectedAccount.set(getValue() == null ? "" : Accounts.getAccountId(getValue())); + ConfigHolder.CONFIG.selectedAccount.set(getValue() == null ? "" : Accounts.getAccountId(getValue())); save(); } }; @@ -423,12 +372,12 @@ public class Settings { * BACKGROUND * ****************************************/ - private final ImmediateStringProperty backgroundImage = new ImmediateStringProperty(this, "backgroundImage", SETTINGS.backgroundImage.get()) { + private final ImmediateStringProperty backgroundImage = new ImmediateStringProperty(this, "backgroundImage", ConfigHolder.CONFIG.backgroundImage.get()) { @Override public void invalidated() { super.invalidated(); - SETTINGS.backgroundImage.set(get()); + ConfigHolder.CONFIG.backgroundImage.set(get()); save(); } }; @@ -445,12 +394,12 @@ public class Settings { this.backgroundImage.set(backgroundImage); } - private final ImmediateObjectProperty backgroundImageType = new ImmediateObjectProperty(this, "backgroundImageType", EnumBackgroundImage.indexOf(SETTINGS.backgroundImageType.get())) { + private final ImmediateObjectProperty backgroundImageType = new ImmediateObjectProperty(this, "backgroundImageType", EnumBackgroundImage.indexOf(ConfigHolder.CONFIG.backgroundImageType.get())) { @Override public void invalidated() { super.invalidated(); - SETTINGS.backgroundImageType.set(get().ordinal()); + ConfigHolder.CONFIG.backgroundImageType.set(get().ordinal()); save(); } }; @@ -471,12 +420,12 @@ public class Settings { * THEME * ****************************************/ - private final ImmediateObjectProperty theme = new ImmediateObjectProperty(this, "theme", Theme.getTheme(SETTINGS.theme.get()).orElse(Theme.BLUE)) { + private final ImmediateObjectProperty theme = new ImmediateObjectProperty(this, "theme", Theme.getTheme(ConfigHolder.CONFIG.theme.get()).orElse(Theme.BLUE)) { @Override public void invalidated() { super.invalidated(); - SETTINGS.theme.set(get().getName().toLowerCase()); + ConfigHolder.CONFIG.theme.set(get().getName().toLowerCase()); save(); } }; @@ -500,19 +449,19 @@ public class Settings { public Profile getSelectedProfile() { checkProfileMap(); - if (!hasProfile(SETTINGS.selectedProfile.get())) { + if (!hasProfile(ConfigHolder.CONFIG.selectedProfile.get())) { getProfileMap().keySet().stream().findFirst().ifPresent(selectedProfile -> { - SETTINGS.selectedProfile.set(selectedProfile); + ConfigHolder.CONFIG.selectedProfile.set(selectedProfile); save(); }); Schedulers.computation().schedule(this::onProfileChanged); } - return getProfile(SETTINGS.selectedProfile.get()); + return getProfile(ConfigHolder.CONFIG.selectedProfile.get()); } public void setSelectedProfile(Profile selectedProfile) { - if (hasProfile(selectedProfile.getName()) && !Objects.equals(selectedProfile.getName(), SETTINGS.selectedProfile.get())) { - SETTINGS.selectedProfile.set(selectedProfile.getName()); + if (hasProfile(selectedProfile.getName()) && !Objects.equals(selectedProfile.getName(), ConfigHolder.CONFIG.selectedProfile.get())) { + ConfigHolder.CONFIG.selectedProfile.set(selectedProfile.getName()); save(); Schedulers.computation().schedule(this::onProfileChanged); } @@ -530,7 +479,7 @@ public class Settings { } public Map getProfileMap() { - return SETTINGS.configurations; + return ConfigHolder.CONFIG.configurations; } public Collection getProfiles() { @@ -589,6 +538,6 @@ public class Settings { } public Config getRawConfig() { - return SETTINGS.clone(); + return ConfigHolder.CONFIG.clone(); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java index cc8fbb5b6..65f83b772 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAccountPane.java @@ -21,9 +21,9 @@ import com.jfoenix.concurrency.JFXUtilities; import com.jfoenix.controls.*; import javafx.beans.binding.Bindings; +import javafx.beans.property.ReadOnlyIntegerProperty; import javafx.fxml.FXML; import javafx.geometry.Pos; -import javafx.scene.Node; import javafx.scene.control.Hyperlink; import javafx.scene.control.Label; import javafx.scene.image.Image; @@ -41,6 +41,7 @@ import org.jackhuang.hmcl.auth.yggdrasil.RemoteAuthenticationException; import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount; import org.jackhuang.hmcl.game.AccountHelper; import org.jackhuang.hmcl.setting.Accounts; +import org.jackhuang.hmcl.setting.ConfigHolder; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; @@ -80,27 +81,27 @@ public class AddAccountPane extends StackPane { cboServers.setCellFactory(jfxListCellFactory(server -> new TwoLineListItem(server.getName(), server.getUrl()))); cboServers.setConverter(stringConverter(AuthlibInjectorServer::getName)); - Bindings.bindContent(cboServers.getItems(), Settings.SETTINGS.authlibInjectorServers); + Bindings.bindContent(cboServers.getItems(), ConfigHolder.CONFIG.authlibInjectorServers); cboServers.getItems().addListener(onInvalidating(this::selectDefaultServer)); selectDefaultServer(); cboType.getItems().setAll(i18n("account.methods.offline"), i18n("account.methods.yggdrasil"), i18n("account.methods.authlib_injector")); - cboType.getSelectionModel().selectedIndexProperty().addListener((a, b, newValue) -> { - txtPassword.setVisible(newValue.intValue() != 0); - lblPassword.setVisible(newValue.intValue() != 0); - cboServers.setVisible(newValue.intValue() == 2); - linkManageInjectorServers.setVisible(newValue.intValue() == 2); - lblInjectorServer.setVisible(newValue.intValue() == 2); - validateAcceptButton(); - }); cboType.getSelectionModel().select(0); - txtPassword.setOnAction(e -> onCreationAccept()); - txtUsername.setOnAction(e -> onCreationAccept()); + ReadOnlyIntegerProperty loginTypeIdProperty = cboType.getSelectionModel().selectedIndexProperty(); + + txtPassword.visibleProperty().bind(loginTypeIdProperty.isNotEqualTo(0)); + lblPassword.visibleProperty().bind(txtPassword.visibleProperty()); + + cboServers.visibleProperty().bind(loginTypeIdProperty.isEqualTo(2)); + lblInjectorServer.visibleProperty().bind(cboServers.visibleProperty()); + linkManageInjectorServers.visibleProperty().bind(cboServers.visibleProperty()); + txtUsername.getValidators().add(new Validator(i18n("input.email"), str -> !txtPassword.isVisible() || str.contains("@"))); - txtUsername.textProperty().addListener(it -> validateAcceptButton()); - txtPassword.textProperty().addListener(it -> validateAcceptButton()); + btnAccept.disableProperty().bind(Bindings.createBooleanBinding( + () -> !txtUsername.validate() || (loginTypeIdProperty.get() != 0 && !txtPassword.validate()), + txtUsername.textProperty(), txtPassword.textProperty(), loginTypeIdProperty)); } /** @@ -112,12 +113,11 @@ public class AddAccountPane extends StackPane { } } - private void validateAcceptButton() { - btnAccept.setDisable(!txtUsername.validate() || (cboType.getSelectionModel().getSelectedIndex() != 0 && !txtPassword.validate())); - } - @FXML private void onCreationAccept() { + if (btnAccept.isDisabled()) + return; + String username = txtUsername.getText(); String password = txtPassword.getText(); Object addtionalData; @@ -149,6 +149,7 @@ public class AddAccountPane extends StackPane { acceptPane.showSpinner(); lblCreationWarning.setText(""); + setDisable(true); Task.ofResult("create_account", () -> factory.create(new Selector(), username, password, addtionalData, Settings.INSTANCE.getProxy())) .finalized(Schedulers.javafx(), variables -> { @@ -161,6 +162,7 @@ public class AddAccountPane extends StackPane { } else { lblCreationWarning.setText(accountException(exception)); } + setDisable(false); acceptPane.hideSpinner(); }).start(); } @@ -176,14 +178,6 @@ public class AddAccountPane extends StackPane { Controllers.navigate(Controllers.getServersPage()); } - private void showSelector(Node node) { - getChildren().setAll(node); - } - - private void closeSelector() { - getChildren().setAll(layout); - } - private class Selector extends BorderPane implements CharacterSelector { private final AdvancedListBox listBox = new AdvancedListBox(); private final JFXButton cancel = new JFXButton(); @@ -240,7 +234,7 @@ public class AddAccountPane extends StackPane { listBox.add(accountItem); } - JFXUtilities.runInFX(() -> showSelector(this)); + JFXUtilities.runInFX(() -> Controllers.dialog(this)); try { latch.await(); @@ -248,11 +242,11 @@ public class AddAccountPane extends StackPane { if (selectedProfile == null) throw new NoSelectedCharacterException(account); - JFXUtilities.runInFX(AddAccountPane.this::closeSelector); - return selectedProfile; } catch (InterruptedException ignore) { throw new NoSelectedCharacterException(account); + } finally { + JFXUtilities.runInFX(() -> Selector.this.fireEvent(new DialogCloseEvent())); } } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAuthlibInjectorServerPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAuthlibInjectorServerPane.java index 24cf3a45d..66d4a4fa9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAuthlibInjectorServerPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AddAuthlibInjectorServerPane.java @@ -22,7 +22,7 @@ import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import java.io.IOException; import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer; -import org.jackhuang.hmcl.setting.Settings; +import org.jackhuang.hmcl.setting.ConfigHolder; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.animation.ContainerAnimations; @@ -95,6 +95,11 @@ public class AddAuthlibInjectorServerPane extends StackPane { @FXML private void onAddNext() { + if (btnAddNext.isDisabled()) + return; + + lblCreationWarning.setText(""); + String url = fixInputUrl(txtServerUrl.getText()); nextPane.showSpinner(); @@ -127,8 +132,8 @@ public class AddAuthlibInjectorServerPane extends StackPane { @FXML private void onAddFinish() { - if (!Settings.SETTINGS.authlibInjectorServers.contains(serverBeingAdded)) { - Settings.SETTINGS.authlibInjectorServers.add(serverBeingAdded); + if (!ConfigHolder.CONFIG.authlibInjectorServers.contains(serverBeingAdded)) { + ConfigHolder.CONFIG.authlibInjectorServers.add(serverBeingAdded); } fireEvent(new DialogCloseEvent()); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java index 74126b1bc..e2fae365a 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/AuthlibInjectorServersPage.java @@ -22,7 +22,7 @@ import static org.jackhuang.hmcl.ui.FXUtils.loadFXML; import static org.jackhuang.hmcl.ui.FXUtils.smoothScrolling; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; -import org.jackhuang.hmcl.setting.Settings; +import org.jackhuang.hmcl.setting.ConfigHolder; import org.jackhuang.hmcl.ui.wizard.DecoratorPage; import javafx.beans.InvalidationListener; @@ -48,15 +48,15 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa smoothScrolling(scrollPane); serversListener = observable -> updateServersList(); - Settings.SETTINGS.authlibInjectorServers.addListener(new WeakInvalidationListener(serversListener)); + ConfigHolder.CONFIG.authlibInjectorServers.addListener(new WeakInvalidationListener(serversListener)); updateServersList(); } private void updateServersList() { listPane.getChildren().setAll( - Settings.SETTINGS.authlibInjectorServers.stream() + ConfigHolder.CONFIG.authlibInjectorServers.stream() .map(server -> new AuthlibInjectorServerItem(server, - item -> Settings.SETTINGS.authlibInjectorServers.remove(item.getServer()))) + item -> ConfigHolder.CONFIG.authlibInjectorServers.remove(item.getServer()))) .collect(toList())); } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java index 0b4316d57..9e8730110 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ExportWizardProvider.java @@ -23,6 +23,7 @@ import org.jackhuang.hmcl.game.HMCLModpackExportTask; import org.jackhuang.hmcl.game.HMCLModpackManager; import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.setting.Config; +import org.jackhuang.hmcl.setting.ConfigHolder; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.setting.Settings; import org.jackhuang.hmcl.task.Task; @@ -93,7 +94,7 @@ public final class ExportWizardProvider implements WizardProvider { config.logLines.set(100); config.configurations.clear(); - zip.putTextFile(Settings.GSON.toJson(config), Settings.SETTINGS_FILE_NAME); + zip.putTextFile(config.toJson(), ConfigHolder.CONFIG_FILENAME); zip.putFile(tempModpack, "modpack.zip"); File bg = new File("bg").getAbsoluteFile(); diff --git a/HMCL/src/main/resources/assets/fxml/account-add.fxml b/HMCL/src/main/resources/assets/fxml/account-add.fxml index 2567bd210..bf0e6313e 100644 --- a/HMCL/src/main/resources/assets/fxml/account-add.fxml +++ b/HMCL/src/main/resources/assets/fxml/account-add.fxml @@ -37,7 +37,7 @@