@ywkrlerche/richardwho 1.0.24 → 1.0.25
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 +47 -12
- package/games.json +1 -1
- package/logos/gm-test-game.png +0 -0
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -63,6 +63,7 @@
|
|
|
63
63
|
// games from the extra collection carry their own pinned cover URL
|
|
64
64
|
function logoUrl(game) {
|
|
65
65
|
if (game.cover) return game.cover;
|
|
66
|
+
if (typeof game.logo === "string") return `logos/${encodeURIComponent(game.logo)}`; // PNG/JPG/GIF logo
|
|
66
67
|
return game.logo ? `logos/${encodeURIComponent(game.id)}.webp` : null;
|
|
67
68
|
}
|
|
68
69
|
function fmtMB(bytes) {
|
|
@@ -220,19 +221,37 @@
|
|
|
220
221
|
|
|
221
222
|
try {
|
|
222
223
|
const pieces = await Promise.all(urls.map(async (url, i) => {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
224
|
+
// Try the main link, then backups. jsDelivr sometimes fails the first fetch of a file it
|
|
225
|
+
// hasn't cached yet, and a download can drop mid-way, so a retry usually succeeds.
|
|
226
|
+
const sources = mirrorsFor(url);
|
|
227
|
+
let lastErr;
|
|
228
|
+
for (let attempt = 0; attempt < sources.length; attempt++) {
|
|
229
|
+
if (controller.signal.aborted) throw new DOMException("Aborted", "AbortError");
|
|
230
|
+
if (attempt) {
|
|
231
|
+
els.loaderStatus.textContent = `Connection hiccup, trying backup ${attempt} of ${sources.length - 1}…`;
|
|
232
|
+
await new Promise((r) => setTimeout(r, 600 * attempt));
|
|
233
|
+
}
|
|
234
|
+
loaded[i] = 0;
|
|
235
|
+
try {
|
|
236
|
+
const res = await fetch(sources[attempt], { signal: controller.signal });
|
|
237
|
+
if (!res.ok) throw new Error(`HTTP ${res.status} for ${url.split("/").pop()}`);
|
|
238
|
+
if (!res.body) { const b = await res.arrayBuffer(); loaded[i] = b.byteLength; update(); return [b]; }
|
|
239
|
+
const reader = res.body.getReader();
|
|
240
|
+
const chunks = [];
|
|
241
|
+
for (;;) {
|
|
242
|
+
const { done, value } = await reader.read();
|
|
243
|
+
if (done) break;
|
|
244
|
+
chunks.push(value);
|
|
245
|
+
loaded[i] += value.byteLength;
|
|
246
|
+
update();
|
|
247
|
+
}
|
|
248
|
+
return chunks;
|
|
249
|
+
} catch (err) {
|
|
250
|
+
if (err.name === "AbortError") throw err;
|
|
251
|
+
lastErr = err;
|
|
252
|
+
}
|
|
234
253
|
}
|
|
235
|
-
|
|
254
|
+
throw lastErr;
|
|
236
255
|
}));
|
|
237
256
|
if (currentLoad?.id !== game.id) return;
|
|
238
257
|
els.loaderStatus.textContent = "Starting…";
|
|
@@ -255,6 +274,22 @@
|
|
|
255
274
|
}
|
|
256
275
|
}
|
|
257
276
|
|
|
277
|
+
// Backup sources for a jsDelivr GitHub link, in the order to try them:
|
|
278
|
+
// the same link again, jsDelivr's second network, then GitHub's own file server.
|
|
279
|
+
// The extra collection's files are also published as gn-math/html at the same commit.
|
|
280
|
+
function mirrorsFor(url) {
|
|
281
|
+
const m = url.match(/^https:\/\/cdn\.jsdelivr\.net\/gh\/([^/]+)\/([^@/]+)@([^/]+)\/(.+)$/);
|
|
282
|
+
if (!m) return [url, url];
|
|
283
|
+
const [, user, repo, ref, path] = m;
|
|
284
|
+
const list = [url, url, `https://fastly.jsdelivr.net/gh/${user}/${repo}@${ref}/${path}`,
|
|
285
|
+
`https://raw.githubusercontent.com/${user}/${repo}/${ref}/${path}`];
|
|
286
|
+
if (user === "freebuisness" && repo === "html") {
|
|
287
|
+
list.push(`https://cdn.jsdelivr.net/gh/gn-math/html@${ref}/${path}`,
|
|
288
|
+
`https://raw.githubusercontent.com/gn-math/html/${ref}/${path}`);
|
|
289
|
+
}
|
|
290
|
+
return list;
|
|
291
|
+
}
|
|
292
|
+
|
|
258
293
|
// The extra collection's launch files embed Google Analytics; remove it so players aren't tracked
|
|
259
294
|
function stripTracking(html) {
|
|
260
295
|
return html
|