Fix auth landing flow and up.sh service fallback
This commit is contained in:
@@ -37,10 +37,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<button id="showLoginButton" type="button">Back to login</button>
|
<button id="showLoginButton" type="button">Back to login</button>
|
||||||
</section>
|
</section>
|
||||||
<div id="nicknameContainer" class="nickname-row">
|
|
||||||
<label for="preconnectNickname">Nickname</label>
|
|
||||||
<input id="preconnectNickname" type="text" maxlength="32" autocomplete="nickname" />
|
|
||||||
</div>
|
|
||||||
<div class="controls" id="button-container">
|
<div class="controls" id="button-container">
|
||||||
<button id="connectButton">Connect</button>
|
<button id="connectButton">Connect</button>
|
||||||
<button id="logoutButton">Log out</button>
|
<button id="logoutButton">Log out</button>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// Maintainer-controlled web client version.
|
// Maintainer-controlled web client version.
|
||||||
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
||||||
window.CHGRID_WEB_VERSION = "2026.02.25 R243";
|
window.CHGRID_WEB_VERSION = "2026.02.25 R244";
|
||||||
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
|
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
|
||||||
window.CHGRID_TIME_ZONE = "America/Detroit";
|
window.CHGRID_TIME_ZONE = "America/Detroit";
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ import {
|
|||||||
import { createItemPropertyEditor } from './items/itemPropertyEditor';
|
import { createItemPropertyEditor } from './items/itemPropertyEditor';
|
||||||
import { createItemPropertyPresentation } from './items/itemPropertyPresentation';
|
import { createItemPropertyPresentation } from './items/itemPropertyPresentation';
|
||||||
import { ItemBehaviorRegistry } from './items/types/behaviorRegistry';
|
import { ItemBehaviorRegistry } from './items/types/behaviorRegistry';
|
||||||
import { NICKNAME_STORAGE_KEY, SettingsStore } from './settings/settingsStore';
|
import { SettingsStore } from './settings/settingsStore';
|
||||||
import { runConnectFlow, runDisconnectFlow, type ConnectFlowDeps } from './session/connectionFlow';
|
import { runConnectFlow, runDisconnectFlow, type ConnectFlowDeps } from './session/connectionFlow';
|
||||||
import { MediaSession } from './session/mediaSession';
|
import { MediaSession } from './session/mediaSession';
|
||||||
import { type AudioLayerState } from './types/audio';
|
import { type AudioLayerState } from './types/audio';
|
||||||
@@ -102,8 +102,6 @@ type Dom = {
|
|||||||
updatesSection: HTMLElement;
|
updatesSection: HTMLElement;
|
||||||
updatesToggle: HTMLButtonElement;
|
updatesToggle: HTMLButtonElement;
|
||||||
updatesPanel: HTMLDivElement;
|
updatesPanel: HTMLDivElement;
|
||||||
nicknameContainer: HTMLDivElement;
|
|
||||||
preconnectNickname: HTMLInputElement;
|
|
||||||
connectButton: HTMLButtonElement;
|
connectButton: HTMLButtonElement;
|
||||||
logoutButton: HTMLButtonElement;
|
logoutButton: HTMLButtonElement;
|
||||||
disconnectButton: HTMLButtonElement;
|
disconnectButton: HTMLButtonElement;
|
||||||
@@ -135,8 +133,6 @@ const dom: Dom = {
|
|||||||
updatesSection: requiredById('updatesSection'),
|
updatesSection: requiredById('updatesSection'),
|
||||||
updatesToggle: requiredById('updatesToggle'),
|
updatesToggle: requiredById('updatesToggle'),
|
||||||
updatesPanel: requiredById('updatesPanel'),
|
updatesPanel: requiredById('updatesPanel'),
|
||||||
nicknameContainer: requiredById('nicknameContainer'),
|
|
||||||
preconnectNickname: requiredById('preconnectNickname'),
|
|
||||||
connectButton: requiredById('connectButton'),
|
connectButton: requiredById('connectButton'),
|
||||||
logoutButton: requiredById('logoutButton'),
|
logoutButton: requiredById('logoutButton'),
|
||||||
disconnectButton: requiredById('disconnectButton'),
|
disconnectButton: requiredById('disconnectButton'),
|
||||||
@@ -519,6 +515,7 @@ function sanitizeAuthUsername(value: string): string {
|
|||||||
function updateConnectAvailability(): void {
|
function updateConnectAvailability(): void {
|
||||||
dom.logoutButton.disabled = !authSessionToken.trim() && !state.running;
|
dom.logoutButton.disabled = !authSessionToken.trim() && !state.running;
|
||||||
if (state.running) {
|
if (state.running) {
|
||||||
|
dom.connectButton.textContent = 'Connect';
|
||||||
dom.connectButton.disabled = true;
|
dom.connectButton.disabled = true;
|
||||||
dom.loginView.classList.add('hidden');
|
dom.loginView.classList.add('hidden');
|
||||||
dom.registerView.classList.add('hidden');
|
dom.registerView.classList.add('hidden');
|
||||||
@@ -532,6 +529,7 @@ function updateConnectAvailability(): void {
|
|||||||
const hasRegisterCredentials =
|
const hasRegisterCredentials =
|
||||||
sanitizeAuthUsername(dom.registerUsername.value).length >= 2 && dom.registerPassword.value.trim().length >= 8;
|
sanitizeAuthUsername(dom.registerUsername.value).length >= 2 && dom.registerPassword.value.trim().length >= 8;
|
||||||
const authReady = hasSessionToken || (authMode === 'login' ? hasLoginCredentials : hasRegisterCredentials);
|
const authReady = hasSessionToken || (authMode === 'login' ? hasLoginCredentials : hasRegisterCredentials);
|
||||||
|
dom.connectButton.textContent = hasSessionToken ? 'Connect' : authMode === 'login' ? 'Log In & Connect' : 'Register & Connect';
|
||||||
dom.connectButton.disabled = mediaSession.isConnecting() || !authReady;
|
dom.connectButton.disabled = mediaSession.isConnecting() || !authReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1419,8 +1417,6 @@ async function handleAuthResult(message: Extract<IncomingMessage, { type: 'auth_
|
|||||||
const resolved = sanitizeName(message.nickname);
|
const resolved = sanitizeName(message.nickname);
|
||||||
if (resolved) {
|
if (resolved) {
|
||||||
state.player.nickname = resolved;
|
state.player.nickname = resolved;
|
||||||
dom.preconnectNickname.value = resolved;
|
|
||||||
settings.saveNickname(resolved);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dom.authPassword.value = '';
|
dom.authPassword.value = '';
|
||||||
@@ -1561,7 +1557,6 @@ const onAppMessage = createOnMessageHandler({
|
|||||||
audioUiBlip: () => audio.sfxUiBlip(),
|
audioUiBlip: () => audio.sfxUiBlip(),
|
||||||
audioUiConfirm: () => audio.sfxUiConfirm(),
|
audioUiConfirm: () => audio.sfxUiConfirm(),
|
||||||
audioUiCancel: () => audio.sfxUiCancel(),
|
audioUiCancel: () => audio.sfxUiCancel(),
|
||||||
NICKNAME_STORAGE_KEY,
|
|
||||||
getCarriedItemId: () => getCarriedItem()?.id ?? null,
|
getCarriedItemId: () => getCarriedItem()?.id ?? null,
|
||||||
recomputeActiveItemPropertyKeys,
|
recomputeActiveItemPropertyKeys,
|
||||||
itemPropertyLabel,
|
itemPropertyLabel,
|
||||||
@@ -2558,8 +2553,6 @@ function closeSettings(): void {
|
|||||||
function setupUiHandlers(): void {
|
function setupUiHandlers(): void {
|
||||||
setupDomUiHandlers({
|
setupDomUiHandlers({
|
||||||
dom,
|
dom,
|
||||||
sanitizeName,
|
|
||||||
nicknameStorageKey: NICKNAME_STORAGE_KEY,
|
|
||||||
updateConnectAvailability,
|
updateConnectAvailability,
|
||||||
connect,
|
connect,
|
||||||
disconnect,
|
disconnect,
|
||||||
@@ -2615,11 +2608,6 @@ setupInputHandlers();
|
|||||||
setupUiHandlers();
|
setupUiHandlers();
|
||||||
dom.authUsername.value = sanitizeAuthUsername(authUsername);
|
dom.authUsername.value = sanitizeAuthUsername(authUsername);
|
||||||
dom.registerUsername.value = sanitizeAuthUsername(authUsername);
|
dom.registerUsername.value = sanitizeAuthUsername(authUsername);
|
||||||
const storedNickname = sanitizeName(settings.loadNickname());
|
|
||||||
dom.preconnectNickname.value = storedNickname;
|
|
||||||
if (storedNickname) {
|
|
||||||
state.player.nickname = storedNickname;
|
|
||||||
}
|
|
||||||
setAuthMode('login');
|
setAuthMode('login');
|
||||||
updateConnectAvailability();
|
updateConnectAvailability();
|
||||||
updateDeviceSummary();
|
updateDeviceSummary();
|
||||||
|
|||||||
@@ -25,13 +25,11 @@ type MessageHandlerDeps = {
|
|||||||
carriedItemId: string | null;
|
carriedItemId: string | null;
|
||||||
};
|
};
|
||||||
dom: {
|
dom: {
|
||||||
nicknameContainer: HTMLElement;
|
|
||||||
connectButton: HTMLElement;
|
connectButton: HTMLElement;
|
||||||
disconnectButton: HTMLElement;
|
disconnectButton: HTMLElement;
|
||||||
focusGridButton: HTMLElement;
|
focusGridButton: HTMLElement;
|
||||||
canvas: HTMLCanvasElement;
|
canvas: HTMLCanvasElement;
|
||||||
instructions: HTMLElement;
|
instructions: HTMLElement;
|
||||||
preconnectNickname: HTMLInputElement;
|
|
||||||
};
|
};
|
||||||
signalingSend: (message: unknown) => void;
|
signalingSend: (message: unknown) => void;
|
||||||
peerManager: {
|
peerManager: {
|
||||||
@@ -63,7 +61,6 @@ type MessageHandlerDeps = {
|
|||||||
audioUiBlip: () => void;
|
audioUiBlip: () => void;
|
||||||
audioUiConfirm: () => void;
|
audioUiConfirm: () => void;
|
||||||
audioUiCancel: () => void;
|
audioUiCancel: () => void;
|
||||||
NICKNAME_STORAGE_KEY: string;
|
|
||||||
getCarriedItemId: () => string | null;
|
getCarriedItemId: () => string | null;
|
||||||
recomputeActiveItemPropertyKeys: (itemId: string) => void;
|
recomputeActiveItemPropertyKeys: (itemId: string) => void;
|
||||||
itemPropertyLabel: (key: string) => string;
|
itemPropertyLabel: (key: string) => string;
|
||||||
@@ -113,7 +110,6 @@ export function createOnMessageHandler(deps: MessageHandlerDeps): (message: Inco
|
|||||||
const targetY = persistedPosition?.y ?? message.player.y;
|
const targetY = persistedPosition?.y ?? message.player.y;
|
||||||
deps.state.player.x = Math.max(0, Math.min(deps.getWorldGridSize() - 1, targetX));
|
deps.state.player.x = Math.max(0, Math.min(deps.getWorldGridSize() - 1, targetX));
|
||||||
deps.state.player.y = Math.max(0, Math.min(deps.getWorldGridSize() - 1, targetY));
|
deps.state.player.y = Math.max(0, Math.min(deps.getWorldGridSize() - 1, targetY));
|
||||||
deps.dom.nicknameContainer.classList.add('hidden');
|
|
||||||
deps.dom.connectButton.classList.add('hidden');
|
deps.dom.connectButton.classList.add('hidden');
|
||||||
deps.dom.disconnectButton.classList.remove('hidden');
|
deps.dom.disconnectButton.classList.remove('hidden');
|
||||||
deps.dom.focusGridButton.classList.remove('hidden');
|
deps.dom.focusGridButton.classList.remove('hidden');
|
||||||
@@ -228,8 +224,8 @@ export function createOnMessageHandler(deps: MessageHandlerDeps): (message: Inco
|
|||||||
case 'nickname_result': {
|
case 'nickname_result': {
|
||||||
deps.state.player.nickname = deps.sanitizeName(message.effectiveNickname) || 'user...';
|
deps.state.player.nickname = deps.sanitizeName(message.effectiveNickname) || 'user...';
|
||||||
if (message.accepted) {
|
if (message.accepted) {
|
||||||
deps.dom.preconnectNickname.value = deps.state.player.nickname;
|
deps.updateStatus(`Nickname set to ${deps.state.player.nickname}`);
|
||||||
localStorage.setItem(deps.NICKNAME_STORAGE_KEY, deps.state.player.nickname);
|
deps.audioUiConfirm();
|
||||||
} else {
|
} else {
|
||||||
deps.pushChatMessage(message.reason || 'Nickname unavailable.');
|
deps.pushChatMessage(message.reason || 'Nickname unavailable.');
|
||||||
deps.audioUiCancel();
|
deps.audioUiCancel();
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ import type { GameState } from '../state/gameState';
|
|||||||
const WELCOME_TIMEOUT_MS = 8_000;
|
const WELCOME_TIMEOUT_MS = 8_000;
|
||||||
|
|
||||||
type DomRefs = {
|
type DomRefs = {
|
||||||
preconnectNickname: HTMLInputElement;
|
|
||||||
nicknameContainer: HTMLDivElement;
|
|
||||||
connectButton: HTMLButtonElement;
|
connectButton: HTMLButtonElement;
|
||||||
disconnectButton: HTMLButtonElement;
|
disconnectButton: HTMLButtonElement;
|
||||||
focusGridButton: HTMLButtonElement;
|
focusGridButton: HTMLButtonElement;
|
||||||
@@ -40,15 +38,14 @@ export type ConnectFlowDeps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs connect flow: validate nickname, preflight mic/device setup, then signaling connect.
|
* Runs connect flow: preflight media setup, then signaling connect/auth.
|
||||||
*/
|
*/
|
||||||
export async function runConnectFlow(deps: ConnectFlowDeps): Promise<void> {
|
export async function runConnectFlow(deps: ConnectFlowDeps): Promise<void> {
|
||||||
if (deps.mediaIsConnecting() || deps.state.running) {
|
if (deps.mediaIsConnecting() || deps.state.running) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const nickname = deps.sanitizeName(deps.dom.preconnectNickname.value);
|
const nickname = deps.sanitizeName(deps.state.player.nickname);
|
||||||
deps.state.player.nickname = nickname || deps.state.player.nickname;
|
deps.state.player.nickname = nickname || deps.state.player.nickname;
|
||||||
deps.dom.preconnectNickname.value = nickname;
|
|
||||||
if (nickname) {
|
if (nickname) {
|
||||||
deps.settingsSaveNickname(nickname);
|
deps.settingsSaveNickname(nickname);
|
||||||
}
|
}
|
||||||
@@ -138,7 +135,6 @@ export function runDisconnectFlow(deps: ConnectFlowDeps): void {
|
|||||||
deps.state.effectSelectIndex = 0;
|
deps.state.effectSelectIndex = 0;
|
||||||
|
|
||||||
deps.mediaSetConnecting(false);
|
deps.mediaSetConnecting(false);
|
||||||
deps.dom.nicknameContainer.classList.remove('hidden');
|
|
||||||
deps.dom.connectButton.classList.remove('hidden');
|
deps.dom.connectButton.classList.remove('hidden');
|
||||||
deps.dom.disconnectButton.classList.add('hidden');
|
deps.dom.disconnectButton.classList.add('hidden');
|
||||||
deps.dom.focusGridButton.classList.add('hidden');
|
deps.dom.focusGridButton.classList.add('hidden');
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
type UiDom = {
|
type UiDom = {
|
||||||
connectButton: HTMLButtonElement;
|
connectButton: HTMLButtonElement;
|
||||||
preconnectNickname: HTMLInputElement;
|
|
||||||
disconnectButton: HTMLButtonElement;
|
disconnectButton: HTMLButtonElement;
|
||||||
focusGridButton: HTMLButtonElement;
|
focusGridButton: HTMLButtonElement;
|
||||||
settingsButton: HTMLButtonElement;
|
settingsButton: HTMLButtonElement;
|
||||||
@@ -19,8 +18,6 @@ type UiDom = {
|
|||||||
*/
|
*/
|
||||||
type UiBindingsDeps = {
|
type UiBindingsDeps = {
|
||||||
dom: UiDom;
|
dom: UiDom;
|
||||||
sanitizeName: (value: string) => string;
|
|
||||||
nicknameStorageKey: string;
|
|
||||||
updateConnectAvailability: () => void;
|
updateConnectAvailability: () => void;
|
||||||
connect: () => Promise<void>;
|
connect: () => Promise<void>;
|
||||||
disconnect: () => void;
|
disconnect: () => void;
|
||||||
@@ -46,25 +43,6 @@ export function setupUiHandlers(deps: UiBindingsDeps): void {
|
|||||||
deps.dom.connectButton.addEventListener('click', () => {
|
deps.dom.connectButton.addEventListener('click', () => {
|
||||||
void deps.connect();
|
void deps.connect();
|
||||||
});
|
});
|
||||||
deps.dom.preconnectNickname.addEventListener('input', () => {
|
|
||||||
deps.updateConnectAvailability();
|
|
||||||
});
|
|
||||||
deps.dom.preconnectNickname.addEventListener('change', () => {
|
|
||||||
const clean = deps.sanitizeName(deps.dom.preconnectNickname.value);
|
|
||||||
deps.dom.preconnectNickname.value = clean;
|
|
||||||
if (clean) {
|
|
||||||
localStorage.setItem(deps.nicknameStorageKey, clean);
|
|
||||||
} else {
|
|
||||||
localStorage.removeItem(deps.nicknameStorageKey);
|
|
||||||
}
|
|
||||||
deps.updateConnectAvailability();
|
|
||||||
});
|
|
||||||
deps.dom.preconnectNickname.addEventListener('keydown', (event) => {
|
|
||||||
if (event.key === 'Enter' && !deps.dom.connectButton.disabled) {
|
|
||||||
event.preventDefault();
|
|
||||||
void deps.connect();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
deps.dom.disconnectButton.addEventListener('click', () => {
|
deps.dom.disconnectButton.addEventListener('click', () => {
|
||||||
deps.disconnect();
|
deps.disconnect();
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ REPO_ROOT="${1:-/home/bestmidi/chgrid}"
|
|||||||
PUBLISH_DIR="${2:-/home/bestmidi/public_html/chgrid}"
|
PUBLISH_DIR="${2:-/home/bestmidi/public_html/chgrid}"
|
||||||
BASE_PATH="${3:-/chgrid/}"
|
BASE_PATH="${3:-/chgrid/}"
|
||||||
SERVICE_NAME="${4:-chat-grid.service}"
|
SERVICE_NAME="${4:-chat-grid.service}"
|
||||||
|
if [[ -z "${SERVICE_NAME// }" || "$SERVICE_NAME" == "-" || "$SERVICE_NAME" == ".service" ]]; then
|
||||||
|
SERVICE_NAME="chat-grid.service"
|
||||||
|
fi
|
||||||
|
|
||||||
"$REPO_ROOT/deploy/scripts/deploy_client.sh" "$REPO_ROOT" "$PUBLISH_DIR" "$BASE_PATH"
|
"$REPO_ROOT/deploy/scripts/deploy_client.sh" "$REPO_ROOT" "$PUBLISH_DIR" "$BASE_PATH"
|
||||||
sudo systemctl restart "$SERVICE_NAME"
|
sudo systemctl restart "$SERVICE_NAME"
|
||||||
|
|||||||
Reference in New Issue
Block a user