diff --git a/src/system/settings/settings-language.ts b/src/system/settings/settings-language.ts index b1df2444507..0c7cbb400aa 100644 --- a/src/system/settings/settings-language.ts +++ b/src/system/settings/settings-language.ts @@ -1,4 +1,5 @@ import { globalScene } from "#app/global-scene"; +import type { LoginRegisterInfoContainerUiHandler } from "#ui/login-register-info-container-ui-handler"; import type { SettingsDisplayUiHandler } from "#ui/settings-display-ui-handler"; import i18next from "i18next"; @@ -8,6 +9,8 @@ const cancelHandler = () => { // Reset the cursor to the current language, if in the settings menu if (handler && typeof (handler as SettingsDisplayUiHandler).setOptionCursor === "function") { (handler as SettingsDisplayUiHandler).setOptionCursor(-1, 0, true); + } else if (handler && typeof (handler as LoginRegisterInfoContainerUiHandler).setInteractive === "function") { + (handler as LoginRegisterInfoContainerUiHandler).setInteractive(true); } }; diff --git a/src/ui/handlers/login-register-info-container-ui-handler.ts b/src/ui/handlers/login-register-info-container-ui-handler.ts index 556ab94e15f..531a78e18b4 100644 --- a/src/ui/handlers/login-register-info-container-ui-handler.ts +++ b/src/ui/handlers/login-register-info-container-ui-handler.ts @@ -7,6 +7,7 @@ import type { ModalConfig } from "#ui/modal-ui-handler"; import { fixedInt } from "#utils/common"; import i18next from "i18next"; import JSZip from "jszip"; +import type InputText from "phaser3-rex-plugins/plugins/inputtext"; interface BuildInteractableImageOpts { scale?: number; @@ -36,6 +37,7 @@ export abstract class LoginRegisterInfoContainerUiHandler extends FormModalUiHan private saveDownloadImage: Phaser.GameObjects.Image; private changeLanguageImage: Phaser.GameObjects.Image; private infoContainer: Phaser.GameObjects.Container; + private lastFocusedInput: InputText | null = null; public override getReadableErrorMessage(error: string): string { if (!error) { @@ -109,6 +111,7 @@ export abstract class LoginRegisterInfoContainerUiHandler extends FormModalUiHan this.changeLanguageImage // .setPositionRelative(this.infoContainer, 40, 0) .on("pointerdown", () => { + this.setInteractive(false); globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, { options: languageOptions, maxOptions: 7, @@ -154,6 +157,7 @@ export abstract class LoginRegisterInfoContainerUiHandler extends FormModalUiHan const handler = () => { globalScene.ui.revertMode(); this.infoContainer.disableInteractive(); + this.setInteractive(true); return true; }; @@ -162,6 +166,7 @@ export abstract class LoginRegisterInfoContainerUiHandler extends FormModalUiHan } globalScene.ui.setOverlayMode(UiMode.OPTION_SELECT, { options, delay: 1000 }); + this.setInteractive(false); this.infoContainer.setInteractive( new Phaser.Geom.Rectangle(0, 0, globalScene.game.canvas.width, globalScene.game.canvas.height), Phaser.Geom.Rectangle.Contains, @@ -230,4 +235,45 @@ export abstract class LoginRegisterInfoContainerUiHandler extends FormModalUiHan return img; } + + /** + * Enable or disable interactivity on all interactive objects. + * @param active - Whether to enable or disable interactivity + */ + public setInteractive(active: boolean): void { + const objects = [...this.buttonBgs, this.usernameInfoImage, this.saveDownloadImage, this.changeLanguageImage]; + + for (const obj of objects) { + if (active) { + obj.setInteractive(); + } else { + obj.disableInteractive(); + if (obj instanceof Phaser.GameObjects.Image) { + obj.clearTint(); + } + } + } + + this.setInteractiveInputs(active); + this.setMouseCursorStyle("default"); + } + + /** + * Enable or disable interactivity on all input fields. + * @param active - Whether to enable or disable interactivity + */ + private setInteractiveInputs(active: boolean): void { + if (active) { + // `setFocus` doesn't focus without a timeout + setTimeout(() => { + this.lastFocusedInput?.setFocus(); + this.lastFocusedInput = null; + }, 50); + } else { + this.lastFocusedInput = this.inputs.find(input => input.isFocused) ?? null; + } + for (const input of this.inputs) { + (input.node as HTMLInputElement).disabled = !active; + } + } } diff --git a/src/ui/handlers/oauth-providers-ui-handler.ts b/src/ui/handlers/oauth-providers-ui-handler.ts index 8839f6880a1..9500e0b5697 100644 --- a/src/ui/handlers/oauth-providers-ui-handler.ts +++ b/src/ui/handlers/oauth-providers-ui-handler.ts @@ -56,6 +56,18 @@ export abstract class OAuthProvidersUiHandler extends LoginRegisterInfoContainer this.getUi().add(this.externalPartyContainer); } + public override setInteractive(active: boolean): void { + super.setInteractive(active); + const externalPartyIcons = this.externalPartyContainer.list.filter(obj => obj instanceof Phaser.GameObjects.Image); + for (const obj of externalPartyIcons) { + if (active) { + obj.setInteractive(); + } else { + obj.disableInteractive(); + } + } + } + protected processExternalProvider(): void { const titleX = 22; this.externalPartyTitle