feat: offer Offline and Microsoft auth; keep authlib injector
Primary account creation entries are Offline and Microsoft. External Yggdrasil / authlib-injector servers remain listed and addable for later use. Offline creation is no longer redirected away or region-restricted.
This commit is contained in:
1 parent
4118030d9c
commit
4cd783d6bb
3 files changed
+37
-57
No files matched your search
@@ -55,8 +55,12 @@ public final class Accounts {
|
||||
public static final MicrosoftAccountFactory FACTORY_MICROSOFT = new MicrosoftAccountFactory(new MicrosoftService(OAUTH_CALLBACK));
|
||||
/// Account factories offered when creating a new account from the UI.
|
||||
///
|
||||
/// Offline login remains loadable for existing accounts, but is no longer offered for creation.
|
||||
public static final List<AccountFactory<?>> FACTORIES = List.of(FACTORY_MICROSOFT, FACTORY_AUTHLIB_INJECTOR);
|
||||
/// Primary: Offline and Microsoft. Authlib-injector remains available for external Yggdrasil servers.
|
||||
public static final List<AccountFactory<?>> FACTORIES = List.of(
|
||||
FACTORY_OFFLINE,
|
||||
FACTORY_MICROSOFT,
|
||||
FACTORY_AUTHLIB_INJECTOR
|
||||
);
|
||||
|
||||
// ==== login type / account factory mapping ====
|
||||
private static final Map<String, AccountFactory<?>> type2factory = new HashMap<>();
|
||||
|
||||
@@ -6,15 +6,15 @@ import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.WeakInvalidationListener;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.*;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.jackhuang.hmcl.auth.Account;
|
||||
import org.jackhuang.hmcl.auth.AccountFactory;
|
||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorServer;
|
||||
import org.jackhuang.hmcl.setting.Accounts;
|
||||
import org.jackhuang.hmcl.setting.SettingsManager;
|
||||
import org.jackhuang.hmcl.ui.Controllers;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
@@ -23,7 +23,6 @@ import org.jackhuang.hmcl.ui.WeakListenerHolder;
|
||||
import org.jackhuang.hmcl.ui.construct.AdvancedListItem;
|
||||
import org.jackhuang.hmcl.ui.decorator.DecoratorAnimatedPage;
|
||||
import org.jackhuang.hmcl.ui.decorator.DecoratorPage;
|
||||
import org.jackhuang.hmcl.util.RegionUtils;
|
||||
import org.jackhuang.hmcl.util.javafx.BindingMapping;
|
||||
import org.jackhuang.hmcl.util.javafx.MappedObservableList;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -31,33 +30,13 @@ import org.jetbrains.annotations.UnmodifiableView;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.jackhuang.hmcl.setting.SettingsManager.userSettings;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
import static org.jackhuang.hmcl.util.javafx.ExtendedProperties.createSelectedItemPropertyFor;
|
||||
|
||||
/// Displays account creation methods and the configured account list.
|
||||
public final class AccountListPage extends DecoratorAnimatedPage implements DecoratorPage {
|
||||
/// Whether offline and third-party account creation is restricted.
|
||||
static final BooleanProperty RESTRICTED = new SimpleBooleanProperty(true);
|
||||
|
||||
static {
|
||||
String property = System.getProperty("hmcl.offline.auth.restricted", "auto");
|
||||
|
||||
if ("false".equals(property)
|
||||
|| "auto".equals(property) && "CN".equals(RegionUtils.MACHINE_REGION)
|
||||
|| SettingsManager.userSettings().enableOfflineAccountProperty().get())
|
||||
RESTRICTED.set(false);
|
||||
else
|
||||
userSettings().enableOfflineAccountProperty().addListener(new ChangeListener<Boolean>() {
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends Boolean> o, Boolean oldValue, Boolean newValue) {
|
||||
if (newValue) {
|
||||
userSettings().enableOfflineAccountProperty().removeListener(this);
|
||||
RESTRICTED.set(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
/// Offline / authlib-injector creation is always allowed for this fork.
|
||||
static final BooleanProperty RESTRICTED = new SimpleBooleanProperty(false);
|
||||
|
||||
/// The account entries derived from the configured accounts.
|
||||
private final @UnmodifiableView ObservableList<AccountListItem> items;
|
||||
@@ -77,6 +56,12 @@ public final class AccountListPage extends DecoratorAnimatedPage implements Deco
|
||||
items = MappedObservableList.create(accounts, AccountListItem::new);
|
||||
selectedAccount = createSelectedItemPropertyFor(items, Account.class);
|
||||
|
||||
AdvancedListItem offlineItem = new AdvancedListItem();
|
||||
offlineItem.getStyleClass().add("navigation-drawer-item");
|
||||
offlineItem.setTitle(i18n("account.methods.offline"));
|
||||
offlineItem.setLeftIcon(SVG.PERSON);
|
||||
offlineItem.setOnAction(e -> openCreateAccount(Accounts.FACTORY_OFFLINE));
|
||||
|
||||
AdvancedListItem microsoftItem = new AdvancedListItem();
|
||||
microsoftItem.getStyleClass().add("navigation-drawer-item");
|
||||
microsoftItem.setTitle(i18n("account.methods.microsoft"));
|
||||
@@ -90,14 +75,14 @@ public final class AccountListPage extends DecoratorAnimatedPage implements Deco
|
||||
});
|
||||
|
||||
InvalidationListener buildSidebarListener = observable -> {
|
||||
boolean restricted = RESTRICTED.get();
|
||||
|
||||
getSidebar().clear();
|
||||
|
||||
getSidebar()
|
||||
.startCategory(i18n("account.create").toUpperCase(Locale.ROOT))
|
||||
.add(offlineItem)
|
||||
.add(microsoftItem);
|
||||
|
||||
// External Yggdrasil / authlib-injector servers stay listed for future use.
|
||||
for (AuthlibInjectorServer server : authServers) {
|
||||
AdvancedListItem item = new AdvancedListItem();
|
||||
item.getStyleClass().add("navigation-drawer-item");
|
||||
@@ -110,24 +95,13 @@ public final class AccountListPage extends DecoratorAnimatedPage implements Deco
|
||||
}
|
||||
});
|
||||
|
||||
ObservableValue<String> title = BindingMapping.of(server, AuthlibInjectorServer::getName);
|
||||
var title = BindingMapping.of(server, AuthlibInjectorServer::getName);
|
||||
item.titleProperty().bind(title);
|
||||
item.setSubtitle(server.getDisplayHostUrl());
|
||||
|
||||
Tooltip tooltip = new Tooltip();
|
||||
if (restricted) {
|
||||
tooltip.setText(i18n("account.login.restricted"));
|
||||
item.setActionDisabled(true);
|
||||
} else {
|
||||
tooltip.textProperty().bind(Bindings.format("%s (%s)", title, server.getUrl()));
|
||||
item.setOnAction(e -> {
|
||||
if (SettingsManager.isUserGameAccountsReadOnly()) {
|
||||
confirmOverwriteUserAccounts(() -> Controllers.dialog(new CreateAccountPane(server)));
|
||||
} else {
|
||||
Controllers.dialog(new CreateAccountPane(server));
|
||||
}
|
||||
});
|
||||
}
|
||||
tooltip.textProperty().bind(Bindings.format("%s (%s)", title, server.getUrl()));
|
||||
item.setOnAction(e -> openCreateAccount(Accounts.getAccountFactoryByAuthlibInjectorServer(server)));
|
||||
FXUtils.installFastTooltip(item, tooltip);
|
||||
|
||||
getSidebar().add(item);
|
||||
@@ -138,7 +112,6 @@ public final class AccountListPage extends DecoratorAnimatedPage implements Deco
|
||||
|
||||
WeakInvalidationListener weakBuildSidebarListener = holder.weak(buildSidebarListener);
|
||||
authServers.addListener(weakBuildSidebarListener);
|
||||
RESTRICTED.addListener(weakBuildSidebarListener);
|
||||
|
||||
AdvancedListItem addAuthServerItem = new AdvancedListItem();
|
||||
addAuthServerItem.getStyleClass().add("navigation-drawer-item");
|
||||
@@ -171,6 +144,14 @@ public final class AccountListPage extends DecoratorAnimatedPage implements Deco
|
||||
setContent(scrollPane);
|
||||
}
|
||||
|
||||
private void openCreateAccount(AccountFactory<?> factory) {
|
||||
if (SettingsManager.isUserGameAccountsReadOnly()) {
|
||||
confirmOverwriteUserAccounts(() -> Controllers.dialog(new CreateAccountPane(factory)));
|
||||
} else {
|
||||
Controllers.dialog(new CreateAccountPane(factory));
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the account selection shared with the launcher.
|
||||
public ObjectProperty<@Nullable Account> selectedAccountProperty() {
|
||||
return selectedAccount;
|
||||
|
||||
@@ -81,20 +81,15 @@ public class CreateAccountPane extends JFXDialogLayout implements DialogAware {
|
||||
|
||||
public CreateAccountPane(AccountFactory<?> factory) {
|
||||
if (factory == null) {
|
||||
if (AccountListPage.RESTRICTED.get()) {
|
||||
showMethodSwitcher = false;
|
||||
factory = Accounts.FACTORY_MICROSOFT;
|
||||
} else {
|
||||
showMethodSwitcher = true;
|
||||
String preferred = settings().preferredLoginTypeProperty().get();
|
||||
try {
|
||||
factory = Accounts.getAccountFactory(preferred);
|
||||
if (factory == Accounts.FACTORY_OFFLINE) {
|
||||
factory = Accounts.FACTORY_MICROSOFT;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
factory = Accounts.FACTORY_MICROSOFT;
|
||||
showMethodSwitcher = true;
|
||||
String preferred = settings().preferredLoginTypeProperty().get();
|
||||
try {
|
||||
factory = Accounts.getAccountFactory(preferred);
|
||||
if (!Accounts.FACTORIES.contains(factory)) {
|
||||
factory = Accounts.FACTORY_OFFLINE;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
factory = Accounts.FACTORY_OFFLINE;
|
||||
}
|
||||
} else {
|
||||
showMethodSwitcher = false;
|
||||
|
||||
Reference in new issue
Block a user