From 1a1ed4e1d0568a1610d5f5da3d541a59afe2b863 Mon Sep 17 00:00:00 2001 From: David Skoland Date: Tue, 24 Mar 2026 12:23:45 +0100 Subject: Add reconnect UI, disconnect button, and visual cleanup - Redesign disconnect overlay as a full-screen modal with dark backdrop - Add working Reconnect button that properly re-establishes WebSocket connection - Add Disconnect button in Settings for testing - Separate disconnect and ban/kick codepaths (no reconnect on ban) - Log disconnect notice in IC log using hrtext style - Refactor area list rendering from client state (renderAreaList) - Extract appendICNotice for reusable IC log notices - Clean up charselect: hide during loading, simplify toolbar layout - Freshen loading screen and charselect styling - Remove loading progress text updates (just show "Loading...") - Guard against undefined client.chars and client.serv Co-Authored-By: Claude Opus 4.6 (1M context) --- webAO/client.ts | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'webAO/client.ts') diff --git a/webAO/client.ts b/webAO/client.ts index 05a40c9..e00afe6 100644 --- a/webAO/client.ts +++ b/webAO/client.ts @@ -13,6 +13,8 @@ import { Viewport } from "./viewport/interfaces/Viewport"; import { EventEmitter } from "events"; import { onReplayGo } from "./dom/onReplayGo"; import { packetHandler } from "./packets/packetHandler"; +import { appendICNotice } from "./client/appendICNotice"; +import { renderAreaList } from "./dom/renderAreaList"; import { loadResources } from "./client/loadResources"; import { AO_HOST } from "./client/aoHost"; import { @@ -111,6 +113,8 @@ export enum clientState { Connected, // Should be set once the client has joined the server (after handshake) Joined, + // Set when a reconnect attempt is in progress + Reconnecting, } export let lastICMessageTime = new Date(0); @@ -274,6 +278,10 @@ class Client extends EventEmitter { */ onOpen(_e: Event) { client.state = clientState.Connected; + document.getElementById("client_error_overlay").style.display = "none"; + document.getElementById("client_waiting").style.display = "block"; + document.getElementById("client_loading").style.display = "block"; + document.getElementById("client_charselect").style.display = "none"; client.joinServer(); } @@ -282,19 +290,21 @@ class Client extends EventEmitter { * @param {CloseEvent} e */ onClose(e: CloseEvent) { - client.state = clientState.NotConnected; console.error(`The connection was closed: ${e.reason} (${e.code})`); + if (this.state === clientState.Reconnecting) return; + client.state = clientState.NotConnected; if (this.banned === false) { if (this.areas.length > 0) { document.getElementById("client_errortext").textContent = "You were disconnected from the server."; + appendICNotice("Disconnected from the server."); } else { document.getElementById("client_errortext").textContent = "Could not connect to the server."; } + (document.getElementById("client_reconnect")).style.display = ""; } - document.getElementById("client_waiting").style.display = "block"; - document.getElementById("client_error").style.display = "flex"; + document.getElementById("client_error_overlay").style.display = "flex"; document.getElementById("client_loading").style.display = "none"; document.getElementById("error_id").textContent = String(e.code); this.cleanup(); @@ -364,10 +374,14 @@ class Client extends EventEmitter { * @param {ErrorEvent} e */ onError(e: ErrorEvent) { - client.state = clientState.NotConnected; console.error(`A network error occurred`); console.error(e); - document.getElementById("client_error").style.display = "flex"; + if (this.state === clientState.Reconnecting) return; + client.state = clientState.NotConnected; + document.getElementById("client_errortext").textContent = + "Could not connect to the server."; + (document.getElementById("client_reconnect")).style.display = ""; + document.getElementById("client_error_overlay").style.display = "flex"; this.cleanup(); } @@ -376,7 +390,7 @@ class Client extends EventEmitter { */ cleanup() { clearInterval(this.checkUpdater); - this.serv.close(); + if (this.serv) this.serv.close(); } /** @@ -412,7 +426,7 @@ class Client extends EventEmitter { resetAreaList() { this.areas = []; - document.getElementById("areas").innerHTML = ""; + renderAreaList(); fetchBackgroundList(); fetchEvidenceList(); fetchCharacterList(); -- cgit From 28a140dc8ab8adf32c783c6887e29c245981ab51 Mon Sep 17 00:00:00 2001 From: David Skoland Date: Tue, 24 Mar 2026 12:35:41 +0100 Subject: Add Connected and Disconnected notices --- webAO/client.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'webAO/client.ts') diff --git a/webAO/client.ts b/webAO/client.ts index e00afe6..70450cf 100644 --- a/webAO/client.ts +++ b/webAO/client.ts @@ -282,6 +282,7 @@ class Client extends EventEmitter { document.getElementById("client_waiting").style.display = "block"; document.getElementById("client_loading").style.display = "block"; document.getElementById("client_charselect").style.display = "none"; + appendICNotice("Connected"); client.joinServer(); } @@ -297,7 +298,7 @@ class Client extends EventEmitter { if (this.areas.length > 0) { document.getElementById("client_errortext").textContent = "You were disconnected from the server."; - appendICNotice("Disconnected from the server."); + appendICNotice("Disconnected"); } else { document.getElementById("client_errortext").textContent = "Could not connect to the server."; -- cgit From 6f407b54c3251b90463bc508852b031d72b0c673 Mon Sep 17 00:00:00 2001 From: David Skoland Date: Sat, 28 Mar 2026 14:09:06 +0100 Subject: remove UI related changes --- webAO/client.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'webAO/client.ts') diff --git a/webAO/client.ts b/webAO/client.ts index 70450cf..5f35c69 100644 --- a/webAO/client.ts +++ b/webAO/client.ts @@ -14,7 +14,6 @@ import { EventEmitter } from "events"; import { onReplayGo } from "./dom/onReplayGo"; import { packetHandler } from "./packets/packetHandler"; import { appendICNotice } from "./client/appendICNotice"; -import { renderAreaList } from "./dom/renderAreaList"; import { loadResources } from "./client/loadResources"; import { AO_HOST } from "./client/aoHost"; import { @@ -427,7 +426,7 @@ class Client extends EventEmitter { resetAreaList() { this.areas = []; - renderAreaList(); + document.getElementById("areas").innerHTML = ""; fetchBackgroundList(); fetchEvidenceList(); fetchCharacterList(); -- cgit