feat: lightweight first-run dialog for picking a game name or signing in
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b3f649c026
commit
06ef27f0e0
6 files changed
+118
-1
No files matched your search
@@ -0,0 +1,92 @@
|
||||
// SPDX-FileCopyrightText: Copyright (C) 2026 The HMCL Authors
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later WITH AdditionRef-HMCL
|
||||
package org.jackhuang.hmcl.ui.account;
|
||||
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXDialogLayout;
|
||||
import com.jfoenix.controls.JFXTextField;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.jackhuang.hmcl.auth.offline.OfflineAccountFactory;
|
||||
import org.jackhuang.hmcl.setting.Accounts;
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.ui.Controllers;
|
||||
import org.jackhuang.hmcl.ui.construct.DialogAware;
|
||||
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
|
||||
import org.jetbrains.annotations.NotNullByDefault;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
/// A small dialog shown when the player has no account yet.
|
||||
///
|
||||
/// The player either types a game name, which creates an offline account, or chooses to sign in
|
||||
/// with a Microsoft account instead. Authentication itself is left to the server.
|
||||
@NotNullByDefault
|
||||
public final class FirstRunAccountDialog extends JFXDialogLayout implements DialogAware {
|
||||
/// Names accepted by the game: letters, digits and underscores, at most 16 characters.
|
||||
private static final Pattern NAME_PATTERN = Pattern.compile("^[A-Za-z0-9_]{1,16}$");
|
||||
|
||||
private final JFXTextField nameField = new JFXTextField();
|
||||
private final Label hint = new Label();
|
||||
private final JFXButton acceptButton = new JFXButton(i18n("first_run.accept"));
|
||||
|
||||
/// Creates the dialog with its name field and the two actions.
|
||||
public FirstRunAccountDialog() {
|
||||
Label heading = new Label(i18n("first_run.title"));
|
||||
setHeading(heading);
|
||||
|
||||
Label description = new Label(i18n("first_run.description"));
|
||||
description.setWrapText(true);
|
||||
nameField.setPromptText(i18n("first_run.name"));
|
||||
hint.setStyle("-fx-text-fill: -monet-error;");
|
||||
hint.setWrapText(true);
|
||||
VBox body = new VBox(13, description, nameField, hint);
|
||||
body.setPrefWidth(377);
|
||||
setBody(body);
|
||||
|
||||
JFXButton microsoftButton = new JFXButton(i18n("first_run.microsoft"));
|
||||
microsoftButton.getStyleClass().add("dialog-cancel");
|
||||
microsoftButton.setOnAction(e -> {
|
||||
fireEvent(new DialogCloseEvent());
|
||||
Controllers.dialog(new CreateAccountPane(Accounts.FACTORY_MICROSOFT));
|
||||
});
|
||||
|
||||
acceptButton.getStyleClass().add("dialog-accept");
|
||||
acceptButton.setOnAction(e -> createAccount());
|
||||
nameField.setOnAction(e -> acceptButton.fire());
|
||||
setActions(microsoftButton, acceptButton);
|
||||
}
|
||||
|
||||
/// Validates the typed name and creates and selects the offline account.
|
||||
private void createAccount() {
|
||||
String name = nameField.getText() == null ? "" : nameField.getText().trim();
|
||||
if (!NAME_PATTERN.matcher(name).matches()) {
|
||||
hint.setText(i18n("first_run.invalid"));
|
||||
return;
|
||||
}
|
||||
|
||||
hint.setText("");
|
||||
acceptButton.setDisable(true);
|
||||
Task.supplyAsync(() -> Accounts.FACTORY_OFFLINE.create(
|
||||
new CreateAccountPane.DialogCharacterSelector(), name, null, null,
|
||||
new OfflineAccountFactory.AdditionalData(null, null)))
|
||||
.whenComplete(Schedulers.javafx(), account -> {
|
||||
if (!Accounts.getAccounts().contains(account)) {
|
||||
Accounts.getAccounts().add(account);
|
||||
}
|
||||
Accounts.setSelectedAccount(account);
|
||||
fireEvent(new DialogCloseEvent());
|
||||
}, exception -> {
|
||||
acceptButton.setDisable(false);
|
||||
hint.setText(Accounts.localizeErrorMessage(exception));
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDialogShown() {
|
||||
nameField.requestFocus();
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.ui.Controllers;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.ui.account.CreateAccountPane;
|
||||
import org.jackhuang.hmcl.ui.account.FirstRunAccountDialog;
|
||||
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
|
||||
import org.jackhuang.hmcl.ui.construct.MessageDialogPane;
|
||||
import org.jackhuang.hmcl.ui.construct.PromptDialogPane;
|
||||
@@ -363,7 +364,7 @@ public final class Instances {
|
||||
private static void ensureSelectedAccount(Consumer<Account> action) {
|
||||
Account account = Accounts.getSelectedAccount();
|
||||
if (account == null) {
|
||||
CreateAccountPane dialog = new CreateAccountPane();
|
||||
FirstRunAccountDialog dialog = new FirstRunAccountDialog();
|
||||
dialog.addEventHandler(DialogCloseEvent.CLOSE, e -> {
|
||||
Account newAccount = Accounts.getSelectedAccount();
|
||||
if (newAccount == null) {
|
||||
|
||||
@@ -800,6 +800,12 @@ home.not_installed=Not installed
|
||||
launcher.name=Server Launcher
|
||||
account.add=Add account
|
||||
account.open_manage=Manage accounts
|
||||
first_run.title=Pick a game name
|
||||
first_run.description=Your name is used when you join the server. You can sign in with a Microsoft account instead.
|
||||
first_run.name=Game name
|
||||
first_run.accept=Start playing
|
||||
first_run.microsoft=Sign in with Microsoft
|
||||
first_run.invalid=Use 1 to 16 letters, digits or underscores.
|
||||
server.join=Join Server
|
||||
instance.launch_and_enter_world=Play World
|
||||
instance.launch.empty=Start Game
|
||||
|
||||
@@ -620,6 +620,12 @@ home.not_installed=未裝
|
||||
launcher.name=服啟
|
||||
account.add=增帳
|
||||
account.open_manage=理帳
|
||||
first_run.title=署名
|
||||
first_run.description=入服用此名。可改登微軟之帳。
|
||||
first_run.name=名
|
||||
first_run.accept=始
|
||||
first_run.microsoft=登正版
|
||||
first_run.invalid=一至十六字,限英文數字底線。
|
||||
server.join=入服
|
||||
# instance.launch_and_enter_world=
|
||||
instance.launch.empty=啟戲
|
||||
|
||||
@@ -623,6 +623,12 @@ home.not_installed=尚未安装
|
||||
launcher.name=服务器启动器
|
||||
account.add=添加账号
|
||||
account.open_manage=管理账号
|
||||
first_run.title=起个游戏名
|
||||
first_run.description=进服时会用这个名字。想用正版账号的话,可以改为登录微软账号。
|
||||
first_run.name=游戏名
|
||||
first_run.accept=开始游戏
|
||||
first_run.microsoft=登录正版账号
|
||||
first_run.invalid=只能用 1 到 16 个英文字母、数字或下划线。
|
||||
server.join=进入服务器
|
||||
instance.launch_and_enter_world=进入世界
|
||||
instance.launch.empty=开始游戏
|
||||
|
||||
@@ -617,6 +617,12 @@ home.not_installed=尚未安裝
|
||||
launcher.name=伺服器啟動器
|
||||
account.add=新增帳號
|
||||
account.open_manage=管理帳號
|
||||
first_run.title=取個遊戲名
|
||||
first_run.description=進服時會使用這個名字。想用正版帳號的話,可以改為登入微軟帳號。
|
||||
first_run.name=遊戲名
|
||||
first_run.accept=開始遊戲
|
||||
first_run.microsoft=登入正版帳號
|
||||
first_run.invalid=只能使用 1 到 16 個英文字母、數字或底線。
|
||||
server.join=進入伺服器
|
||||
instance.launch_and_enter_world=進入世界
|
||||
instance.launch.empty=開始遊戲
|
||||
|
||||
Reference in new issue
Block a user