-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathservice-worker.js
More file actions
141 lines (129 loc) · 4.4 KB
/
Copy pathservice-worker.js
File metadata and controls
141 lines (129 loc) · 4.4 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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
const APP_VERSION = '1.0.3';
const CACHE_VERSION = `resident-pro-v${APP_VERSION}`;
const SHELL_CACHE = `shell-${CACHE_VERSION}`;
const RUNTIME_CACHE = `runtime-${CACHE_VERSION}`;
const RUNTIME_CACHE_MAX_ENTRIES = 40;
const APP_SHELL = [
'./',
'./index.html',
'./styles.css',
'./lib/date-utils.js',
'./lib/storage-utils.js',
'./lib/resident-logic.js',
'./lib/app-config.js',
'./lib/ui-utils.js',
'./lib/report-ui.js',
'./app.js',
'./pwa-register.js',
'./manifest.webmanifest',
'./assets/vendor/flatpickr/flatpickr.min.js',
'./assets/vendor/flatpickr/themes/dark.css',
'./assets/vendor/flatpickr/themes/light.css',
'./assets/icons/icon.svg',
'./assets/icons/icon-maskable.svg'
];
const OFFLINE_HTML = `<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Offline - Resident Pro</title>
<style>
body{font-family:system-ui,-apple-system,Segoe UI,sans-serif;background:#edf5ff;color:#11213f;margin:0;display:grid;place-items:center;min-height:100vh;padding:24px}
.card{max-width:460px;background:#fff;border:1px solid #dbe7ff;border-radius:14px;padding:20px;box-shadow:0 8px 24px rgba(23,64,129,.08)}
h1{margin:0 0 8px;font-size:1.25rem}
p{margin:0;line-height:1.5}
</style>
</head>
<body>
<div class="card">
<h1>You are offline</h1>
<p>Resident Pro could not load this page right now. Reconnect to the internet and refresh.</p>
</div>
</body>
</html>`;
const shouldCacheResponse = (response) =>
Boolean(response) && response.ok && response.type === 'basic';
const addShellAsset = async (cache, url) => {
try {
await cache.add(url);
} catch (_) {
// A missing optional asset should not block service worker updates.
}
};
const trimRuntimeCache = async () => {
const cache = await caches.open(RUNTIME_CACHE);
const keys = await cache.keys();
if (keys.length <= RUNTIME_CACHE_MAX_ENTRIES) return;
const deleteCount = keys.length - RUNTIME_CACHE_MAX_ENTRIES;
await Promise.all(keys.slice(0, deleteCount).map((request) => cache.delete(request)));
};
self.addEventListener('install', (event) => {
event.waitUntil((async () => {
const cache = await caches.open(SHELL_CACHE);
await Promise.all(APP_SHELL.map((url) => addShellAsset(cache, url)));
self.skipWaiting();
})());
});
self.addEventListener('activate', (event) => {
event.waitUntil((async () => {
const names = await caches.keys();
await Promise.all(
names
.filter((name) => name !== SHELL_CACHE && name !== RUNTIME_CACHE)
.map((name) => caches.delete(name))
);
await self.clients.claim();
})());
});
self.addEventListener('fetch', (event) => {
if (event.request.method !== 'GET') return;
const requestUrl = new URL(event.request.url);
if (requestUrl.origin !== self.location.origin) return;
if (event.request.mode === 'navigate') {
event.respondWith((async () => {
try {
const fresh = await fetch(event.request);
if (shouldCacheResponse(fresh)) {
const runtime = await caches.open(RUNTIME_CACHE);
await runtime.put(event.request, fresh.clone());
await trimRuntimeCache();
}
return fresh;
} catch (_) {
const cachedPage = await caches.match(event.request);
if (cachedPage) return cachedPage;
const cachedShell = await caches.match('./index.html');
if (cachedShell) return cachedShell;
return new Response(OFFLINE_HTML, {
status: 200,
headers: { 'Content-Type': 'text/html; charset=utf-8' }
});
}
})());
return;
}
event.respondWith((async () => {
const cached = await caches.match(event.request);
if (cached) return cached;
try {
const fresh = await fetch(event.request);
if (shouldCacheResponse(fresh)) {
const runtime = await caches.open(RUNTIME_CACHE);
await runtime.put(event.request, fresh.clone());
await trimRuntimeCache();
}
return fresh;
} catch (_) {
if (event.request.destination === 'document') {
const cachedShell = await caches.match('./index.html');
if (cachedShell) return cachedShell;
return new Response(OFFLINE_HTML, {
status: 200,
headers: { 'Content-Type': 'text/html; charset=utf-8' }
});
}
return new Response('', { status: 503, statusText: 'Offline' });
}
})());
});