-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathservice-worker.js
135 lines (114 loc) · 3.84 KB
/
service-worker.js
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
/* globals self, Response */
// this is needed to create a binary-different file when
// I don't need to make any actual changes to this file
const VERSION = 'v1.0.2';
const WORKER = '👷';
const KEY = 'heic-app-v1';
const APP_PATHS = [
'./',
// modules
'./src/loader.js',
'./src/toast.js',
'./src/event-emitter.js',
'./src/storage.js',
'./src/menu.js',
'./src/progress.js',
'./src/controls.js',
'./src/open.js',
'./src/convert.js',
'./src/download.js',
// style and assets
'./src/style.css',
'./manifest.json',
'./assets/icon-512.png',
];
const CDN_PATHS = [
'https://fonts.googleapis.com/icon?family=Material+Icons',
'https://fonts.gstatic.com/s/materialicons/v48/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2',
'https://cdn.jsdelivr.net/npm/toastify-js@1.6.1/src/toastify.min.css',
'https://cdn.jsdelivr.net/npm/toastify-js@1.6.1/src/toastify.min.js',
'https://cdn.jsdelivr.net/npm/file-saver@2.0.2/dist/FileSaver.min.js',
'https://cdn.jsdelivr.net/npm/libheif-js@1.18.2/libheif-wasm/libheif-bundle.mjs',
];
// eslint-disable-next-line no-console
const log = (first, ...args) => console.log(`${WORKER} ${VERSION} - ${first}`, ...args);
const serveShareTarget = event => {
// Redirect so the user can refresh the page without resending data.
event.respondWith(Response.redirect(event.request.url));
event.waitUntil(async function () {
const data = await event.request.formData();
const client = await self.clients.get(event.resultingClientId);
const file = data.get('file');
client.postMessage({ file, action: 'load-image' });
}());
};
const createCache = async (allowDelete = true) => {
const cache = await caches.open(KEY);
const keys = await cache.keys();
let newCdnPaths = [].concat(CDN_PATHS);
const deletePaths = [];
keys.forEach(({ url }) => {
// this is a CDN file that we still expect, leave it
if (CDN_PATHS.includes(url)) {
newCdnPaths = newCdnPaths.filter(u => u !== url);
return;
}
deletePaths.push(url);
});
if (allowDelete) {
log('CACHE DELETE', deletePaths);
await Promise.all(deletePaths.map(u => cache.delete(u)));
}
const newCachePaths = [].concat(APP_PATHS).concat(newCdnPaths);
log('CACHE ADD', newCachePaths);
await cache.addAll(newCachePaths);
};
self.addEventListener('install', (event) => {
log('INSTALL start');
const start = Date.now();
event.waitUntil((async () => {
await createCache(false);
await self.skipWaiting();
log(`INSTALL done in ${Date.now() - start}ms`);
})());
});
self.addEventListener('activate', (event) => {
log('ACTIVATE start');
const start = Date.now();
event.waitUntil((async () => {
await createCache();
await self.clients.claim();
log(`ACTIVATE done in ${Date.now() - start}ms`);
})());
});
self.addEventListener('fetch', (event) => {
log('fetch', event.request.method, event.request.url);
const url = new URL(event.request.url);
const isSameOrigin = url.origin === location.origin;
const isShareTarget = isSameOrigin && url.searchParams.has('share-target');
const isSharePost = isShareTarget && event.request.method === 'POST';
if (isSharePost) {
log('handling share target request');
return void serveShareTarget(event);
}
const local = {
host: location.hostname === 'localhost',
ip: /^([0-9]+\.){3}[0-9]+$/.test(location.hostname)
};
const isLocal = local.ip;
if (isLocal) {
return;
}
event.respondWith((async () => {
const cache = await caches.open(KEY);
const response = !isShareTarget ?
await cache.match(event.request) :
await cache.match(event.request, { ignoreSearch: true });
if (response) {
log('serving cache result for', event.request.method, event.request.url);
return response;
}
log('serving network result for', event.request.method, event.request.url);
return fetch(event.request);
})());
});