diff options
| -rw-r--r-- | public/client.html | 31 | ||||
| -rw-r--r-- | tsconfig.json | 2 | ||||
| -rw-r--r-- | webAO/client.ts | 26 | ||||
| -rw-r--r-- | webAO/client/appendICNotice.ts | 10 | ||||
| -rw-r--r-- | webAO/client/handleBans.ts | 3 | ||||
| -rw-r--r-- | webAO/dom/disconnectButton.ts | 12 | ||||
| -rw-r--r-- | webAO/dom/reconnectButton.ts | 24 | ||||
| -rw-r--r-- | webAO/dom/window.ts | 3 | ||||
| -rw-r--r-- | webAO/styles/client.css | 68 |
9 files changed, 142 insertions, 37 deletions
diff --git a/public/client.html b/public/client.html index ef60e15..d6ac1b6 100644 --- a/public/client.html +++ b/public/client.html @@ -131,20 +131,22 @@ <br /><br /> <div id="client_chartable"></div> </div> - <div id="client_error" class="error" style="display: none"> - <h1 id="client_errortext">Connection error.</h1> - <p style="color: #a00"> - Code: - <span id="error_id">(none)</span> + </div> + <div id="client_error_overlay" style="display: none"> + <div id="client_error"> + <div id="client_error_icon">⚠</div> + <h2 id="client_errortext"></h2> + <p id="client_error_code"> + Error code: <span id="error_id">(none)</span> + </p> + <button id="client_reconnect" onclick="ReconnectButton()"> + Reconnect + </button> + <p id="client_error_help"> + Having trouble? + <a href="https://discord.gg/9rYQVVQ" target="_blank">Join us on Discord</a> </p> </div> - <p> - Having trouble? - <a href="https://discord.gg/9rYQVVQ">Join us on Discord</a> - </p> - <button id="client_reconnect" onclick="ReconnectButton()"> - Reconnect - </button> </div> </body> @@ -954,6 +956,11 @@ If you don't agree, disable cookies for this site in your browser.</span > + <br /> + <br /> + <button id="client_disconnect" onclick="DisconnectButton()"> + Disconnect + </button> </span> <!-- About section --> diff --git a/tsconfig.json b/tsconfig.json index 9a5045a..f33e7c1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,5 +10,5 @@ "resolveJsonModule": true, "esModuleInterop": true }, - "include": ["./webAO/*", "./webAO/viewport/viewport.ts"] + "include": ["./webAO/**/*"] } diff --git a/webAO/client.ts b/webAO/client.ts index 8a01526..703ce73 100644 --- a/webAO/client.ts +++ b/webAO/client.ts @@ -13,6 +13,7 @@ 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 { loadResources } from "./client/loadResources"; import { AO_HOST } from "./client/aoHost"; import { @@ -112,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); @@ -275,6 +278,11 @@ 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"; + appendICNotice("Connected"); client.joinServer(); } @@ -283,19 +291,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"); } else { document.getElementById("client_errortext").textContent = "Could not connect to the server."; } + (<HTMLElement>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(); @@ -365,10 +375,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."; + (<HTMLElement>document.getElementById("client_reconnect")).style.display = ""; + document.getElementById("client_error_overlay").style.display = "flex"; this.cleanup(); } @@ -377,7 +391,7 @@ class Client extends EventEmitter { */ cleanup() { clearInterval(this.checkUpdater); - this.serv.close(); + if (this.serv) this.serv.close(); } /** diff --git a/webAO/client/appendICNotice.ts b/webAO/client/appendICNotice.ts new file mode 100644 index 0000000..29065db --- /dev/null +++ b/webAO/client/appendICNotice.ts @@ -0,0 +1,10 @@ +/** + * Appends a notice (hrtext divider) to the IC log. + * @param {string} msg the notice text + */ +export function appendICNotice(msg: string) { + const el = document.createElement("div"); + el.className = "hrtext"; + el.textContent = msg; + document.getElementById("client_log")!.appendChild(el); +} diff --git a/webAO/client/handleBans.ts b/webAO/client/handleBans.ts index 9eec9be..004b27e 100644 --- a/webAO/client/handleBans.ts +++ b/webAO/client/handleBans.ts @@ -6,10 +6,9 @@ import { safeTags } from "../encoding"; * @param {string} reason why */ export const handleBans = (type: string, reason: string) => { - document.getElementById("client_error")!.style.display = "flex"; + document.getElementById("client_error_overlay")!.style.display = "flex"; document.getElementById("client_errortext")!.innerHTML = `${type}:<br>${safeTags(reason).replace(/\n/g, "<br />")}`; (<HTMLElement>document.getElementById("client_reconnect")).style.display = "none"; - alert(type + ":\r" + reason); }; diff --git a/webAO/dom/disconnectButton.ts b/webAO/dom/disconnectButton.ts new file mode 100644 index 0000000..35daf16 --- /dev/null +++ b/webAO/dom/disconnectButton.ts @@ -0,0 +1,12 @@ +import { client } from "../client"; + +/** + * Triggered when the disconnect button in settings is pushed. + * Forces a disconnection for testing purposes. + */ +export function DisconnectButton() { + if (client.serv && client.serv.readyState === WebSocket.OPEN) { + client.serv.close(); + } +} +window.DisconnectButton = DisconnectButton; diff --git a/webAO/dom/reconnectButton.ts b/webAO/dom/reconnectButton.ts index 079e7fc..eecb915 100644 --- a/webAO/dom/reconnectButton.ts +++ b/webAO/dom/reconnectButton.ts @@ -1,16 +1,28 @@ -import Client, { client, setClient } from "../client"; +import Client, { client, clientState, setClient } from "../client"; import queryParser from "../utils/queryParser"; -const { ip: serverIP } = queryParser(); +const { ip: serverIP, connect } = queryParser(); /** * Triggered when the reconnect button is pushed. */ export function ReconnectButton() { - client.cleanup(); - setClient(new Client(serverIP)); + document.getElementById("client_errortext")!.textContent = "Reconnecting..."; - if (client) { - document.getElementById("client_error")!.style.display = "none"; + // Build the connection string the same way the initial connection does + let connectionString = connect; + if (!connectionString && serverIP) { + // if connectionString is not set, try IP + // and just guess ws, though it could be wss + connectionString = `ws://${serverIP}`; } + + const hdid = client.hdid; + client.state = clientState.Reconnecting; + client.cleanup(); + + const newClient = new Client(connectionString); + setClient(newClient); + newClient.hdid = hdid; + newClient.connect(); } window.ReconnectButton = ReconnectButton; diff --git a/webAO/dom/window.ts b/webAO/dom/window.ts index ee1b121..ba19982 100644 --- a/webAO/dom/window.ts +++ b/webAO/dom/window.ts @@ -29,7 +29,8 @@ declare global { pickEmotion: (emo: number) => void; pickChar: (ccharacter: any) => void; chartable_filter: (_event: any) => void; - ReconnectButton: (_event: any) => void; + ReconnectButton: () => void; + DisconnectButton: () => void; opusCheck: (channel: HTMLAudioElement) => OnErrorEventHandlerNonNull; imgError: (image: any) => void; charError: (image: any) => void; diff --git a/webAO/styles/client.css b/webAO/styles/client.css index e3ee820..673d176 100644 --- a/webAO/styles/client.css +++ b/webAO/styles/client.css @@ -58,25 +58,75 @@ } } +#client_error_overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.6); + display: flex; + justify-content: center; + align-items: center; + z-index: 200; +} + #client_error { - position: absolute; display: flex; flex-direction: column; - padding: 10px; - top: 50%; - left: 50%; - margin-right: -50%; - transform: translate(-50%, -50%); + padding: 24px 36px; justify-content: center; align-items: center; - background: #a00; + background: rgba(0, 0, 0, 0.9); + border: 2px solid #c00; + border-radius: 8px; color: #fff; font-size: large; - z-index: 100; + min-width: 280px; + box-shadow: 0 4px 24px rgba(0, 0, 0, 0.5); +} + +#client_error_icon { + font-size: 48px; + color: #f44; + margin-bottom: 4px; } #client_errortext { - animation: error_blink 3s ease-in-out infinite; + margin: 4px 0 8px; + text-align: center; +} + +#client_error_code { + color: #999; + font-size: 12px; + margin: 0 0 16px; +} + +#client_reconnect { + background: #c00; + color: #fff; + border: none; + border-radius: 4px; + padding: 10px 32px; + font-size: 16px; + cursor: pointer; + margin-bottom: 12px; + transition: background 0.2s; +} + +#client_reconnect:hover { + background: #e22; +} + +#client_error_help { + color: #aaa; + font-size: 12px; + margin: 0; +} + +#client_error_help a { + color: #6af; } #client_secondfactor { |
