存储AuthlibInjectorServerInfo对象而不是url字符串
This commit is contained in:
@@ -17,11 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.setting;
|
package org.jackhuang.hmcl.setting;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.Launcher;
|
import org.jackhuang.hmcl.Launcher;
|
||||||
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServerInfo;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
@@ -35,7 +36,6 @@ import javafx.beans.property.StringProperty;
|
|||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.collections.ObservableMap;
|
import javafx.collections.ObservableMap;
|
||||||
import javafx.collections.ObservableSet;
|
|
||||||
|
|
||||||
public final class Config implements Cloneable {
|
public final class Config implements Cloneable {
|
||||||
|
|
||||||
@@ -99,8 +99,7 @@ public final class Config implements Cloneable {
|
|||||||
@SerializedName("logLines")
|
@SerializedName("logLines")
|
||||||
public final IntegerProperty logLines = new SimpleIntegerProperty(100);
|
public final IntegerProperty logLines = new SimpleIntegerProperty(100);
|
||||||
|
|
||||||
@SerializedName("authlibInjectorServerURLs")
|
public final ObservableList<AuthlibInjectorServerInfo> authlibInjectorServers = FXCollections.observableArrayList();
|
||||||
public final ObservableSet<String> authlibInjectorServerURLs = FXCollections.observableSet(new HashSet<>());
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Config clone() {
|
public Config clone() {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jackhuang.hmcl.setting;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.ObjectProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
@@ -35,6 +36,7 @@ import org.jackhuang.hmcl.Launcher;
|
|||||||
import org.jackhuang.hmcl.auth.Account;
|
import org.jackhuang.hmcl.auth.Account;
|
||||||
import org.jackhuang.hmcl.auth.AccountFactory;
|
import org.jackhuang.hmcl.auth.AccountFactory;
|
||||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
||||||
|
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServerInfo;
|
||||||
import org.jackhuang.hmcl.download.DownloadProvider;
|
import org.jackhuang.hmcl.download.DownloadProvider;
|
||||||
import org.jackhuang.hmcl.event.*;
|
import org.jackhuang.hmcl.event.*;
|
||||||
import org.jackhuang.hmcl.task.Schedulers;
|
import org.jackhuang.hmcl.task.Schedulers;
|
||||||
@@ -51,6 +53,9 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
|
import static java.util.stream.Collectors.toSet;
|
||||||
|
import static org.jackhuang.hmcl.ui.FXUtils.onInvalidating;
|
||||||
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
import static org.jackhuang.hmcl.util.Lang.tryCast;
|
||||||
import static org.jackhuang.hmcl.util.Logging.LOG;
|
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||||
|
|
||||||
@@ -71,7 +76,8 @@ public class Settings {
|
|||||||
|
|
||||||
public static final Settings INSTANCE = new Settings();
|
public static final Settings INSTANCE = new Settings();
|
||||||
|
|
||||||
private final Config SETTINGS = initSettings();
|
// TODO: another way to access this property aside from Settings.INSTANCE.SETTINGS
|
||||||
|
public final Config SETTINGS = initSettings();
|
||||||
|
|
||||||
private final Map<String, Account> accounts = new ConcurrentHashMap<>();
|
private final Map<String, Account> accounts = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@@ -99,7 +105,10 @@ public class Settings {
|
|||||||
accounts.put(Accounts.getAccountId(account), account);
|
accounts.put(Accounts.getAccountId(account), account);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAuthlibInjectorAccounts();
|
migrateAuthlibInjectorServers();
|
||||||
|
|
||||||
|
SETTINGS.authlibInjectorServers.addListener(onInvalidating(this::removeDanglingAuthlibInjectorAccounts));
|
||||||
|
|
||||||
checkProfileMap();
|
checkProfileMap();
|
||||||
|
|
||||||
save();
|
save();
|
||||||
@@ -303,30 +312,50 @@ public class Settings {
|
|||||||
* AUTHLIB INJECTORS *
|
* AUTHLIB INJECTORS *
|
||||||
****************************************/
|
****************************************/
|
||||||
|
|
||||||
public Set<String> getAuthlibInjectorServerURLs() {
|
private Set<String> getAuthlibInjectorServerUrls() {
|
||||||
return SETTINGS.authlibInjectorServerURLs;
|
return SETTINGS.authlibInjectorServers.stream()
|
||||||
|
.map(AuthlibInjectorServerInfo::getServerIp)
|
||||||
|
.collect(toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAuthlibInjectorServerURL(String serverURL) {
|
/**
|
||||||
SETTINGS.authlibInjectorServerURLs.remove(serverURL);
|
* The {@code serverBaseURL} specified in {@link AuthlibInjectorAccount} may not have an associated
|
||||||
|
* {@link AuthlibInjectorServerInfo} in {@link Config#authlibInjectorServers},
|
||||||
checkAuthlibInjectorAccounts();
|
* which usually happens when migrating data from an older version.
|
||||||
save();
|
* This method adds the missing servers to {@link Config#authlibInjectorServers}.
|
||||||
|
*/
|
||||||
|
private void migrateAuthlibInjectorServers() {
|
||||||
|
Set<String> existentServerUrls = getAuthlibInjectorServerUrls();
|
||||||
|
accounts.values().stream()
|
||||||
|
.filter(AuthlibInjectorAccount.class::isInstance)
|
||||||
|
.map(it -> ((AuthlibInjectorAccount) it).getServerBaseURL())
|
||||||
|
.distinct()
|
||||||
|
.filter(it -> !existentServerUrls.contains(it))
|
||||||
|
.forEach(url -> {
|
||||||
|
String serverName;
|
||||||
|
try {
|
||||||
|
serverName = Accounts.getAuthlibInjectorServerName(url);
|
||||||
|
Logging.LOG.info("Migrated authlib injector server [" + url + "], name=[" + serverName + "]");
|
||||||
|
} catch (Exception e) {
|
||||||
|
serverName = url;
|
||||||
|
Logging.LOG.log(Level.WARNING, "Failed to migrate authlib injector server [" + url + "]", e);
|
||||||
|
}
|
||||||
|
SETTINGS.authlibInjectorServers.add(new AuthlibInjectorServerInfo(url, serverName));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAuthlibInjectorServerURL(String serverURL) {
|
/**
|
||||||
SETTINGS.authlibInjectorServerURLs.add(serverURL);
|
* After an {@link AuthlibInjectorServerInfo} is removed, the associated accounts should also be removed.
|
||||||
save();
|
* This method performs a check and removes the dangling accounts.
|
||||||
}
|
* Don't call this before {@link #migrateAuthlibInjectorServers()} is called, otherwise old data would be lost.
|
||||||
|
*/
|
||||||
private void checkAuthlibInjectorAccounts() {
|
private void removeDanglingAuthlibInjectorAccounts() {
|
||||||
for (Account account : getAccounts()) {
|
Set<String> currentServerUrls = getAuthlibInjectorServerUrls();
|
||||||
if (account instanceof AuthlibInjectorAccount) {
|
accounts.values().stream()
|
||||||
AuthlibInjectorAccount injectorAccount = (AuthlibInjectorAccount) account;
|
.filter(AuthlibInjectorAccount.class::isInstance)
|
||||||
if (!SETTINGS.authlibInjectorServerURLs.contains(injectorAccount.getServerBaseURL()))
|
.filter(it -> !currentServerUrls.contains(((AuthlibInjectorAccount) it).getServerBaseURL()))
|
||||||
deleteAccount(account);
|
.collect(toList())
|
||||||
}
|
.forEach(this::deleteAccount);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************
|
/****************************************
|
||||||
|
|||||||
@@ -49,14 +49,13 @@ import org.jackhuang.hmcl.ui.construct.Validator;
|
|||||||
import org.jackhuang.hmcl.util.Constants;
|
import org.jackhuang.hmcl.util.Constants;
|
||||||
import org.jackhuang.hmcl.util.Logging;
|
import org.jackhuang.hmcl.util.Logging;
|
||||||
|
|
||||||
import java.util.Collection;
|
import static java.util.stream.Collectors.toList;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class AddAccountPane extends StackPane {
|
public class AddAccountPane extends StackPane {
|
||||||
|
|
||||||
@@ -96,10 +95,6 @@ public class AddAccountPane extends StackPane {
|
|||||||
});
|
});
|
||||||
cboType.getSelectionModel().select(0);
|
cboType.getSelectionModel().select(0);
|
||||||
|
|
||||||
// These two lines can eliminate black, don't know why.
|
|
||||||
cboServers.getItems().setAll(new TwoLineListItem("", ""));
|
|
||||||
cboServers.getSelectionModel().select(0);
|
|
||||||
|
|
||||||
txtPassword.setOnAction(e -> onCreationAccept());
|
txtPassword.setOnAction(e -> onCreationAccept());
|
||||||
txtUsername.setOnAction(e -> onCreationAccept());
|
txtUsername.setOnAction(e -> onCreationAccept());
|
||||||
txtUsername.getValidators().add(new Validator(Launcher.i18n("input.email"), str -> !txtPassword.isVisible() || str.contains("@")));
|
txtUsername.getValidators().add(new Validator(Launcher.i18n("input.email"), str -> !txtPassword.isVisible() || str.contains("@")));
|
||||||
@@ -113,21 +108,12 @@ public class AddAccountPane extends StackPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadServers() {
|
private void loadServers() {
|
||||||
Task.ofResult("list", () -> Settings.INSTANCE.getAuthlibInjectorServerURLs().parallelStream()
|
cboServers.getItems().setAll(
|
||||||
.flatMap(serverURL -> {
|
Settings.INSTANCE.SETTINGS.authlibInjectorServers.stream()
|
||||||
try {
|
.map(server -> new TwoLineListItem(server.getServerName(), server.getServerIp()))
|
||||||
return Stream.of(new TwoLineListItem(Accounts.getAuthlibInjectorServerName(serverURL), serverURL));
|
.collect(toList()));
|
||||||
} catch (Exception e) {
|
if (!cboServers.getItems().isEmpty())
|
||||||
Logging.LOG.log(Level.WARNING, "Authlib-injector server root " + serverURL + " cannot be recognized.", e);
|
cboServers.getSelectionModel().select(0);
|
||||||
return Stream.empty();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList()))
|
|
||||||
.subscribe(Task.of(Schedulers.javafx(), variables -> {
|
|
||||||
cboServers.getItems().setAll(variables.<Collection<TwoLineListItem>>get("list"));
|
|
||||||
if (!cboServers.getItems().isEmpty())
|
|
||||||
cboServers.getSelectionModel().select(0);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showSpinner() {
|
private void showSpinner() {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import com.jfoenix.controls.*;
|
|||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
import javafx.beans.property.StringProperty;
|
import javafx.beans.property.StringProperty;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.Node;
|
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.control.ScrollPane;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
@@ -18,13 +17,9 @@ import org.jackhuang.hmcl.task.Task;
|
|||||||
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
|
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
|
||||||
import org.jackhuang.hmcl.ui.animation.TransitionHandler;
|
import org.jackhuang.hmcl.ui.animation.TransitionHandler;
|
||||||
import org.jackhuang.hmcl.ui.wizard.DecoratorPage;
|
import org.jackhuang.hmcl.ui.wizard.DecoratorPage;
|
||||||
import org.jackhuang.hmcl.util.Logging;
|
|
||||||
import org.jackhuang.hmcl.util.NetworkUtils;
|
import org.jackhuang.hmcl.util.NetworkUtils;
|
||||||
|
|
||||||
import java.util.Collection;
|
import static java.util.stream.Collectors.toList;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
public class AuthlibInjectorServersPage extends StackPane implements DecoratorPage {
|
public class AuthlibInjectorServersPage extends StackPane implements DecoratorPage {
|
||||||
private final StringProperty title = new SimpleStringProperty(this, "title", Launcher.i18n("account.injector.server"));
|
private final StringProperty title = new SimpleStringProperty(this, "title", Launcher.i18n("account.injector.server"));
|
||||||
@@ -64,7 +59,7 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void removeServer(AuthlibInjectorServerItem item) {
|
private void removeServer(AuthlibInjectorServerItem item) {
|
||||||
Settings.INSTANCE.removeAuthlibInjectorServerURL(item.getInfo().getServerIp());
|
Settings.INSTANCE.SETTINGS.authlibInjectorServers.remove(item.getInfo());
|
||||||
loading();
|
loading();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,27 +67,20 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa
|
|||||||
getChildren().remove(contentPane);
|
getChildren().remove(contentPane);
|
||||||
spinner.setVisible(true);
|
spinner.setVisible(true);
|
||||||
|
|
||||||
Task.ofResult("list", () -> Settings.INSTANCE.getAuthlibInjectorServerURLs().parallelStream()
|
listPane.getChildren().setAll(
|
||||||
.flatMap(serverURL -> {
|
Settings.INSTANCE.SETTINGS.authlibInjectorServers.stream()
|
||||||
try {
|
.map(server -> new AuthlibInjectorServerItem(server, this::removeServer))
|
||||||
return Stream.of(new AuthlibInjectorServerItem(new AuthlibInjectorServerInfo(serverURL, Accounts.getAuthlibInjectorServerName(serverURL)), this::removeServer));
|
.collect(toList()));
|
||||||
} catch (Exception e) {
|
|
||||||
Logging.LOG.log(Level.WARNING, "Authlib-injector server root " + serverURL + " cannot be recognized.", e);
|
// TODO: remove spinner
|
||||||
return Stream.empty();
|
loadingCompleted();
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect(Collectors.toList()))
|
|
||||||
.subscribe(Task.of(Schedulers.javafx(), variables -> {
|
|
||||||
listPane.getChildren().setAll(variables.<Collection<? extends Node>>get("list"));
|
|
||||||
loadingCompleted();
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadingCompleted() {
|
private void loadingCompleted() {
|
||||||
getChildren().add(contentPane);
|
getChildren().add(contentPane);
|
||||||
spinner.setVisible(false);
|
spinner.setVisible(false);
|
||||||
|
|
||||||
if (Settings.INSTANCE.getAuthlibInjectorServerURLs().isEmpty())
|
if (Settings.INSTANCE.SETTINGS.authlibInjectorServers.isEmpty())
|
||||||
onAdd();
|
onAdd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +132,9 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void onAddFinish() {
|
private void onAddFinish() {
|
||||||
Settings.INSTANCE.addAuthlibInjectorServerURL(serverBeingAdded.getServerIp());
|
if (!Settings.INSTANCE.SETTINGS.authlibInjectorServers.contains(serverBeingAdded)) {
|
||||||
|
Settings.INSTANCE.SETTINGS.authlibInjectorServers.add(serverBeingAdded);
|
||||||
|
}
|
||||||
loading();
|
loading();
|
||||||
dialog.close();
|
dialog.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import javafx.animation.Interpolator;
|
|||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.InvalidationListener;
|
||||||
import javafx.beans.property.Property;
|
import javafx.beans.property.Property;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
@@ -67,6 +68,10 @@ public final class FXUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static InvalidationListener onInvalidating(Runnable action) {
|
||||||
|
return arg -> action.run();
|
||||||
|
}
|
||||||
|
|
||||||
public static <T> void onChange(ObservableValue<T> value, Consumer<T> consumer) {
|
public static <T> void onChange(ObservableValue<T> value, Consumer<T> consumer) {
|
||||||
value.addListener((a, b, c) -> consumer.accept(c));
|
value.addListener((a, b, c) -> consumer.accept(c));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,4 +33,19 @@ public class AuthlibInjectorServerInfo {
|
|||||||
public String getServerName() {
|
public String getServerName() {
|
||||||
return serverName;
|
return serverName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return serverIp.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == this)
|
||||||
|
return true;
|
||||||
|
if (!(obj instanceof AuthlibInjectorServerInfo))
|
||||||
|
return false;
|
||||||
|
AuthlibInjectorServerInfo another = (AuthlibInjectorServerInfo) obj;
|
||||||
|
return this.serverIp.equals(another.serverIp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user