other modals too

This commit is contained in:
Ryan Barlow
2026-05-26 18:59:53 +01:00
parent e2901e72dd
commit c8fc3298f8
3 changed files with 32 additions and 4 deletions
+11 -1
View File
@@ -37,6 +37,7 @@ import "./components/CopyButton";
import "./components/LobbyConfigItem"; import "./components/LobbyConfigItem";
import "./components/LobbyPlayerView"; import "./components/LobbyPlayerView";
import { modalHeader } from "./components/ui/ModalHeader"; import { modalHeader } from "./components/ui/ModalHeader";
import { IdentityReadyController } from "./identity/IdentityReadyController";
import { nationsConfigToSlider } from "./utilities/GameConfigHelpers"; import { nationsConfigToSlider } from "./utilities/GameConfigHelpers";
@customElement("join-lobby-modal") @customElement("join-lobby-modal")
@@ -58,6 +59,7 @@ export class JoinLobbyModal extends BaseModal {
private leaveLobbyOnClose = true; private leaveLobbyOnClose = true;
private countdownTimerId: number | null = null; private countdownTimerId: number | null = null;
private identity = new IdentityReadyController(this);
private handledJoinTimeout = false; private handledJoinTimeout = false;
private isPrivateLobby(): boolean { private isPrivateLobby(): boolean {
@@ -250,9 +252,14 @@ export class JoinLobbyModal extends BaseModal {
></o-button> ></o-button>
</div> </div>
<o-button <o-button
title=${translateText("private_lobby.join_lobby")} title=${
this.identity.validating
? translateText("username.tag_checking")
: translateText("private_lobby.join_lobby")
}
width="block" width="block"
submit submit
?disable=${!this.identity.ready}
></o-button> ></o-button>
</div> </div>
</div> </div>
@@ -891,6 +898,9 @@ export class JoinLobbyModal extends BaseModal {
private async joinLobbyFromInput(e: SubmitEvent): Promise<void> { private async joinLobbyFromInput(e: SubmitEvent): Promise<void> {
e.preventDefault(); e.preventDefault();
// Guard against Enter-key submit while the identity gate hasn't cleared
// (the disabled button blocks click but not keyboard submission).
if (!this.identity.ready) return;
const lobbyId = this.normalizeLobbyId(this.lobbyIdInput.value); const lobbyId = this.normalizeLobbyId(this.lobbyIdInput.value);
if (!lobbyId) { if (!lobbyId) {
this.showMessage(translateText("private_lobby.not_found"), "red"); this.showMessage(translateText("private_lobby.not_found"), "red");
+12 -2
View File
@@ -7,6 +7,7 @@ import { getPlayToken } from "./Auth";
import { BaseModal } from "./components/BaseModal"; import { BaseModal } from "./components/BaseModal";
import "./components/Difficulties"; import "./components/Difficulties";
import { modalHeader } from "./components/ui/ModalHeader"; import { modalHeader } from "./components/ui/ModalHeader";
import { IdentityReadyController } from "./identity/IdentityReadyController";
import { JoinLobbyEvent } from "./Main"; import { JoinLobbyEvent } from "./Main";
import { translateText } from "./Utils"; import { translateText } from "./Utils";
@@ -204,6 +205,7 @@ export class MatchmakingModal extends BaseModal {
@customElement("matchmaking-button") @customElement("matchmaking-button")
export class MatchmakingButton extends LitElement { export class MatchmakingButton extends LitElement {
@state() private isLoggedIn = false; @state() private isLoggedIn = false;
private identity = new IdentityReadyController(this);
constructor() { constructor() {
super(); super();
@@ -226,12 +228,20 @@ export class MatchmakingButton extends LitElement {
} }
render() { render() {
const disabled = this.isLoggedIn && !this.identity.ready;
const title = disabled
? this.identity.validating
? translateText("username.tag_checking")
: translateText("matchmaking_modal.title")
: translateText("matchmaking_modal.title");
return this.isLoggedIn return this.isLoggedIn
? html` ? html`
<button <button
@click="${this.handleLoggedInClick}" @click="${this.handleLoggedInClick}"
class="no-crazygames w-full h-20 bg-purple-600 hover:bg-purple-500 text-white font-black uppercase tracking-widest rounded-xl transition-all duration-200 flex flex-col items-center justify-center group overflow-hidden relative" ?disabled=${disabled}
title="${translateText("matchmaking_modal.title")}" aria-busy=${this.identity.validating ? "true" : "false"}
class="no-crazygames w-full h-20 bg-purple-600 hover:bg-purple-500 text-white font-black uppercase tracking-widest rounded-xl transition-all duration-200 flex flex-col items-center justify-center group overflow-hidden relative disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-purple-600"
title="${title}"
> >
<span class="relative z-10 text-2xl"> <span class="relative z-10 text-2xl">
${translateText("matchmaking_button.play_ranked")} ${translateText("matchmaking_button.play_ranked")}
+9 -1
View File
@@ -3,6 +3,7 @@ import { customElement, state } from "lit/decorators.js";
import { UserMeResponse } from "../../core/ApiSchemas"; import { UserMeResponse } from "../../core/ApiSchemas";
import { getUserMe, hasLinkedAccount } from "../Api"; import { getUserMe, hasLinkedAccount } from "../Api";
import { userAuth } from "../Auth"; import { userAuth } from "../Auth";
import { IdentityReadyController } from "../identity/IdentityReadyController";
import { translateText } from "../Utils"; import { translateText } from "../Utils";
import { BaseModal } from "./BaseModal"; import { BaseModal } from "./BaseModal";
import { modalHeader } from "./ui/ModalHeader"; import { modalHeader } from "./ui/ModalHeader";
@@ -14,6 +15,7 @@ export class RankedModal extends BaseModal {
@state() private elo: number | string = "..."; @state() private elo: number | string = "...";
@state() private userMeResponse: UserMeResponse | false = false; @state() private userMeResponse: UserMeResponse | false = false;
@state() private errorMessage: string | null = null; @state() private errorMessage: string | null = null;
private identity = new IdentityReadyController(this);
constructor() { constructor() {
super(); super();
@@ -118,10 +120,16 @@ export class RankedModal extends BaseModal {
} }
private renderCard(title: string, subtitle: string, onClick: () => void) { private renderCard(title: string, subtitle: string, onClick: () => void) {
const disabled = !this.identity.ready;
return html` return html`
<button <button
@click=${onClick} @click=${onClick}
class="flex flex-col w-full h-28 sm:h-32 rounded-2xl bg-surface border-0 transition-transform hover:scale-[1.02] active:scale-[0.98] p-6 items-center justify-center gap-3" ?disabled=${disabled}
title=${disabled && this.identity.validating
? translateText("username.tag_checking")
: ""}
aria-busy=${this.identity.validating ? "true" : "false"}
class="flex flex-col w-full h-28 sm:h-32 rounded-2xl bg-surface border-0 transition-transform hover:scale-[1.02] active:scale-[0.98] p-6 items-center justify-center gap-3 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100"
> >
<div class="flex flex-col items-center gap-1 text-center"> <div class="flex flex-col items-center gap-1 text-center">
<h3 <h3