Do our own EventSource reconnection, show icon to user

This commit is contained in:
Ian Gulliver
2020-11-25 23:21:22 +00:00
parent 82da61bd86
commit 7d1035f751
2 changed files with 91 additions and 22 deletions

View File

@@ -1,4 +1,5 @@
"use strict"; "use strict";
const messageBus = new EventTarget();
function main() { function main() {
const url = new URL(location.href); const url = new URL(location.href);
if (url.searchParams.has("room")) { if (url.searchParams.has("room")) {
@@ -64,14 +65,32 @@ function watch(roomId, clientId, adminSecret, prnt) {
if (adminSecret) { if (adminSecret) {
url.searchParams.set("admin_secret", adminSecret); url.searchParams.set("admin_secret", adminSecret);
} }
const es = new EventSource(url.toString()); createEventSource(url);
renderControls(roomId, clientId, adminSecret, prnt, es); renderControls(roomId, clientId, adminSecret, prnt);
renderTimers(roomId, adminSecret, prnt, es); renderTimers(roomId, adminSecret, prnt);
if (adminSecret) { if (adminSecret) {
renderAdmin(roomId, adminSecret, prnt, es); renderAdmin(roomId, adminSecret, prnt);
} }
} }
function renderControls(roomId, clientId, adminSecret, prnt, es) { function createEventSource(url) {
const es = new EventSource(url.toString());
es.addEventListener("open", () => {
messageBus.dispatchEvent(new Event("open"));
});
es.addEventListener("message", (e) => {
messageBus.dispatchEvent(new MessageEvent("message", {
data: e.data,
lastEventId: e.lastEventId,
}));
});
es.addEventListener("error", () => {
console.warn("disconnected");
es.close();
setTimeout(() => createEventSource(url), 3000);
messageBus.dispatchEvent(new Event("error"));
});
}
function renderControls(roomId, clientId, adminSecret, prnt) {
const controls = create(prnt, "div", undefined, ["controls"]); const controls = create(prnt, "div", undefined, ["controls"]);
const left = create(controls, "span", "<<<", ["control-button"]); const left = create(controls, "span", "<<<", ["control-button"]);
left.addEventListener("click", () => control(roomId, clientId, controls, "left")); left.addEventListener("click", () => control(roomId, clientId, controls, "left"));
@@ -88,7 +107,8 @@ function renderControls(roomId, clientId, adminSecret, prnt, es) {
break; break;
} }
}); });
es.addEventListener("message", (e) => { messageBus.addEventListener("message", (ev) => {
const e = ev;
const event = JSON.parse(e.data); const event = JSON.parse(e.data);
if (!event.standard_event) { if (!event.standard_event) {
return; return;
@@ -105,10 +125,11 @@ function renderControls(roomId, clientId, adminSecret, prnt, es) {
} }
}); });
} }
function renderTimers(roomId, adminSecret, prnt, es) { function renderTimers(roomId, adminSecret, prnt) {
let overallStart = null; let overallStart = null;
let meStart = null; let meStart = null;
es.addEventListener("message", (e) => { messageBus.addEventListener("message", (ev) => {
const e = ev;
const event = JSON.parse(e.data); const event = JSON.parse(e.data);
if (!event.standard_event) { if (!event.standard_event) {
return; return;
@@ -117,6 +138,14 @@ function renderTimers(roomId, adminSecret, prnt, es) {
meStart = parseInt(event.standard_event.active_start || "0", 10) || null; meStart = parseInt(event.standard_event.active_start || "0", 10) || null;
}); });
const width = 10; const width = 10;
const statusDiv = create(prnt, "div", "Status: ".padStart(width, "\u00a0"));
const status = create(statusDiv, "span");
messageBus.addEventListener("open", () => {
status.innerText = "\u{1f7e2}";
});
messageBus.addEventListener("error", () => {
status.innerText = "\u{1f534}";
});
const clockDiv = create(prnt, "div", "Clock: ".padStart(width, "\u00a0")); const clockDiv = create(prnt, "div", "Clock: ".padStart(width, "\u00a0"));
const clock = create(clockDiv, "span"); const clock = create(clockDiv, "span");
const overallDiv = create(prnt, "div", "Overall: ".padStart(width, "\u00a0")); const overallDiv = create(prnt, "div", "Overall: ".padStart(width, "\u00a0"));
@@ -158,7 +187,7 @@ function renderTimers(roomId, adminSecret, prnt, es) {
} }
}, 250); }, 250);
} }
function renderAdmin(roomId, adminSecret, prnt, es) { function renderAdmin(roomId, adminSecret, prnt) {
const table = create(prnt, "table", undefined, ["users"]); const table = create(prnt, "table", undefined, ["users"]);
const head = create(table, "thead"); const head = create(table, "thead");
const head1 = create(head, "tr"); const head1 = create(head, "tr");
@@ -169,11 +198,12 @@ function renderAdmin(roomId, adminSecret, prnt, es) {
create(head1, "th", "🌟"); create(head1, "th", "🌟");
const body = create(table, "tbody"); const body = create(table, "tbody");
const rows = new Map(); const rows = new Map();
es.addEventListener("open", () => { messageBus.addEventListener("open", () => {
rows.clear(); rows.clear();
body.innerHTML = ""; body.innerHTML = "";
}); });
es.addEventListener("message", (e) => { messageBus.addEventListener("message", (ev) => {
const e = ev;
const event = JSON.parse(e.data); const event = JSON.parse(e.data);
if (!event.admin_event) { if (!event.admin_event) {
return; return;

View File

@@ -65,6 +65,8 @@ interface Client {
active_start: string; active_start: string;
} }
const messageBus = new EventTarget();
function main() { function main() {
const url = new URL(location.href); const url = new URL(location.href);
@@ -143,18 +145,41 @@ function watch(roomId: string, clientId: string, adminSecret: string | null, prn
if (adminSecret) { if (adminSecret) {
url.searchParams.set("admin_secret", adminSecret); url.searchParams.set("admin_secret", adminSecret);
} }
const es = new EventSource(url.toString()); createEventSource(url);
renderControls(roomId, clientId, adminSecret, prnt, es); renderControls(roomId, clientId, adminSecret, prnt);
renderTimers(roomId, adminSecret, prnt, es); renderTimers(roomId, adminSecret, prnt);
if (adminSecret) { if (adminSecret) {
renderAdmin(roomId, adminSecret, prnt, es); renderAdmin(roomId, adminSecret, prnt);
} }
} }
function renderControls(roomId: string, clientId: string, adminSecret: string | null, prnt: HTMLElement, es: EventSource) { function createEventSource(url: URL) {
const es = new EventSource(url.toString());
es.addEventListener("open", () => {
messageBus.dispatchEvent(new Event("open"));
});
es.addEventListener("message", (e) => {
messageBus.dispatchEvent(new MessageEvent("message", {
data: e.data,
lastEventId: e.lastEventId,
}));
});
es.addEventListener("error", () => {
console.warn("disconnected");
es.close();
setTimeout(() => createEventSource(url), 3000);
messageBus.dispatchEvent(new Event("error"));
});
}
function renderControls(roomId: string, clientId: string, adminSecret: string | null, prnt: HTMLElement) {
const controls = create(prnt, "div", undefined, ["controls"]) as HTMLDivElement; const controls = create(prnt, "div", undefined, ["controls"]) as HTMLDivElement;
const left = create(controls, "span", "<<<", ["control-button"]) as HTMLDivElement; const left = create(controls, "span", "<<<", ["control-button"]) as HTMLDivElement;
@@ -176,7 +201,8 @@ function renderControls(roomId: string, clientId: string, adminSecret: string |
} }
}); });
es.addEventListener("message", (e) => { messageBus.addEventListener("message", (ev) => {
const e = ev as MessageEvent;
const event = JSON.parse(e.data) as Event; const event = JSON.parse(e.data) as Event;
if (!event.standard_event) { if (!event.standard_event) {
@@ -196,11 +222,12 @@ function renderControls(roomId: string, clientId: string, adminSecret: string |
}); });
} }
function renderTimers(roomId: string, adminSecret: string | null, prnt: HTMLElement, es: EventSource) { function renderTimers(roomId: string, adminSecret: string | null, prnt: HTMLElement) {
let overallStart: number | null = null; let overallStart: number | null = null;
let meStart: number | null = null; let meStart: number | null = null;
es.addEventListener("message", (e) => { messageBus.addEventListener("message", (ev) => {
const e = ev as MessageEvent;
const event = JSON.parse(e.data) as Event; const event = JSON.parse(e.data) as Event;
if (!event.standard_event) { if (!event.standard_event) {
@@ -213,6 +240,17 @@ function renderTimers(roomId: string, adminSecret: string | null, prnt: HTMLElem
const width = 10; const width = 10;
const statusDiv = create(prnt, "div", "Status: ".padStart(width, "\u00a0"));
const status = create(statusDiv, "span");
messageBus.addEventListener("open", () => {
status.innerText = "\u{1f7e2}";
});
messageBus.addEventListener("error", () => {
status.innerText = "\u{1f534}";
});
const clockDiv = create(prnt, "div", "Clock: ".padStart(width, "\u00a0")); const clockDiv = create(prnt, "div", "Clock: ".padStart(width, "\u00a0"));
const clock = create(clockDiv, "span"); const clock = create(clockDiv, "span");
@@ -260,7 +298,7 @@ function renderTimers(roomId: string, adminSecret: string | null, prnt: HTMLElem
}, 250); }, 250);
} }
function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es: EventSource) { function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement) {
const table = create(prnt, "table", undefined, ["users"]) as HTMLTableElement; const table = create(prnt, "table", undefined, ["users"]) as HTMLTableElement;
const head = create(table, "thead"); const head = create(table, "thead");
const head1 = create(head, "tr"); const head1 = create(head, "tr");
@@ -274,12 +312,13 @@ function renderAdmin(roomId: string, adminSecret: string, prnt: HTMLElement, es:
const rows: Map<string, HTMLTableRowElement> = new Map(); const rows: Map<string, HTMLTableRowElement> = new Map();
es.addEventListener("open", () => { messageBus.addEventListener("open", () => {
rows.clear(); rows.clear();
body.innerHTML = ""; body.innerHTML = "";
}); });
es.addEventListener("message", (e) => { messageBus.addEventListener("message", (ev) => {
const e = ev as MessageEvent;
const event = JSON.parse(e.data) as Event; const event = JSON.parse(e.data) as Event;
if (!event.admin_event) { if (!event.admin_event) {