存储AuthlibInjectorServerInfo对象而不是url字符串

This commit is contained in:
yushijinhun
2018-06-16 19:15:16 +08:00
parent bfbc4613b9
commit 22732fee6a
6 changed files with 95 additions and 71 deletions

View File

@@ -17,11 +17,12 @@
*/
package org.jackhuang.hmcl.setting;
import java.util.HashSet;
import java.util.Map;
import java.util.TreeMap;
import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServerInfo;
import com.google.gson.annotations.SerializedName;
import javafx.beans.property.BooleanProperty;
@@ -35,7 +36,6 @@ 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 {
@@ -99,8 +99,7 @@ public final class Config implements Cloneable {
@SerializedName("logLines")
public final IntegerProperty logLines = new SimpleIntegerProperty(100);
@SerializedName("authlibInjectorServerURLs")
public final ObservableSet<String> authlibInjectorServerURLs = FXCollections.observableSet(new HashSet<>());
public final ObservableList<AuthlibInjectorServerInfo> authlibInjectorServers = FXCollections.observableArrayList();
@Override
public Config clone() {

View File

@@ -19,6 +19,7 @@ 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;
@@ -35,6 +36,7 @@ import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.AccountFactory;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServerInfo;
import org.jackhuang.hmcl.download.DownloadProvider;
import org.jackhuang.hmcl.event.*;
import org.jackhuang.hmcl.task.Schedulers;
@@ -51,6 +53,9 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
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.Logging.LOG;
@@ -71,7 +76,8 @@ public class 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<>();
@@ -99,7 +105,10 @@ public class Settings {
accounts.put(Accounts.getAccountId(account), account);
}
checkAuthlibInjectorAccounts();
migrateAuthlibInjectorServers();
SETTINGS.authlibInjectorServers.addListener(onInvalidating(this::removeDanglingAuthlibInjectorAccounts));
checkProfileMap();
save();
@@ -303,30 +312,50 @@ public class Settings {
* AUTHLIB INJECTORS *
****************************************/
public Set<String> getAuthlibInjectorServerURLs() {
return SETTINGS.authlibInjectorServerURLs;
private Set<String> getAuthlibInjectorServerUrls() {
return SETTINGS.authlibInjectorServers.stream()
.map(AuthlibInjectorServerInfo::getServerIp)
.collect(toSet());
}
public void removeAuthlibInjectorServerURL(String serverURL) {
SETTINGS.authlibInjectorServerURLs.remove(serverURL);
checkAuthlibInjectorAccounts();
save();
/**
* The {@code serverBaseURL} specified in {@link AuthlibInjectorAccount} may not have an associated
* {@link AuthlibInjectorServerInfo} in {@link Config#authlibInjectorServers},
* which usually happens when migrating data from an older version.
* 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);
save();
}
private void checkAuthlibInjectorAccounts() {
for (Account account : getAccounts()) {
if (account instanceof AuthlibInjectorAccount) {
AuthlibInjectorAccount injectorAccount = (AuthlibInjectorAccount) account;
if (!SETTINGS.authlibInjectorServerURLs.contains(injectorAccount.getServerBaseURL()))
deleteAccount(account);
}
}
/**
* After an {@link AuthlibInjectorServerInfo} is removed, the associated accounts should also be removed.
* 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 removeDanglingAuthlibInjectorAccounts() {
Set<String> currentServerUrls = getAuthlibInjectorServerUrls();
accounts.values().stream()
.filter(AuthlibInjectorAccount.class::isInstance)
.filter(it -> !currentServerUrls.contains(((AuthlibInjectorAccount) it).getServerBaseURL()))
.collect(toList())
.forEach(this::deleteAccount);
}
/****************************************

View File

@@ -49,14 +49,13 @@ import org.jackhuang.hmcl.ui.construct.Validator;
import org.jackhuang.hmcl.util.Constants;
import org.jackhuang.hmcl.util.Logging;
import java.util.Collection;
import static java.util.stream.Collectors.toList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class AddAccountPane extends StackPane {
@@ -96,10 +95,6 @@ public class AddAccountPane extends StackPane {
});
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());
txtUsername.setOnAction(e -> onCreationAccept());
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() {
Task.ofResult("list", () -> Settings.INSTANCE.getAuthlibInjectorServerURLs().parallelStream()
.flatMap(serverURL -> {
try {
return Stream.of(new TwoLineListItem(Accounts.getAuthlibInjectorServerName(serverURL), serverURL));
} catch (Exception e) {
Logging.LOG.log(Level.WARNING, "Authlib-injector server root " + serverURL + " cannot be recognized.", e);
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);
}));
cboServers.getItems().setAll(
Settings.INSTANCE.SETTINGS.authlibInjectorServers.stream()
.map(server -> new TwoLineListItem(server.getServerName(), server.getServerIp()))
.collect(toList()));
if (!cboServers.getItems().isEmpty())
cboServers.getSelectionModel().select(0);
}
private void showSpinner() {

View File

@@ -4,7 +4,6 @@ import com.jfoenix.controls.*;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
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.TransitionHandler;
import org.jackhuang.hmcl.ui.wizard.DecoratorPage;
import org.jackhuang.hmcl.util.Logging;
import org.jackhuang.hmcl.util.NetworkUtils;
import java.util.Collection;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toList;
public class AuthlibInjectorServersPage extends StackPane implements DecoratorPage {
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) {
Settings.INSTANCE.removeAuthlibInjectorServerURL(item.getInfo().getServerIp());
Settings.INSTANCE.SETTINGS.authlibInjectorServers.remove(item.getInfo());
loading();
}
@@ -72,27 +67,20 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa
getChildren().remove(contentPane);
spinner.setVisible(true);
Task.ofResult("list", () -> Settings.INSTANCE.getAuthlibInjectorServerURLs().parallelStream()
.flatMap(serverURL -> {
try {
return Stream.of(new AuthlibInjectorServerItem(new AuthlibInjectorServerInfo(serverURL, Accounts.getAuthlibInjectorServerName(serverURL)), this::removeServer));
} catch (Exception e) {
Logging.LOG.log(Level.WARNING, "Authlib-injector server root " + serverURL + " cannot be recognized.", e);
return Stream.empty();
}
})
.collect(Collectors.toList()))
.subscribe(Task.of(Schedulers.javafx(), variables -> {
listPane.getChildren().setAll(variables.<Collection<? extends Node>>get("list"));
loadingCompleted();
}));
listPane.getChildren().setAll(
Settings.INSTANCE.SETTINGS.authlibInjectorServers.stream()
.map(server -> new AuthlibInjectorServerItem(server, this::removeServer))
.collect(toList()));
// TODO: remove spinner
loadingCompleted();
}
private void loadingCompleted() {
getChildren().add(contentPane);
spinner.setVisible(false);
if (Settings.INSTANCE.getAuthlibInjectorServerURLs().isEmpty())
if (Settings.INSTANCE.SETTINGS.authlibInjectorServers.isEmpty())
onAdd();
}
@@ -144,7 +132,9 @@ public class AuthlibInjectorServersPage extends StackPane implements DecoratorPa
@FXML
private void onAddFinish() {
Settings.INSTANCE.addAuthlibInjectorServerURL(serverBeingAdded.getServerIp());
if (!Settings.INSTANCE.SETTINGS.authlibInjectorServers.contains(serverBeingAdded)) {
Settings.INSTANCE.SETTINGS.authlibInjectorServers.add(serverBeingAdded);
}
loading();
dialog.close();
}

View File

@@ -23,6 +23,7 @@ import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.property.Property;
import javafx.beans.value.ChangeListener;
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) {
value.addListener((a, b, c) -> consumer.accept(c));
}

View File

@@ -33,4 +33,19 @@ public class AuthlibInjectorServerInfo {
public String getServerName() {
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);
}
}