[Bug] Fix Login Screen Buttons can be Pressed While Animating (#5170)

* destroy containers when processing external containers

* make form buttons uninteractible until tweens finished instead

* fix holding enter spam

* fix conflicts
This commit is contained in:
Chris 2025-04-19 17:00:12 -04:00 committed by GitHub
parent 65294f408e
commit bda286cebb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 120 additions and 106 deletions

View File

@ -124,7 +124,7 @@ export abstract class FormModalUiHandler extends ModalUiHandler {
if (this.buttonBgs.length) { if (this.buttonBgs.length) {
this.buttonBgs[0].off("pointerdown"); this.buttonBgs[0].off("pointerdown");
this.buttonBgs[0].on("pointerdown", () => { this.buttonBgs[0].on("pointerdown", () => {
if (this.submitAction) { if (this.submitAction && globalScene.tweens.getTweensOf(this.modalContainer).length === 0) {
this.submitAction(); this.submitAction();
} }
}); });

View File

@ -40,25 +40,9 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
setup(): void { setup(): void {
super.setup(); super.setup();
this.buildExternalPartyContainer(); this.buildExternalPartyContainer();
this.buildInfoContainer();
this.infoContainer = globalScene.add.container(0, 0);
this.usernameInfoImage = this.buildInteractableImage("settings_icon", "username-info-icon", {
x: 20,
scale: 0.5,
});
this.saveDownloadImage = this.buildInteractableImage("saving_icon", "save-download-icon", {
x: 0,
scale: 0.75,
});
this.infoContainer.add(this.usernameInfoImage);
this.infoContainer.add(this.saveDownloadImage);
this.getUi().add(this.infoContainer);
this.infoContainer.setVisible(false);
this.infoContainer.disableInteractive();
} }
private buildExternalPartyContainer() { private buildExternalPartyContainer() {
@ -84,6 +68,26 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
this.externalPartyContainer.setVisible(false); this.externalPartyContainer.setVisible(false);
} }
private buildInfoContainer() {
this.infoContainer = globalScene.add.container(0, 0);
this.usernameInfoImage = this.buildInteractableImage("settings_icon", "username-info-icon", {
x: 20,
scale: 0.5,
});
this.saveDownloadImage = this.buildInteractableImage("saving_icon", "save-download-icon", {
x: 0,
scale: 0.75,
});
this.infoContainer.add(this.usernameInfoImage);
this.infoContainer.add(this.saveDownloadImage);
this.getUi().add(this.infoContainer);
this.infoContainer.setVisible(false);
this.infoContainer.disableInteractive();
}
override getModalTitle(_config?: ModalConfig): string { override getModalTitle(_config?: ModalConfig): string {
let key = "menu:login"; let key = "menu:login";
if (import.meta.env.VITE_SERVER_URL === "https://apibeta.pokerogue.net") { if (import.meta.env.VITE_SERVER_URL === "https://apibeta.pokerogue.net") {
@ -143,27 +147,29 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
this.processExternalProvider(config); this.processExternalProvider(config);
const originalLoginAction = this.submitAction; const originalLoginAction = this.submitAction;
this.submitAction = _ => { this.submitAction = _ => {
// Prevent overlapping overrides on action modification if (globalScene.tweens.getTweensOf(this.modalContainer).length === 0) {
this.submitAction = originalLoginAction; // Prevent overlapping overrides on action modification
this.sanitizeInputs(); this.submitAction = originalLoginAction;
this.sanitizeInputs();
globalScene.ui.setMode(UiMode.LOADING, { buttonActions: [] }); globalScene.ui.setMode(UiMode.LOADING, { buttonActions: [] });
const onFail = error => { const onFail = error => {
globalScene.ui.setMode(UiMode.LOGIN_FORM, Object.assign(config, { errorMessage: error?.trim() })); globalScene.ui.setMode(UiMode.LOGIN_FORM, Object.assign(config, { errorMessage: error?.trim() }));
globalScene.ui.playError(); globalScene.ui.playError();
}; };
if (!this.inputs[0].text) { if (!this.inputs[0].text) {
return onFail(i18next.t("menu:emptyUsername")); return onFail(i18next.t("menu:emptyUsername"));
}
const [usernameInput, passwordInput] = this.inputs;
pokerogueApi.account.login({ username: usernameInput.text, password: passwordInput.text }).then(error => {
if (!error && originalLoginAction) {
originalLoginAction();
} else {
onFail(error);
} }
});
const [usernameInput, passwordInput] = this.inputs;
pokerogueApi.account.login({ username: usernameInput.text, password: passwordInput.text }).then(error => {
if (!error && originalLoginAction) {
originalLoginAction();
} else {
onFail(error);
}
});
}
}; };
return true; return true;
@ -221,34 +227,36 @@ export default class LoginFormUiHandler extends FormModalUiHandler {
}; };
this.usernameInfoImage.on("pointerdown", () => { this.usernameInfoImage.on("pointerdown", () => {
const localStorageKeys = Object.keys(localStorage); // this gets the keys for localStorage if (globalScene.tweens.getTweensOf(this.infoContainer).length === 0) {
const keyToFind = "data_"; const localStorageKeys = Object.keys(localStorage); // this gets the keys for localStorage
const dataKeys = localStorageKeys.filter(ls => ls.indexOf(keyToFind) >= 0); const keyToFind = "data_";
if (dataKeys.length > 0 && dataKeys.length <= 2) { const dataKeys = localStorageKeys.filter(ls => ls.indexOf(keyToFind) >= 0);
const options: OptionSelectItem[] = []; if (dataKeys.length > 0 && dataKeys.length <= 2) {
for (let i = 0; i < dataKeys.length; i++) { const options: OptionSelectItem[] = [];
options.push({ for (let i = 0; i < dataKeys.length; i++) {
label: dataKeys[i].replace(keyToFind, ""), options.push({
handler: () => { label: dataKeys[i].replace(keyToFind, ""),
globalScene.ui.revertMode(); handler: () => {
this.infoContainer.disableInteractive(); globalScene.ui.revertMode();
return true; this.infoContainer.disableInteractive();
}, return true;
}); },
} });
}
globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, { globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, {
options: options, options: options,
delay: 1000, delay: 1000,
}); });
this.infoContainer.setInteractive( this.infoContainer.setInteractive(
new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width, globalScene.game.canvas.height), new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width, globalScene.game.canvas.height),
Phaser.Geom.Rectangle.Contains, Phaser.Geom.Rectangle.Contains,
); );
} else { } else {
if (dataKeys.length > 2) { if (dataKeys.length > 2) {
return onFail(this.ERR_TOO_MANY_SAVES); return onFail(this.ERR_TOO_MANY_SAVES);
}
return onFail(this.ERR_NO_SAVES);
} }
return onFail(this.ERR_NO_SAVES);
} }
}); });

View File

@ -134,7 +134,11 @@ export abstract class ModalUiHandler extends UiHandler {
for (let a = 0; a < this.buttonBgs.length; a++) { for (let a = 0; a < this.buttonBgs.length; a++) {
if (a < this.buttonBgs.length) { if (a < this.buttonBgs.length) {
this.buttonBgs[a].on("pointerdown", _ => config.buttonActions[a]()); this.buttonBgs[a].on("pointerdown", _ => {
if (globalScene.tweens.getTweensOf(this.modalContainer).length === 0) {
config.buttonActions[a]();
}
});
} }
} }

View File

@ -98,51 +98,53 @@ export default class RegistrationFormUiHandler extends FormModalUiHandler {
const originalRegistrationAction = this.submitAction; const originalRegistrationAction = this.submitAction;
this.submitAction = _ => { this.submitAction = _ => {
// Prevent overlapping overrides on action modification if (globalScene.tweens.getTweensOf(this.modalContainer).length === 0) {
this.submitAction = originalRegistrationAction; // Prevent overlapping overrides on action modification
this.sanitizeInputs(); this.submitAction = originalRegistrationAction;
this.sanitizeInputs();
globalScene.ui.setMode(UiMode.LOADING, { buttonActions: [] }); globalScene.ui.setMode(UiMode.LOADING, { buttonActions: [] });
const onFail = error => { const onFail = error => {
globalScene.ui.setMode(UiMode.REGISTRATION_FORM, Object.assign(config, { errorMessage: error?.trim() })); globalScene.ui.setMode(UiMode.REGISTRATION_FORM, Object.assign(config, { errorMessage: error?.trim() }));
globalScene.ui.playError(); globalScene.ui.playError();
const errorMessageFontSize = languageSettings[i18next.resolvedLanguage!]?.errorMessageFontSize; const errorMessageFontSize = languageSettings[i18next.resolvedLanguage!]?.errorMessageFontSize;
if (errorMessageFontSize) { if (errorMessageFontSize) {
this.errorMessage.setFontSize(errorMessageFontSize); this.errorMessage.setFontSize(errorMessageFontSize);
}
};
if (!this.inputs[0].text) {
return onFail(i18next.t("menu:emptyUsername"));
}
if (!this.inputs[1].text) {
return onFail(this.getReadableErrorMessage("invalid password"));
}
if (this.inputs[1].text !== this.inputs[2].text) {
return onFail(i18next.t("menu:passwordNotMatchingConfirmPassword"));
}
const [usernameInput, passwordInput] = this.inputs;
pokerogueApi.account
.register({
username: usernameInput.text,
password: passwordInput.text,
})
.then(registerError => {
if (!registerError) {
pokerogueApi.account
.login({
username: usernameInput.text,
password: passwordInput.text,
})
.then(loginError => {
if (!loginError) {
originalRegistrationAction?.();
} else {
onFail(loginError);
}
});
} else {
onFail(registerError);
} }
}); };
if (!this.inputs[0].text) {
return onFail(i18next.t("menu:emptyUsername"));
}
if (!this.inputs[1].text) {
return onFail(this.getReadableErrorMessage("invalid password"));
}
if (this.inputs[1].text !== this.inputs[2].text) {
return onFail(i18next.t("menu:passwordNotMatchingConfirmPassword"));
}
const [usernameInput, passwordInput] = this.inputs;
pokerogueApi.account
.register({
username: usernameInput.text,
password: passwordInput.text,
})
.then(registerError => {
if (!registerError) {
pokerogueApi.account
.login({
username: usernameInput.text,
password: passwordInput.text,
})
.then(loginError => {
if (!loginError) {
originalRegistrationAction?.();
} else {
onFail(loginError);
}
});
} else {
onFail(registerError);
}
});
}
}; };
return true; return true;