aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/client.html31
-rw-r--r--tsconfig.json2
-rw-r--r--webAO/client.ts26
-rw-r--r--webAO/client/appendICNotice.ts10
-rw-r--r--webAO/client/handleBans.ts3
-rw-r--r--webAO/dom/disconnectButton.ts12
-rw-r--r--webAO/dom/reconnectButton.ts24
-rw-r--r--webAO/dom/window.ts3
-rw-r--r--webAO/styles/client.css68
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">&#x26A0;</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 {