mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-22 11:31:21 +00:00
9088adeb7a
This PR adds full translation support for all out-of-game UI elements, including the start screen, public/private lobby modals, and other pre-game interfaces. All static text has been externalized to en.json and ja.json for future language support. If you find any spots that are not yet translated (missing from the JSON), please let me know. Thanks a lot! This is a follow-up to PR [#305](https://github.com/openfrontio/OpenFrontIO/pull/305). --------- Co-authored-by: Cldprv <dubois.cnm@tutanota.com> Co-authored-by: jacks0n <rosty.west89@gmail.com>
113 lines
3.2 KiB
TypeScript
113 lines
3.2 KiB
TypeScript
import { LitElement, html } from "lit";
|
|
import { customElement, property, state } from "lit/decorators.js";
|
|
import { v4 as uuidv4 } from "uuid";
|
|
import {
|
|
MAX_USERNAME_LENGTH,
|
|
validateUsername,
|
|
} from "../core/validations/username";
|
|
import { UserSettings } from "../core/game/UserSettings";
|
|
import { translateText } from "../client/Utils";
|
|
|
|
const usernameKey: string = "username";
|
|
|
|
@customElement("username-input")
|
|
export class UsernameInput extends LitElement {
|
|
@state() private username: string = "";
|
|
@property({ type: String }) validationError: string = "";
|
|
private _isValid: boolean = true;
|
|
private userSettings: UserSettings = new UserSettings();
|
|
|
|
// Remove static styles since we're using Tailwind
|
|
|
|
createRenderRoot() {
|
|
// Disable shadow DOM to allow Tailwind classes to work
|
|
return this;
|
|
}
|
|
|
|
public getCurrentUsername(): string {
|
|
return this.username;
|
|
}
|
|
|
|
connectedCallback() {
|
|
super.connectedCallback();
|
|
this.username = this.getStoredUsername();
|
|
this.dispatchUsernameEvent();
|
|
}
|
|
|
|
render() {
|
|
return html`
|
|
<input
|
|
type="text"
|
|
.value=${this.username}
|
|
@input=${this.handleChange}
|
|
@change=${this.handleChange}
|
|
placeholder="${translateText("username.enter_username")}"
|
|
maxlength="${MAX_USERNAME_LENGTH}"
|
|
class="w-full px-4 py-2 border border-gray-300 rounded-xl shadow-sm text-2xl text-center focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:border-gray-300/60 dark:bg-gray-700 dark:text-white"
|
|
/>
|
|
${this.validationError
|
|
? html`<div
|
|
class="mt-2 px-3 py-1 text-lg border rounded bg-white text-red-600 border-red-600 dark:bg-gray-700 dark:text-red-300 dark:border-red-300"
|
|
>
|
|
${this.validationError}
|
|
</div>`
|
|
: null}
|
|
`;
|
|
}
|
|
|
|
private handleChange(e: Event) {
|
|
const input = e.target as HTMLInputElement;
|
|
this.username = input.value.trim();
|
|
const result = validateUsername(this.username);
|
|
this._isValid = result.isValid;
|
|
if (result.isValid) {
|
|
this.storeUsername(this.username);
|
|
this.validationError = "";
|
|
} else {
|
|
this.validationError = result.error;
|
|
}
|
|
}
|
|
|
|
private getStoredUsername(): string {
|
|
const storedUsername = localStorage.getItem(usernameKey);
|
|
if (storedUsername) {
|
|
return storedUsername;
|
|
}
|
|
return this.generateNewUsername();
|
|
}
|
|
|
|
private storeUsername(username: string) {
|
|
if (username) {
|
|
localStorage.setItem(usernameKey, username);
|
|
}
|
|
}
|
|
|
|
private dispatchUsernameEvent() {
|
|
this.dispatchEvent(
|
|
new CustomEvent("username-change", {
|
|
detail: { username: this.username },
|
|
bubbles: true,
|
|
composed: true,
|
|
}),
|
|
);
|
|
}
|
|
|
|
private generateNewUsername(): string {
|
|
const newUsername = "Anon" + this.uuidToThreeDigits();
|
|
this.storeUsername(newUsername);
|
|
return newUsername;
|
|
}
|
|
|
|
private uuidToThreeDigits(): string {
|
|
const uuid = uuidv4();
|
|
const cleanUuid = uuid.replace(/-/g, "").toLowerCase();
|
|
const decimal = BigInt(`0x${cleanUuid}`);
|
|
const threeDigits = decimal % 1000n;
|
|
return threeDigits.toString().padStart(3, "0");
|
|
}
|
|
|
|
public isValid(): boolean {
|
|
return this._isValid;
|
|
}
|
|
}
|