From 6719f4177bad14d793ff2a3e70c7764169d7353e Mon Sep 17 00:00:00 2001 From: Ryan <7389646+ryanbarlow97@users.noreply.github.com> Date: Thu, 15 Jan 2026 00:56:50 +0000 Subject: [PATCH] [Bugfix] Login Modal (#2903) If this PR fixes an issue, link it below. If not, delete these two lines. Resolves #2889 ## Description: fixes login in modal: image (theres also one more afterwards but that leaks my email and cba to edit it out) ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: w.o.n --- src/client/LangSelector.ts | 1 + src/client/Main.ts | 4 +- src/client/TokenLoginModal.ts | 96 +++++++++++++++---- src/client/components/PlayPage.ts | 2 +- src/client/components/baseComponents/Modal.ts | 6 ++ 5 files changed, 86 insertions(+), 23 deletions(-) diff --git a/src/client/LangSelector.ts b/src/client/LangSelector.ts index 1ee3329c7..3097ea7a8 100644 --- a/src/client/LangSelector.ts +++ b/src/client/LangSelector.ts @@ -228,6 +228,7 @@ export class LangSelector extends LitElement { "stats-modal", "flag-input-modal", "flag-input", + "token-login", ]; document.title = this.translateText("main.title") ?? document.title; diff --git a/src/client/Main.ts b/src/client/Main.ts index f2cdae39d..88fe223f4 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -687,7 +687,7 @@ class Client { // in case it is unset during reload. this.userSettings.setSelectedPatternName(patternName); }); - this.tokenLoginModal.open(token); + this.tokenLoginModal.openWithToken(token); } else { alertAndStrip(`purchase succeeded: ${patternName}`); this.patternsModal.refresh(); @@ -706,7 +706,7 @@ class Client { } strip(); - this.tokenLoginModal.open(token); + this.tokenLoginModal.openWithToken(token); return; } diff --git a/src/client/TokenLoginModal.ts b/src/client/TokenLoginModal.ts index cb7ef143e..97f0b3043 100644 --- a/src/client/TokenLoginModal.ts +++ b/src/client/TokenLoginModal.ts @@ -1,17 +1,14 @@ -import { html, LitElement } from "lit"; -import { customElement, query } from "lit/decorators.js"; +import { html } from "lit"; +import { customElement } from "lit/decorators.js"; import { tempTokenLogin } from "./Auth"; +import { BaseModal } from "./components/BaseModal"; import "./components/Difficulties"; import "./components/PatternButton"; +import { modalHeader } from "./components/ui/ModalHeader"; import { translateText } from "./Utils"; @customElement("token-login") -export class TokenLoginModal extends LitElement { - @query("o-modal") private modalEl!: HTMLElement & { - open: () => void; - close: () => void; - }; - +export class TokenLoginModal extends BaseModal { private isAttemptingLogin = false; private retryInterval: NodeJS.Timeout | undefined = undefined; @@ -27,39 +24,98 @@ export class TokenLoginModal extends LitElement { } render() { + const title = translateText("token_login_modal.title"); + const content = html` +
+ ${modalHeader({ + title, + onBack: () => this.close(), + ariaLabel: translateText("common.back"), + })} +
+ ${this.email ? this.loginSuccess(this.email) : this.loggingIn()} +
+
+ `; + + if (this.inline) { + return content; + } + return html` - ${this.email ? this.loginSuccess(this.email) : this.loggingIn()} + ${content} `; } private loggingIn() { - return html`

${translateText("token_login_modal.logging_in")}

`; + const loggingText = translateText("token_login_modal.logging_in"); + return html` +
+
+
+
+
+

${loggingText}

+
+
+
+
+
+ `; } private loginSuccess(email: string) { - return html`

- ${translateText("token_login_modal.success", { - email, - })} -

`; + const successText = translateText("token_login_modal.success", { email }); + return html` +
+
+
+
+

${successText}

+
+ `; } - public async open(token: string) { - this.token = token; - this.modalEl?.open(); + public open(): void { + if (!this.token) { + return; + } + super.open(); + clearInterval(this.retryInterval); this.retryInterval = setInterval(() => this.tryLogin(), 3000); } + public openWithToken(token: string): void { + this.token = token; + this.email = null; + this.attemptCount = 0; + this.isAttemptingLogin = false; + this.open(); + } + public close() { this.token = null; clearInterval(this.retryInterval); this.attemptCount = 0; - this.modalEl?.close(); + super.close(); this.isAttemptingLogin = false; } diff --git a/src/client/components/PlayPage.ts b/src/client/components/PlayPage.ts index 15dd47d56..d785f1a62 100644 --- a/src/client/components/PlayPage.ts +++ b/src/client/components/PlayPage.ts @@ -13,7 +13,7 @@ export class PlayPage extends LitElement { id="page-play" class="flex flex-col gap-2 w-full max-w-6xl mx-auto px-0 sm:px-4 transition-all duration-300 my-auto min-h-0" > - +
diff --git a/src/client/components/baseComponents/Modal.ts b/src/client/components/baseComponents/Modal.ts index 7ef216ffc..3094faf99 100644 --- a/src/client/components/baseComponents/Modal.ts +++ b/src/client/components/baseComponents/Modal.ts @@ -25,6 +25,9 @@ export class OModal extends LitElement { @property({ type: Boolean }) public hideHeader = false; + @property({ type: String }) + public maxWidth = ""; + public onClose?: () => void; public open() { @@ -67,6 +70,8 @@ export class OModal extends LitElement { : `relative flex flex-col w-[90%] min-w-[400px] max-w-[900px] m-8 rounded-lg shadow-[0_20px_60px_rgba(0,0,0,0.8)] max-h-[calc(100vh-4rem)] ${ this.alwaysMaximized ? "h-auto" : "" }`; + const wrapperStyle = + !this.inline && this.maxWidth ? `max-width: ${this.maxWidth};` : ""; return html` ${this.isModalOpen @@ -78,6 +83,7 @@ export class OModal extends LitElement {
e.stopPropagation()} class="${wrapperClass}" + style="${wrapperStyle}" > ${this.inline || this.hideCloseButton ? html``