mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-03-07 17:36:52 +08:00
feat: show migration hint when 410. Closes #1045.
This commit is contained in:
parent
0b2e9c3f62
commit
37cee9cebd
@ -340,14 +340,21 @@ public final class Accounts {
|
||||
RemoteAuthenticationException remoteException = (RemoteAuthenticationException) exception;
|
||||
String remoteMessage = remoteException.getRemoteMessage();
|
||||
if ("ForbiddenOperationException".equals(remoteException.getRemoteName()) && remoteMessage != null) {
|
||||
if (remoteMessage.contains("Invalid credentials"))
|
||||
if (remoteMessage.contains("Invalid credentials")) {
|
||||
return i18n("account.failed.invalid_credentials");
|
||||
else if (remoteMessage.contains("Invalid token"))
|
||||
} else if (remoteMessage.contains("Invalid token")) {
|
||||
return i18n("account.failed.invalid_token");
|
||||
else if (remoteMessage.contains("Invalid username or password"))
|
||||
} else if (remoteMessage.contains("Invalid username or password")) {
|
||||
return i18n("account.failed.invalid_password");
|
||||
else
|
||||
} else {
|
||||
return remoteMessage;
|
||||
}
|
||||
} else if ("ResourceException".equals(remoteException.getRemoteName()) && remoteMessage != null) {
|
||||
if (remoteMessage.contains("The requested resource is no longer available")) {
|
||||
return i18n("account.failed.migration");
|
||||
} else {
|
||||
return remoteMessage;
|
||||
}
|
||||
}
|
||||
return exception.getMessage();
|
||||
} else if (exception instanceof AuthlibInjectorDownloadException) {
|
||||
|
@ -17,50 +17,106 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui.account;
|
||||
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXDialogLayout;
|
||||
import com.jfoenix.controls.JFXPasswordField;
|
||||
import com.jfoenix.controls.JFXProgressBar;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.jackhuang.hmcl.auth.Account;
|
||||
import org.jackhuang.hmcl.auth.AuthInfo;
|
||||
import org.jackhuang.hmcl.auth.NoSelectedCharacterException;
|
||||
import org.jackhuang.hmcl.auth.authlibinjector.AuthlibInjectorAccount;
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilService;
|
||||
import org.jackhuang.hmcl.setting.Accounts;
|
||||
import org.jackhuang.hmcl.task.Schedulers;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.ui.construct.DialogCloseEvent;
|
||||
import org.jackhuang.hmcl.ui.construct.JFXHyperlink;
|
||||
import org.jackhuang.hmcl.ui.construct.RequiredValidator;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed;
|
||||
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
public class AccountLoginPane extends StackPane {
|
||||
private final Account oldAccount;
|
||||
private final Consumer<AuthInfo> success;
|
||||
private final Runnable failed;
|
||||
|
||||
@FXML private Label lblUsername;
|
||||
@FXML private JFXPasswordField txtPassword;
|
||||
@FXML private Label lblCreationWarning;
|
||||
@FXML private JFXProgressBar progressBar;
|
||||
private final JFXPasswordField txtPassword;
|
||||
private final Label lblCreationWarning = new Label();
|
||||
private final JFXProgressBar progressBar;
|
||||
|
||||
public AccountLoginPane(Account oldAccount, Consumer<AuthInfo> success, Runnable failed) {
|
||||
this.oldAccount = oldAccount;
|
||||
this.success = success;
|
||||
this.failed = failed;
|
||||
|
||||
FXUtils.loadFXML(this, "/assets/fxml/account-login.fxml");
|
||||
progressBar = new JFXProgressBar();
|
||||
StackPane.setAlignment(progressBar, Pos.TOP_CENTER);
|
||||
progressBar.setVisible(false);
|
||||
|
||||
lblUsername.setText(oldAccount.getUsername());
|
||||
txtPassword.setOnAction(e -> onAccept());
|
||||
JFXDialogLayout dialogLayout = new JFXDialogLayout();
|
||||
|
||||
{
|
||||
dialogLayout.setHeading(new Label(i18n("login.enter_password")));
|
||||
}
|
||||
|
||||
{
|
||||
VBox body = new VBox(15);
|
||||
body.setPadding(new Insets(15, 0, 0, 0));
|
||||
|
||||
Label usernameLabel = new Label(oldAccount.getUsername());
|
||||
|
||||
txtPassword = new JFXPasswordField();
|
||||
txtPassword.setOnAction(e -> onAccept());
|
||||
txtPassword.getValidators().add(new RequiredValidator());
|
||||
txtPassword.setLabelFloat(true);
|
||||
txtPassword.setPromptText(i18n("account.password"));
|
||||
|
||||
body.getChildren().setAll(usernameLabel, txtPassword);
|
||||
|
||||
if (oldAccount instanceof YggdrasilAccount && !(oldAccount instanceof AuthlibInjectorAccount)) {
|
||||
HBox linkPane = new HBox(8);
|
||||
body.getChildren().add(linkPane);
|
||||
|
||||
JFXHyperlink migrationLink = new JFXHyperlink(i18n("account.methods.yggdrasil.migration"));
|
||||
migrationLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.PROFILE_URL));
|
||||
|
||||
JFXHyperlink migrationHowLink = new JFXHyperlink(i18n("account.methods.yggdrasil.migration.how"));
|
||||
migrationHowLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.MIGRATION_FAQ_URL));
|
||||
|
||||
linkPane.getChildren().setAll(migrationLink, migrationLink);
|
||||
}
|
||||
|
||||
dialogLayout.setBody(body);
|
||||
}
|
||||
|
||||
{
|
||||
JFXButton acceptButton = new JFXButton(i18n("button.ok"));
|
||||
acceptButton.setOnAction(e -> onAccept());
|
||||
acceptButton.getStyleClass().add("dialog-accept");
|
||||
|
||||
JFXButton cancelButton = new JFXButton(i18n("button.cancel"));
|
||||
cancelButton.setOnAction(e -> onCancel());
|
||||
cancelButton.getStyleClass().add("dialog-cancel");
|
||||
|
||||
dialogLayout.setActions(lblCreationWarning, acceptButton, cancelButton);
|
||||
}
|
||||
|
||||
onEscPressed(this, this::onCancel);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void onAccept() {
|
||||
String password = txtPassword.getText();
|
||||
progressBar.setVisible(true);
|
||||
@ -81,7 +137,6 @@ public class AccountLoginPane extends StackPane {
|
||||
}).start();
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void onCancel() {
|
||||
failed.run();
|
||||
fireEvent(new DialogCloseEvent());
|
||||
|
@ -277,7 +277,7 @@ public class CreateAccountPane extends JFXDialogLayout implements DialogAware {
|
||||
JFXHyperlink profileLink = new JFXHyperlink(i18n("account.methods.microsoft.profile"));
|
||||
profileLink.setOnAction(e -> FXUtils.openLink("https://account.live.com/editprof.aspx"));
|
||||
JFXHyperlink purchaseLink = new JFXHyperlink(i18n("account.methods.yggdrasil.purchase"));
|
||||
purchaseLink.setOnAction(e -> FXUtils.openLink("https://www.minecraft.net/zh-hans/store/minecraft-java-edition"));
|
||||
purchaseLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.PURCHASE_URL));
|
||||
box.getChildren().setAll(profileLink, birthLink, purchaseLink);
|
||||
GridPane.setColumnSpan(box, 2);
|
||||
|
||||
@ -418,13 +418,17 @@ public class CreateAccountPane extends JFXDialogLayout implements DialogAware {
|
||||
if (factory instanceof YggdrasilAccountFactory) {
|
||||
HBox box = new HBox();
|
||||
GridPane.setColumnSpan(box, 2);
|
||||
|
||||
JFXHyperlink migrationLink = new JFXHyperlink(i18n("account.methods.yggdrasil.migration"));
|
||||
migrationLink.setOnAction(e -> FXUtils.openLink("https://help.minecraft.net/hc/en-us/articles/360050865492-JAVA-Account-Migration-FAQ"));
|
||||
migrationLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.PROFILE_URL));
|
||||
|
||||
JFXHyperlink migrationHowLink = new JFXHyperlink(i18n("account.methods.yggdrasil.migration.how"));
|
||||
migrationHowLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.MIGRATION_FAQ_URL));
|
||||
|
||||
JFXHyperlink purchaseLink = new JFXHyperlink(i18n("account.methods.yggdrasil.purchase"));
|
||||
purchaseLink.setOnAction(e -> FXUtils.openLink("https://www.minecraft.net/zh-hans/store/minecraft-java-edition"));
|
||||
purchaseLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.PURCHASE_URL));
|
||||
|
||||
box.getChildren().setAll(migrationLink, purchaseLink);
|
||||
box.getChildren().setAll(migrationLink, migrationHowLink, purchaseLink);
|
||||
add(box, 0, rowIndex);
|
||||
|
||||
rowIndex++;
|
||||
@ -432,7 +436,7 @@ public class CreateAccountPane extends JFXDialogLayout implements DialogAware {
|
||||
|
||||
if (factory instanceof OfflineAccountFactory) {
|
||||
JFXHyperlink purchaseLink = new JFXHyperlink(i18n("account.methods.yggdrasil.purchase"));
|
||||
purchaseLink.setOnAction(e -> FXUtils.openLink("https://www.minecraft.net/zh-hans/store/minecraft-java-edition"));
|
||||
purchaseLink.setOnAction(e -> FXUtils.openLink(YggdrasilService.PURCHASE_URL));
|
||||
HBox linkPane = new HBox(purchaseLink);
|
||||
GridPane.setColumnSpan(linkPane, 2);
|
||||
add(linkPane, 0, rowIndex);
|
||||
|
@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import com.jfoenix.controls.*?>
|
||||
<?import com.jfoenix.validation.RequiredFieldValidator?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.StackPane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<fx:root xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
type="StackPane">
|
||||
<JFXDialogLayout>
|
||||
<heading>
|
||||
<Label text="%login.enter_password" />
|
||||
</heading>
|
||||
<body>
|
||||
<VBox spacing="15" style="-fx-padding: 15 0 0 0;">
|
||||
<Label fx:id="lblUsername" />
|
||||
<JFXPasswordField fx:id="txtPassword" promptText="%account.password" labelFloat="true">
|
||||
<validators>
|
||||
<RequiredFieldValidator message="Input Required!">
|
||||
</RequiredFieldValidator>
|
||||
</validators>
|
||||
</JFXPasswordField>
|
||||
</VBox>
|
||||
</body>
|
||||
<actions>
|
||||
<Label fx:id="lblCreationWarning" />
|
||||
<JFXButton onMouseClicked="#onAccept" text="%button.ok" styleClass="dialog-accept"/>
|
||||
<JFXButton onMouseClicked="#onCancel" text="%button.cancel" styleClass="dialog-cancel"/>
|
||||
</actions>
|
||||
</JFXDialogLayout>
|
||||
<JFXProgressBar fx:id="progressBar" visible="false" StackPane.alignment="TOP_CENTER"/>
|
||||
</fx:root>
|
@ -61,6 +61,7 @@ account.failed.injector_download_failure=Failed to download authlib-injector. Ch
|
||||
account.failed.invalid_credentials=Incorrect password, or you are forbidden to login temporarily.
|
||||
account.failed.invalid_password=Invalid password
|
||||
account.failed.invalid_token=Please log out and re-enter your password to login.
|
||||
account.failed.migration=Your account needs to be migrated to a Microsoft account. If already migrated, you should login your migrated Microsoft account instead.
|
||||
account.failed.no_character=No character in this account.
|
||||
account.failed.server_response_malformed=Invalid server response. The authentication server may have an error.
|
||||
account.injector.add=Add an authentication server
|
||||
@ -96,7 +97,8 @@ account.methods.offline.uuid=UUID
|
||||
account.methods.offline.uuid.hint=UUID is the unique identifier to the game character in Minecraft. The way that UUID is generated varies from different game launchers. Changing UUID to the one generated by other launcher would promise that game blocks/items in the backpack of your offline account remain. This option is for expert. Unless you know what you are doing, we do not suggest you to change this option.
|
||||
account.methods.offline.uuid.malformed=Malformed
|
||||
account.methods.yggdrasil=Mojang
|
||||
account.methods.yggdrasil.migration=How to migrate to Microsoft Account?
|
||||
account.methods.yggdrasil.migration=Migrate to Microsoft Account
|
||||
account.methods.yggdrasil.migration.how=How to migrate to Microsoft Account?
|
||||
account.methods.yggdrasil.purchase=Purchase Minecraft
|
||||
account.missing=No Account
|
||||
account.missing.add=Click here to add
|
||||
|
@ -61,6 +61,7 @@ account.failed.injector_download_failure=無法下載 authlib-injector,請檢
|
||||
account.failed.invalid_credentials=您的使用者名稱或密碼錯誤,或者登入次數過多被暫時禁止登入,請稍後再試
|
||||
account.failed.invalid_password=密碼無效
|
||||
account.failed.invalid_token=請嘗試登出並重新輸入密碼登入
|
||||
account.failed.migration=你的帳號需要被遷移至微軟帳號。如果你已經遷移,你需要使用微軟登錄方式登錄遷移後的微軟帳號。
|
||||
account.failed.no_character=該帳戶沒有角色
|
||||
account.failed.server_response_malformed=無法解析認證伺服器回應,可能是伺服器故障
|
||||
account.injector.add=新增認證伺服器
|
||||
@ -96,7 +97,8 @@ account.methods.offline.uuid=UUID
|
||||
account.methods.offline.uuid.hint=UUID 是 Minecraft 對玩家角色的唯一標識符,每個啟動器生成 UUID 的方式可能不同。通過修改 UUID 選項至原啟動器所生成的 UUID,你可以保證在切換啟動器後,遊戲還能將你的遊戲角色識別為給定 UUID 所對應的角色,從而保留原來角色的背包物品。UUID 選項為高級選項,除非你知道你在做什麼,否則你不需要調整該選項。
|
||||
account.methods.offline.uuid.malformed=格式錯誤
|
||||
account.methods.yggdrasil=正版登入
|
||||
account.methods.yggdrasil.migration=如何遷移至微軟帳戶?
|
||||
account.methods.yggdrasil.migration=遷移至微軟帳戶
|
||||
account.methods.yggdrasil.migration.how=如何遷移至微軟帳戶?
|
||||
account.methods.yggdrasil.purchase=購買 Minecraft
|
||||
account.missing=沒有遊戲帳戶
|
||||
account.missing.add=按一下此處加入帳戶
|
||||
|
@ -61,6 +61,7 @@ account.failed.injector_download_failure=无法下载 authlib-injector,请检
|
||||
account.failed.invalid_credentials=您的用户名或密码错误,或者登录次数过多被暂时禁止登录,请稍后再试
|
||||
account.failed.invalid_password=无效的密码
|
||||
account.failed.invalid_token=请尝试登出并重新输入密码登录
|
||||
account.failed.migration=你的帐号需要被迁移至微软帐号。如果你已经迁移,你需要使用微软登录方式登录迁移后的微软帐号。
|
||||
account.failed.no_character=该帐号没有角色
|
||||
account.failed.server_response_malformed=无法解析认证服务器响应,可能是服务器故障
|
||||
account.injector.add=添加认证服务器
|
||||
@ -96,7 +97,8 @@ account.methods.offline.uuid=UUID
|
||||
account.methods.offline.uuid.hint=UUID 是 Minecraft 对玩家角色的唯一标识符,每个启动器生成 UUID 的方式可能不同。通过修改 UUID 选项至原启动器所生成的 UUID,你可以保证在切换启动器后,游戏还能将你的游戏角色识别为给定 UUID 所对应的角色,从而保留原来角色的背包物品。UUID 选项为高级选项,除非你知道你在做什么,否则你不需要调整该选项。
|
||||
account.methods.offline.uuid.malformed=格式错误
|
||||
account.methods.yggdrasil=Mojang 帐户
|
||||
account.methods.yggdrasil.migration=如何迁移至微软帐户?
|
||||
account.methods.yggdrasil.migration=迁移至微软账户
|
||||
account.methods.yggdrasil.migration.how=如何迁移至微软帐户?
|
||||
account.methods.yggdrasil.purchase=购买 Minecraft
|
||||
account.missing=没有游戏帐户
|
||||
account.missing.add=点击此处添加帐户
|
||||
|
@ -272,4 +272,7 @@ public class YggdrasilService {
|
||||
.registerTypeAdapterFactory(ValidationTypeAdapterFactory.INSTANCE)
|
||||
.create();
|
||||
|
||||
public static final String PROFILE_URL = "https://www.minecraft.net/profile";
|
||||
public static final String MIGRATION_FAQ_URL = "https://help.minecraft.net/hc/en-us/articles/360050865492-JAVA-Account-Migration-FAQ";
|
||||
public static final String PURCHASE_URL = "https://www.minecraft.net/zh-hans/store/minecraft-java-edition";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user