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 e5a8f99c1c..0b61409ea1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Accounts.java @@ -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> FACTORIES = List.of(FACTORY_MICROSOFT, FACTORY_AUTHLIB_INJECTOR); + /// Primary: Offline and Microsoft. Authlib-injector remains available for external Yggdrasil servers. + public static final List> FACTORIES = List.of( + FACTORY_OFFLINE, + FACTORY_MICROSOFT, + FACTORY_AUTHLIB_INJECTOR + ); // ==== login type / account factory mapping ==== private static final Map> type2factory = new HashMap<>(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListPage.java index d2894770e8..a573b3d2a9 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/AccountListPage.java @@ -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() { - @Override - public void changed(ObservableValue 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 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 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; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java index 8846272f46..a7b462c8e2 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/account/CreateAccountPane.java @@ -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;