diff --git a/client/index.html b/client/index.html index c7de718..d20c926 100644 --- a/client/index.html +++ b/client/index.html @@ -42,6 +42,10 @@

+
diff --git a/client/public/version.js b/client/public/version.js index 2bc04bc..a2d7d4f 100644 --- a/client/public/version.js +++ b/client/public/version.js @@ -1,5 +1,5 @@ // Maintainer-controlled web client version. // Format: YYYY.MM.DD Rn (example: 2026.02.20 R2) -window.CHGRID_WEB_VERSION = "2026.02.25 R248"; +window.CHGRID_WEB_VERSION = "2026.02.25 R249"; // Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid. window.CHGRID_TIME_ZONE = "America/Detroit"; diff --git a/client/src/main.ts b/client/src/main.ts index 34364ac..58b0449 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -100,6 +100,8 @@ type Dom = { registerPasswordConfirm: HTMLInputElement; registerEmail: HTMLInputElement; authPolicyHintRegister: HTMLParagraphElement; + authSessionView: HTMLElement; + authSessionText: HTMLParagraphElement; showRegisterButton: HTMLButtonElement; showLoginButton: HTMLButtonElement; updatesSection: HTMLElement; @@ -133,6 +135,8 @@ const dom: Dom = { registerPasswordConfirm: requiredById('registerPasswordConfirm'), registerEmail: requiredById('registerEmail'), authPolicyHintRegister: requiredById('authPolicyHintRegister'), + authSessionView: requiredById('authSessionView'), + authSessionText: requiredById('authSessionText'), showRegisterButton: requiredById('showRegisterButton'), showLoginButton: requiredById('showLoginButton'), updatesSection: requiredById('updatesSection'), @@ -587,10 +591,20 @@ function updateConnectAvailability(): void { dom.connectButton.disabled = true; dom.loginView.classList.add('hidden'); dom.registerView.classList.add('hidden'); + dom.authSessionView.classList.add('hidden'); return; } - dom.loginView.classList.toggle('hidden', authMode !== 'login'); - dom.registerView.classList.toggle('hidden', authMode !== 'register'); + if (hasSessionToken) { + const label = sanitizeAuthUsername(authUsername) || 'current account'; + dom.authSessionText.textContent = `Logged in as ${label}.`; + dom.loginView.classList.add('hidden'); + dom.registerView.classList.add('hidden'); + dom.authSessionView.classList.remove('hidden'); + } else { + dom.loginView.classList.toggle('hidden', authMode !== 'login'); + dom.registerView.classList.toggle('hidden', authMode !== 'register'); + dom.authSessionView.classList.add('hidden'); + } const usernameMin = authPolicy?.usernameMinLength ?? 1; const passwordMin = authPolicy?.passwordMinLength ?? 1; const hasLoginCredentials = @@ -1115,8 +1129,9 @@ function formatCoordinate(value: number): string { /** Persists current local player coordinates for reconnect/refresh restore. */ function persistPlayerPosition(): void { try { + const positionKey = getPlayerPositionStorageKey(); localStorage.setItem( - 'spatialChatPosition', + positionKey, JSON.stringify({ x: state.player.x, y: state.player.y }), ); } catch { @@ -1126,7 +1141,7 @@ function persistPlayerPosition(): void { /** Loads previously persisted local player coordinates, when available and valid. */ function getPersistedPlayerPosition(): { x: number; y: number } | null { - const raw = localStorage.getItem('spatialChatPosition'); + const raw = localStorage.getItem(getPlayerPositionStorageKey()); if (!raw) return null; try { const parsed = JSON.parse(raw) as { x?: unknown; y?: unknown }; @@ -1138,6 +1153,12 @@ function getPersistedPlayerPosition(): { x: number; y: number } | null { } } +/** Resolves local storage key for per-account saved player position. */ +function getPlayerPositionStorageKey(): string { + const usernameKey = sanitizeAuthUsername(authUsername); + return usernameKey ? `spatialChatPosition:${usernameKey}` : 'spatialChatPosition'; +} + /** Picks one random footstep sample URL. */ function randomFootstepUrl(): string { return FOOTSTEP_SOUND_URLS[Math.floor(Math.random() * FOOTSTEP_SOUND_URLS.length)]; diff --git a/client/src/styles.css b/client/src/styles.css index 623bffd..633fbec 100644 --- a/client/src/styles.css +++ b/client/src/styles.css @@ -123,6 +123,11 @@ body { font-size: 0.92rem; } +#authSessionText { + margin: 0; + color: #cbd5e1; +} + .nickname-row { display: flex; justify-content: center;