mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 12:10:15 +00:00
[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: <img width="782" height="330" alt="image" src="https://github.com/user-attachments/assets/60f1825f-5678-4853-a78b-bbed5198b0fb" /> (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
This commit is contained in:
@@ -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;
|
||||
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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`
|
||||
<div
|
||||
class="h-full flex flex-col ${this.inline
|
||||
? "bg-black/60 backdrop-blur-md rounded-2xl border border-white/10 overflow-hidden"
|
||||
: ""}"
|
||||
>
|
||||
${modalHeader({
|
||||
title,
|
||||
onBack: () => this.close(),
|
||||
ariaLabel: translateText("common.back"),
|
||||
})}
|
||||
<div class="flex-1 flex flex-col gap-4 p-6">
|
||||
${this.email ? this.loginSuccess(this.email) : this.loggingIn()}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
if (this.inline) {
|
||||
return content;
|
||||
}
|
||||
|
||||
return html`
|
||||
<o-modal
|
||||
id="token-login-modal"
|
||||
title="${translateText("token_login_modal.title")}"
|
||||
title="${title}"
|
||||
hideHeader
|
||||
hideCloseButton
|
||||
maxWidth="620px"
|
||||
>
|
||||
${this.email ? this.loginSuccess(this.email) : this.loggingIn()}
|
||||
${content}
|
||||
</o-modal>
|
||||
`;
|
||||
}
|
||||
|
||||
private loggingIn() {
|
||||
return html` <p>${translateText("token_login_modal.logging_in")}</p> `;
|
||||
const loggingText = translateText("token_login_modal.logging_in");
|
||||
return html`
|
||||
<div class="flex items-center gap-4">
|
||||
<div
|
||||
class="w-12 h-12 rounded-full border border-blue-400/40 bg-blue-500/10 flex items-center justify-center"
|
||||
>
|
||||
<div
|
||||
class="w-6 h-6 border-2 border-blue-400/30 border-t-blue-400 rounded-full animate-spin"
|
||||
></div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<p class="text-lg font-semibold text-white">${loggingText}</p>
|
||||
<div class="h-1 w-full bg-white/10 rounded-full overflow-hidden">
|
||||
<div class="h-full w-1/2 bg-blue-400/80 animate-pulse"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
private loginSuccess(email: string) {
|
||||
return html`<p>
|
||||
${translateText("token_login_modal.success", {
|
||||
email,
|
||||
})}
|
||||
</p> `;
|
||||
const successText = translateText("token_login_modal.success", { email });
|
||||
return html`
|
||||
<div class="flex items-center gap-4">
|
||||
<div
|
||||
class="w-12 h-12 rounded-full border border-emerald-400/40 bg-emerald-500/10 flex items-center justify-center"
|
||||
>
|
||||
<div class="w-2 h-2 bg-emerald-400 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
<p class="text-base text-white/90">${successText}</p>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
>
|
||||
<token-login class="w-full hidden"></token-login>
|
||||
<token-login class="absolute"></token-login>
|
||||
|
||||
<!-- Header / Identity Section -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-12 gap-2 lg:gap-6 w-full">
|
||||
|
||||
@@ -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 {
|
||||
<div
|
||||
@click=${(e: Event) => e.stopPropagation()}
|
||||
class="${wrapperClass}"
|
||||
style="${wrapperStyle}"
|
||||
>
|
||||
${this.inline || this.hideCloseButton
|
||||
? html``
|
||||
|
||||
Reference in New Issue
Block a user