@ywkrlerche/richardwho 1.0.24 → 1.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app.js +52 -14
- package/config.js +5 -0
- package/index.html +2 -2
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
const CFG = window.RUG_CONFIG || {};
|
|
5
5
|
const SITE_NAME = "Richards Unblocked Games";
|
|
6
|
+
// The tab/history shows this instead of the real names (set in config.js)
|
|
7
|
+
const TAB_TITLE = CFG.tabTitle || null;
|
|
8
|
+
const tabTitle = (gameName) => TAB_TITLE || (gameName ? `${gameName} · ${SITE_NAME}` : SITE_NAME);
|
|
6
9
|
const RECENT_KEY = "rug-recent";
|
|
7
10
|
const CLOCK_KEY = "rug-clock24";
|
|
8
11
|
const THEME_KEY = "rug-theme";
|
|
@@ -63,6 +66,7 @@
|
|
|
63
66
|
// games from the extra collection carry their own pinned cover URL
|
|
64
67
|
function logoUrl(game) {
|
|
65
68
|
if (game.cover) return game.cover;
|
|
69
|
+
if (typeof game.logo === "string") return `logos/${encodeURIComponent(game.logo)}`; // PNG/JPG/GIF logo
|
|
66
70
|
return game.logo ? `logos/${encodeURIComponent(game.id)}.webp` : null;
|
|
67
71
|
}
|
|
68
72
|
function fmtMB(bytes) {
|
|
@@ -201,7 +205,7 @@
|
|
|
201
205
|
els.retryBtn.hidden = true;
|
|
202
206
|
els.barFill.style.width = "0%";
|
|
203
207
|
els.loaderStatus.textContent = "Connecting…";
|
|
204
|
-
document.title =
|
|
208
|
+
document.title = tabTitle(game.name);
|
|
205
209
|
|
|
206
210
|
const urls = gameUrls(game);
|
|
207
211
|
const loaded = new Array(urls.length).fill(0);
|
|
@@ -220,19 +224,37 @@
|
|
|
220
224
|
|
|
221
225
|
try {
|
|
222
226
|
const pieces = await Promise.all(urls.map(async (url, i) => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
227
|
+
// Try the main link, then backups. jsDelivr sometimes fails the first fetch of a file it
|
|
228
|
+
// hasn't cached yet, and a download can drop mid-way, so a retry usually succeeds.
|
|
229
|
+
const sources = mirrorsFor(url);
|
|
230
|
+
let lastErr;
|
|
231
|
+
for (let attempt = 0; attempt < sources.length; attempt++) {
|
|
232
|
+
if (controller.signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
233
|
+
if (attempt) {
|
|
234
|
+
els.loaderStatus.textContent = `Connection hiccup, trying backup ${attempt} of ${sources.length - 1}…`;
|
|
235
|
+
await new Promise((r) => setTimeout(r, 600 * attempt));
|
|
236
|
+
}
|
|
237
|
+
loaded[i] = 0;
|
|
238
|
+
try {
|
|
239
|
+
const res = await fetch(sources[attempt], { signal: controller.signal });
|
|
240
|
+
if (!res.ok) throw new Error(`HTTP ${res.status} for ${url.split("/").pop()}`);
|
|
241
|
+
if (!res.body) { const b = await res.arrayBuffer(); loaded[i] = b.byteLength; update(); return [b]; }
|
|
242
|
+
const reader = res.body.getReader();
|
|
243
|
+
const chunks = [];
|
|
244
|
+
for (;;) {
|
|
245
|
+
const { done, value } = await reader.read();
|
|
246
|
+
if (done) break;
|
|
247
|
+
chunks.push(value);
|
|
248
|
+
loaded[i] += value.byteLength;
|
|
249
|
+
update();
|
|
250
|
+
}
|
|
251
|
+
return chunks;
|
|
252
|
+
} catch (err) {
|
|
253
|
+
if (err.name === "AbortError") throw err;
|
|
254
|
+
lastErr = err;
|
|
255
|
+
}
|
|
234
256
|
}
|
|
235
|
-
|
|
257
|
+
throw lastErr;
|
|
236
258
|
}));
|
|
237
259
|
if (currentLoad?.id !== game.id) return;
|
|
238
260
|
els.loaderStatus.textContent = "Starting…";
|
|
@@ -255,6 +277,22 @@
|
|
|
255
277
|
}
|
|
256
278
|
}
|
|
257
279
|
|
|
280
|
+
// Backup sources for a jsDelivr GitHub link, in the order to try them:
|
|
281
|
+
// the same link again, jsDelivr's second network, then GitHub's own file server.
|
|
282
|
+
// The extra collection's files are also published as gn-math/html at the same commit.
|
|
283
|
+
function mirrorsFor(url) {
|
|
284
|
+
const m = url.match(/^https:\/\/cdn\.jsdelivr\.net\/gh\/([^/]+)\/([^@/]+)@([^/]+)\/(.+)$/);
|
|
285
|
+
if (!m) return [url, url];
|
|
286
|
+
const [, user, repo, ref, path] = m;
|
|
287
|
+
const list = [url, url, `https://fastly.jsdelivr.net/gh/${user}/${repo}@${ref}/${path}`,
|
|
288
|
+
`https://raw.githubusercontent.com/${user}/${repo}/${ref}/${path}`];
|
|
289
|
+
if (user === "freebuisness" && repo === "html") {
|
|
290
|
+
list.push(`https://cdn.jsdelivr.net/gh/gn-math/html@${ref}/${path}`,
|
|
291
|
+
`https://raw.githubusercontent.com/gn-math/html/${ref}/${path}`);
|
|
292
|
+
}
|
|
293
|
+
return list;
|
|
294
|
+
}
|
|
295
|
+
|
|
258
296
|
// The extra collection's launch files embed Google Analytics; remove it so players aren't tracked
|
|
259
297
|
function stripTracking(html) {
|
|
260
298
|
return html
|
|
@@ -307,7 +345,7 @@
|
|
|
307
345
|
stopGame();
|
|
308
346
|
els.player.hidden = true;
|
|
309
347
|
document.body.classList.remove("playing");
|
|
310
|
-
document.title =
|
|
348
|
+
document.title = tabTitle();
|
|
311
349
|
const view = location.hash === "#games" || location.hash === "#recent" ? "games" : "home";
|
|
312
350
|
els.homeView.hidden = view !== "home";
|
|
313
351
|
els.gamesView.hidden = view !== "games";
|
package/config.js
CHANGED
|
@@ -14,6 +14,11 @@ window.RUG_CONFIG = {
|
|
|
14
14
|
// Keys that trigger panic (KeyboardEvent.key values)
|
|
15
15
|
panicKeys: ["`", "]"],
|
|
16
16
|
|
|
17
|
+
// What the browser tab and history show instead of the site/game name.
|
|
18
|
+
// Set tabTitle to null to show the real names again.
|
|
19
|
+
tabTitle: "Google Classroom",
|
|
20
|
+
tabIcon: "https://ssl.gstatic.com/classroom/favicon.png",
|
|
21
|
+
|
|
17
22
|
// For local testing only: load games from a folder on a local server
|
|
18
23
|
// instead of jsDelivr, e.g. "/repos". Leave null when published.
|
|
19
24
|
localBase: null,
|
package/index.html
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
-
<title>
|
|
6
|
+
<title>Google Classroom</title>
|
|
7
7
|
<meta name="description" content="richardwho: Richards Unblocked Games. Hundreds of games, nothing to install.">
|
|
8
|
-
<link rel="icon"
|
|
8
|
+
<link rel="icon" id="tab-icon" href="https://ssl.gstatic.com/classroom/favicon.png">
|
|
9
9
|
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
|
|
10
10
|
<link rel="stylesheet" href="style.css">
|
|
11
11
|
<script>
|