Repository navigation
Expand file tree
/
Copy pathsw.js
More file actions
116 lines (115 loc) · 4.58 KB
/
Copy pathsw.js
File metadata and controls
116 lines (115 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Service worker — offline app shell + runtime cache. Bump CACHE on each release.
const CACHE = 'arcade-v49';
const AUDIO_CACHE = 'arcade-audio'; // persistent music library — NOT versioned, survives deploys
const isAudio = (u) => u.pathname.includes('/audio/') && /\.(mp3|m4a|ogg|wav)$/i.test(u.pathname);
const SHELL = [
'./', './index.html', './app.css', './manifest.webmanifest',
'./icon.svg', './icon-192.png', './icon-512.png', './apple-touch-icon-180.png',
'https://cdn.tailwindcss.com',
'https://unpkg.com/peerjs@1.5.4/dist/peerjs.min.js',
'https://unpkg.com/mqtt@5.7.0/dist/mqtt.min.js',
// MODULES:START (auto-generated by bump-version.sh — do not edit by hand)
'./js/app.js?v=49',
'./js/demos.js?v=49',
'./js/favorites.js?v=49',
'./js/friends.js?v=49',
'./js/i18n.js?v=49',
'./js/identity.js?v=49',
'./js/logic.js?v=49',
'./js/loyalty.js?v=49',
'./js/platform.js?v=49',
'./js/prefs.js?v=49',
'./js/presence.js?v=49',
'./js/profile.js?v=49',
'./js/sound.js?v=49',
'./js/tools.js?v=49',
'./js/tutorials.js?v=49',
'./js/games/2048.js?v=49',
'./js/games/airhockey.js?v=49',
'./js/games/backgammon.js?v=49',
'./js/games/battleship.js?v=49',
'./js/games/breakthrough.js?v=49',
'./js/games/checkers.js?v=49',
'./js/games/chess.js?v=49',
'./js/games/chinese-checkers.js?v=49',
'./js/games/connect-four.js?v=49',
'./js/games/domineering.js?v=49',
'./js/games/dominoes.js?v=49',
'./js/games/dots-boxes.js?v=49',
'./js/games/farkle.js?v=49',
'./js/games/go.js?v=49',
'./js/games/gomoku.js?v=49',
'./js/games/hangman.js?v=49',
'./js/games/hex.js?v=49',
'./js/games/level2048.js?v=49',
'./js/games/lights-out.js?v=49',
'./js/games/loa.js?v=49',
'./js/games/ludo.js?v=49',
'./js/games/mancala.js?v=49',
'./js/games/mastermind.js?v=49',
'./js/games/match3.js?v=49',
'./js/games/memory.js?v=49',
'./js/games/minesweeper.js?v=49',
'./js/games/nim.js?v=49',
'./js/games/nine-mens-morris.js?v=49',
'./js/games/notakto.js?v=49',
'./js/games/number-duel.js?v=49',
'./js/games/onitama.js?v=49',
'./js/games/order-chaos.js?v=49',
'./js/games/pentago.js?v=49',
'./js/games/pig.js?v=49',
'./js/games/quarto.js?v=49',
'./js/games/quoridor.js?v=49',
'./js/games/reversi.js?v=49',
'./js/games/rock-paper-scissors.js?v=49',
'./js/games/sim.js?v=49',
'./js/games/snake.js?v=49',
'./js/games/snakes.js?v=49',
'./js/games/sudoku.js?v=49',
'./js/games/tetris.js?v=49',
'./js/games/tic-tac-toe.js?v=49',
'./js/games/tileboard.js?v=49',
'./js/games/tron.js?v=49',
'./js/games/ultimate-ttt.js?v=49',
'./js/games/word-ladder-puzzles.js?v=49',
'./js/games/word-ladder.js?v=49',
'./js/games/word-race.js?v=49',
'./js/games/wordle-duel.js?v=49',
'./js/games/yahtzee.js?v=49',
// MODULES:END
];
self.addEventListener('install', (e) => {
self.skipWaiting();
e.waitUntil(caches.open(CACHE).then((c) => Promise.all(SHELL.map((u) => c.add(u).catch(() => {})))));
});
self.addEventListener('activate', (e) => {
e.waitUntil(caches.keys().then((keys) => Promise.all(keys.filter((k) => k !== CACHE && k !== AUDIO_CACHE).map((k) => caches.delete(k)))).then(() => self.clients.claim()));
});
self.addEventListener('fetch', (e) => {
const req = e.request;
if (req.method !== 'GET') return;
const url = new URL(req.url);
// Navigation -> serve cached index (offline fallback).
if (req.mode === 'navigate') {
e.respondWith(fetch(req).catch(() => caches.match('./index.html')));
return;
}
// Music files -> cache-first against the persistent audio bucket. On miss just pass through
// (don't cache here: media elements send Range → 206, which is not the full file; the app's
// prefetchAudio() stores full 200 responses in AUDIO_CACHE for offline).
if (isAudio(url)) {
e.respondWith(caches.open(AUDIO_CACHE).then((c) => c.match(req).then((hit) => hit || fetch(req))));
return;
}
// tracks.json -> network-first (fresh playlist), fall back to the audio cache offline.
if (url.pathname.endsWith('/audio/tracks.json') || url.pathname.endsWith('audio/tracks.json')) {
e.respondWith(fetch(req).then((res) => { const copy = res.clone(); caches.open(AUDIO_CACHE).then((c) => c.put(req, copy)).catch(() => {}); return res; }).catch(() => caches.open(AUDIO_CACHE).then((c) => c.match(req))));
return;
}
// Cache-first with runtime caching (JS modules carry ?v=N so new deploys fetch fresh).
e.respondWith(caches.match(req).then((hit) => hit || fetch(req).then((res) => {
const copy = res.clone();
caches.open(CACHE).then((c) => c.put(req, copy)).catch(() => {});
return res;
}).catch(() => hit)));
});