@docusaurus/plugin-pwa 2.0.0-beta.fc64c12e4 → 2.0.0
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/lib/index.d.ts +10 -0
- package/lib/index.js +164 -0
- package/lib/options.d.ts +9 -0
- package/lib/options.js +46 -0
- package/lib/registerSw.d.ts +18 -0
- package/lib/registerSw.js +186 -0
- package/lib/renderReloadPopup.d.ts +8 -0
- package/lib/renderReloadPopup.js +22 -0
- package/lib/sw.d.ts +7 -0
- package/lib/sw.js +111 -0
- package/lib/theme/PwaReloadPopup/index.d.ts +9 -0
- package/{src → lib}/theme/PwaReloadPopup/index.js +0 -4
- package/lib/theme/PwaReloadPopup/styles.module.css +39 -0
- package/package.json +35 -20
- package/src/deps.d.ts +15 -0
- package/src/{index.js → index.ts} +54 -43
- package/src/{pluginOptionSchema.js → options.ts} +17 -8
- package/src/plugin-pwa.d.ts +88 -0
- package/src/registerSw.ts +237 -0
- package/src/{renderReloadPopup.js → renderReloadPopup.tsx} +7 -5
- package/src/{sw.js → sw.ts} +36 -44
- package/src/theme/PwaReloadPopup/index.tsx +59 -0
- package/src/types.d.ts +8 -0
- package/src/registerSw.js +0 -303
package/src/{sw.js → sw.ts}
RENAMED
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
/* eslint-disable no-restricted-globals */
|
|
8
8
|
|
|
9
|
-
import {PrecacheController} from 'workbox-precaching';
|
|
9
|
+
import {PrecacheController, type PrecacheEntry} from 'workbox-precaching';
|
|
10
10
|
|
|
11
11
|
function parseSwParams() {
|
|
12
12
|
const params = JSON.parse(
|
|
13
|
-
new URLSearchParams(self.location.search).get('params')
|
|
13
|
+
new URLSearchParams(self.location.search).get('params')!,
|
|
14
14
|
);
|
|
15
15
|
if (params.debug) {
|
|
16
16
|
console.log('[Docusaurus-PWA][SW]: Service Worker params:', params);
|
|
@@ -18,11 +18,11 @@ function parseSwParams() {
|
|
|
18
18
|
return params;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
//
|
|
21
|
+
// Doc advises against dynamic imports in SW
|
|
22
22
|
// https://developers.google.com/web/tools/workbox/guides/using-bundlers#code_splitting_and_dynamic_imports
|
|
23
23
|
// https://twitter.com/sebastienlorber/status/1280155204575518720
|
|
24
|
-
// but
|
|
25
|
-
async function runSWCustomCode(params) {
|
|
24
|
+
// but looks it's working fine as it's inlined by webpack, need to double check
|
|
25
|
+
async function runSWCustomCode(params: {offlineMode: boolean; debug: boolean}) {
|
|
26
26
|
if (process.env.PWA_SW_CUSTOM) {
|
|
27
27
|
const customSW = await import(process.env.PWA_SW_CUSTOM);
|
|
28
28
|
if (typeof customSW.default === 'function') {
|
|
@@ -38,49 +38,43 @@ async function runSWCustomCode(params) {
|
|
|
38
38
|
/**
|
|
39
39
|
* Gets different possible variations for a request URL. Similar to
|
|
40
40
|
* https://git.io/JvixK
|
|
41
|
-
*
|
|
42
|
-
* @param {string} url
|
|
43
41
|
*/
|
|
44
|
-
function getPossibleURLs(url) {
|
|
45
|
-
const possibleURLs = [];
|
|
42
|
+
function getPossibleURLs(url: string) {
|
|
46
43
|
const urlObject = new URL(url, self.location.href);
|
|
47
44
|
|
|
48
45
|
if (urlObject.origin !== self.location.origin) {
|
|
49
|
-
return
|
|
46
|
+
return [];
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
// Ignore search params and hash
|
|
53
50
|
urlObject.search = '';
|
|
54
51
|
urlObject.hash = '';
|
|
55
52
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (urlObject.pathname.endsWith('/')) {
|
|
61
|
-
possibleURLs.push(`${urlObject.href}index.html`);
|
|
62
|
-
} else {
|
|
53
|
+
return [
|
|
54
|
+
// /blog.html
|
|
55
|
+
urlObject.href,
|
|
56
|
+
// /blog/ => /blog/index.html
|
|
63
57
|
// /blog => /blog/index.html
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return possibleURLs;
|
|
58
|
+
`${urlObject.href}${urlObject.pathname.endsWith('/') ? '' : '/'}index.html`,
|
|
59
|
+
];
|
|
68
60
|
}
|
|
69
61
|
|
|
70
62
|
(async () => {
|
|
71
63
|
const params = parseSwParams();
|
|
72
64
|
|
|
73
|
-
|
|
65
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
66
|
+
const precacheManifest = (
|
|
67
|
+
self as typeof globalThis & {__WB_MANIFEST: (string | PrecacheEntry)[]}
|
|
68
|
+
).__WB_MANIFEST;
|
|
74
69
|
const controller = new PrecacheController({
|
|
75
|
-
|
|
70
|
+
// Safer to turn this true?
|
|
71
|
+
fallbackToNetwork: true,
|
|
76
72
|
});
|
|
77
73
|
|
|
78
74
|
if (params.offlineMode) {
|
|
79
75
|
controller.addToCacheList(precacheManifest);
|
|
80
76
|
if (params.debug) {
|
|
81
|
-
console.log('[Docusaurus-PWA][SW]: addToCacheList', {
|
|
82
|
-
precacheManifest,
|
|
83
|
-
});
|
|
77
|
+
console.log('[Docusaurus-PWA][SW]: addToCacheList', {precacheManifest});
|
|
84
78
|
}
|
|
85
79
|
}
|
|
86
80
|
|
|
@@ -88,31 +82,30 @@ function getPossibleURLs(url) {
|
|
|
88
82
|
|
|
89
83
|
self.addEventListener('install', (event) => {
|
|
90
84
|
if (params.debug) {
|
|
91
|
-
console.log('[Docusaurus-PWA][SW]: install event', {
|
|
92
|
-
event,
|
|
93
|
-
});
|
|
85
|
+
console.log('[Docusaurus-PWA][SW]: install event', {event});
|
|
94
86
|
}
|
|
95
|
-
event.waitUntil(
|
|
87
|
+
(event as ExtendableEvent).waitUntil(
|
|
88
|
+
controller.install(event as ExtendableEvent),
|
|
89
|
+
);
|
|
96
90
|
});
|
|
97
91
|
|
|
98
92
|
self.addEventListener('activate', (event) => {
|
|
99
93
|
if (params.debug) {
|
|
100
|
-
console.log('[Docusaurus-PWA][SW]: activate event', {
|
|
101
|
-
event,
|
|
102
|
-
});
|
|
94
|
+
console.log('[Docusaurus-PWA][SW]: activate event', {event});
|
|
103
95
|
}
|
|
104
|
-
event.waitUntil(
|
|
96
|
+
(event as ExtendableEvent).waitUntil(
|
|
97
|
+
controller.activate(event as ExtendableEvent),
|
|
98
|
+
);
|
|
105
99
|
});
|
|
106
100
|
|
|
107
101
|
self.addEventListener('fetch', async (event) => {
|
|
108
102
|
if (params.offlineMode) {
|
|
109
|
-
const requestURL = event.request.url;
|
|
103
|
+
const requestURL = (event as FetchEvent).request.url;
|
|
110
104
|
const possibleURLs = getPossibleURLs(requestURL);
|
|
111
|
-
for (
|
|
112
|
-
const possibleURL = possibleURLs[i];
|
|
105
|
+
for (const possibleURL of possibleURLs) {
|
|
113
106
|
const cacheKey = controller.getCacheKeyForURL(possibleURL);
|
|
114
107
|
if (cacheKey) {
|
|
115
|
-
const cachedResponse = caches.match(cacheKey)
|
|
108
|
+
const cachedResponse = caches.match(cacheKey) as Promise<Response>;
|
|
116
109
|
if (params.debug) {
|
|
117
110
|
console.log('[Docusaurus-PWA][SW]: serving cached asset', {
|
|
118
111
|
requestURL,
|
|
@@ -122,7 +115,7 @@ function getPossibleURLs(url) {
|
|
|
122
115
|
cachedResponse,
|
|
123
116
|
});
|
|
124
117
|
}
|
|
125
|
-
event.respondWith(cachedResponse);
|
|
118
|
+
(event as FetchEvent).respondWith(cachedResponse);
|
|
126
119
|
break;
|
|
127
120
|
}
|
|
128
121
|
}
|
|
@@ -131,15 +124,14 @@ function getPossibleURLs(url) {
|
|
|
131
124
|
|
|
132
125
|
self.addEventListener('message', async (event) => {
|
|
133
126
|
if (params.debug) {
|
|
134
|
-
console.log('[Docusaurus-PWA][SW]: message event', {
|
|
135
|
-
event,
|
|
136
|
-
});
|
|
127
|
+
console.log('[Docusaurus-PWA][SW]: message event', {event});
|
|
137
128
|
}
|
|
138
129
|
|
|
139
|
-
const type = event
|
|
130
|
+
const type = (event as MessageEvent).data?.type;
|
|
140
131
|
|
|
141
132
|
if (type === 'SKIP_WAITING') {
|
|
142
|
-
|
|
133
|
+
// lib def bug, see https://github.com/microsoft/TypeScript/issues/14877
|
|
134
|
+
(self as typeof globalThis & ServiceWorkerGlobalScope).skipWaiting();
|
|
143
135
|
}
|
|
144
136
|
});
|
|
145
137
|
})();
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React, {useState} from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import Translate, {translate} from '@docusaurus/Translate';
|
|
11
|
+
import type {Props} from '@theme/PwaReloadPopup';
|
|
12
|
+
|
|
13
|
+
import styles from './styles.module.css';
|
|
14
|
+
|
|
15
|
+
export default function PwaReloadPopup({onReload}: Props): JSX.Element | false {
|
|
16
|
+
const [isVisible, setIsVisible] = useState(true);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
isVisible && (
|
|
20
|
+
<div className={clsx('alert', 'alert--secondary', styles.popup)}>
|
|
21
|
+
<p>
|
|
22
|
+
<Translate
|
|
23
|
+
id="theme.PwaReloadPopup.info"
|
|
24
|
+
description="The text for PWA reload popup">
|
|
25
|
+
New version available
|
|
26
|
+
</Translate>
|
|
27
|
+
</p>
|
|
28
|
+
<div className={styles.buttonContainer}>
|
|
29
|
+
<button
|
|
30
|
+
className="button button--link"
|
|
31
|
+
type="button"
|
|
32
|
+
onClick={() => {
|
|
33
|
+
setIsVisible(false);
|
|
34
|
+
onReload();
|
|
35
|
+
}}>
|
|
36
|
+
<Translate
|
|
37
|
+
id="theme.PwaReloadPopup.refreshButtonText"
|
|
38
|
+
description="The text for PWA reload button">
|
|
39
|
+
Refresh
|
|
40
|
+
</Translate>
|
|
41
|
+
</button>
|
|
42
|
+
|
|
43
|
+
<button
|
|
44
|
+
aria-label={translate({
|
|
45
|
+
id: 'theme.PwaReloadPopup.closeButtonAriaLabel',
|
|
46
|
+
message: 'Close',
|
|
47
|
+
description:
|
|
48
|
+
'The ARIA label for close button of PWA reload popup',
|
|
49
|
+
})}
|
|
50
|
+
className="close"
|
|
51
|
+
type="button"
|
|
52
|
+
onClick={() => setIsVisible(false)}>
|
|
53
|
+
<span aria-hidden="true">×</span>
|
|
54
|
+
</button>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
)
|
|
58
|
+
);
|
|
59
|
+
}
|
package/src/types.d.ts
ADDED
package/src/registerSw.js
DELETED
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/
|
|
7
|
-
import {createStorageSlot} from '@docusaurus/theme-common';
|
|
8
|
-
|
|
9
|
-
// First: read the env variables (provided by Webpack)
|
|
10
|
-
/* eslint-disable prefer-destructuring */
|
|
11
|
-
const PWA_SERVICE_WORKER_URL = process.env.PWA_SERVICE_WORKER_URL;
|
|
12
|
-
const PWA_RELOAD_POPUP = process.env.PWA_RELOAD_POPUP;
|
|
13
|
-
const PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES =
|
|
14
|
-
process.env.PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES;
|
|
15
|
-
const PWA_DEBUG = process.env.PWA_DEBUG;
|
|
16
|
-
/* eslint-enable prefer-destructuring */
|
|
17
|
-
|
|
18
|
-
const debug = PWA_DEBUG; // shortcut
|
|
19
|
-
|
|
20
|
-
const MAX_MOBILE_WIDTH = 940;
|
|
21
|
-
|
|
22
|
-
const AppInstalledEventFiredStorage = createStorageSlot(
|
|
23
|
-
'docusaurus.pwa.event.appInstalled.fired',
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
async function clearRegistrations() {
|
|
27
|
-
const registrations = await navigator.serviceWorker.getRegistrations();
|
|
28
|
-
if (debug) {
|
|
29
|
-
console.log(
|
|
30
|
-
`[Docusaurus-PWA][registerSw]: will unregister all service worker registrations`,
|
|
31
|
-
registrations,
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
await Promise.all(
|
|
35
|
-
registrations.map(async (registration) => {
|
|
36
|
-
const result = await registration?.registration?.unregister();
|
|
37
|
-
if (debug) {
|
|
38
|
-
console.log(
|
|
39
|
-
`[Docusaurus-PWA][registerSw]: unregister() service worker registration`,
|
|
40
|
-
registrations,
|
|
41
|
-
result,
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
}),
|
|
45
|
-
);
|
|
46
|
-
if (debug) {
|
|
47
|
-
console.log(
|
|
48
|
-
`[Docusaurus-PWA][registerSw]: unregistered all service worker registrations`,
|
|
49
|
-
registrations,
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
window.location.reload();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/*
|
|
56
|
-
As of 2021:
|
|
57
|
-
It is complicated and not very reliable to detect an app is actually installed.
|
|
58
|
-
https://stackoverflow.com/questions/51735869/check-if-user-has-already-installed-pwa-to-homescreen-on-chrome
|
|
59
|
-
|
|
60
|
-
- appinstalled event is not in the spec anymore and seems to not fire? https://firt.dev/pwa-2021#less-capabilities-%E2%98%B9%EF%B8%8F
|
|
61
|
-
- getInstalledRelatedApps() is only supported in recent Chrome and does not seem to reliable either https://github.com/WICG/get-installed-related-apps
|
|
62
|
-
- display-mode: standalone is not exactly the same concept, but looks like a decent fallback https://petelepage.com/blog/2019/07/is-my-pwa-installed/
|
|
63
|
-
*/
|
|
64
|
-
async function isAppInstalledEventFired() {
|
|
65
|
-
return AppInstalledEventFiredStorage.get() === 'true';
|
|
66
|
-
}
|
|
67
|
-
async function isAppInstalledRelatedApps() {
|
|
68
|
-
if ('getInstalledRelatedApps' in window.navigator) {
|
|
69
|
-
const relatedApps = await navigator.getInstalledRelatedApps();
|
|
70
|
-
return relatedApps.some((app) => app.platform === 'webapp');
|
|
71
|
-
}
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
function isStandaloneDisplayMode() {
|
|
75
|
-
return window.matchMedia('(display-mode: standalone)').matches;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const OfflineModeActivationStrategiesImplementations = {
|
|
79
|
-
always: () => true,
|
|
80
|
-
mobile: () => window.innerWidth <= MAX_MOBILE_WIDTH,
|
|
81
|
-
saveData: () => !!(navigator.connection && navigator.connection.saveData),
|
|
82
|
-
appInstalled: async () => {
|
|
83
|
-
const installedEventFired = await isAppInstalledEventFired();
|
|
84
|
-
const installedRelatedApps = await isAppInstalledRelatedApps();
|
|
85
|
-
return installedEventFired || installedRelatedApps;
|
|
86
|
-
},
|
|
87
|
-
standalone: () => isStandaloneDisplayMode(),
|
|
88
|
-
queryString: () =>
|
|
89
|
-
new URLSearchParams(window.location.search).get('offlineMode') === 'true',
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
async function isStrategyActive(strategyName) {
|
|
93
|
-
return OfflineModeActivationStrategiesImplementations[strategyName]();
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async function getActiveStrategies() {
|
|
97
|
-
const activeStrategies = await Promise.all(
|
|
98
|
-
PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES.map(async (strategyName) => {
|
|
99
|
-
const isActive = await isStrategyActive(strategyName);
|
|
100
|
-
return isActive ? strategyName : undefined;
|
|
101
|
-
}),
|
|
102
|
-
);
|
|
103
|
-
return activeStrategies.filter(Boolean); // remove undefined values
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async function isOfflineModeEnabled() {
|
|
107
|
-
const activeStrategies = await getActiveStrategies();
|
|
108
|
-
const enabled = activeStrategies.length > 0;
|
|
109
|
-
if (debug) {
|
|
110
|
-
const logObject = {
|
|
111
|
-
activeStrategies,
|
|
112
|
-
availableStrategies: PWA_OFFLINE_MODE_ACTIVATION_STRATEGIES,
|
|
113
|
-
};
|
|
114
|
-
if (enabled) {
|
|
115
|
-
console.log(
|
|
116
|
-
'[Docusaurus-PWA][registerSw]: offline mode enabled, because of activation strategies',
|
|
117
|
-
logObject,
|
|
118
|
-
);
|
|
119
|
-
} else {
|
|
120
|
-
console.log(
|
|
121
|
-
'[Docusaurus-PWA][registerSw]: offline mode disabled, because none of the offlineModeActivationStrategies could be used',
|
|
122
|
-
logObject,
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return enabled;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function createServiceWorkerUrl(params) {
|
|
130
|
-
const paramsQueryString = JSON.stringify(params);
|
|
131
|
-
const url = `${PWA_SERVICE_WORKER_URL}?params=${encodeURIComponent(
|
|
132
|
-
paramsQueryString,
|
|
133
|
-
)}`;
|
|
134
|
-
if (debug) {
|
|
135
|
-
console.log(`[Docusaurus-PWA][registerSw]: service worker url`, {
|
|
136
|
-
url,
|
|
137
|
-
params,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
return url;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
async function registerSW() {
|
|
144
|
-
const {Workbox} = await import('workbox-window');
|
|
145
|
-
|
|
146
|
-
const offlineMode = await isOfflineModeEnabled();
|
|
147
|
-
|
|
148
|
-
const url = createServiceWorkerUrl({offlineMode, debug});
|
|
149
|
-
const wb = new Workbox(url);
|
|
150
|
-
|
|
151
|
-
const registration = await wb.register();
|
|
152
|
-
|
|
153
|
-
const sendSkipWaiting = () => wb.messageSW({type: 'SKIP_WAITING'});
|
|
154
|
-
|
|
155
|
-
const handleServiceWorkerWaiting = async () => {
|
|
156
|
-
if (debug) {
|
|
157
|
-
console.log('[Docusaurus-PWA][registerSw]: handleServiceWorkerWaiting');
|
|
158
|
-
}
|
|
159
|
-
// Immediately load new service worker when files aren't cached
|
|
160
|
-
if (!offlineMode) {
|
|
161
|
-
sendSkipWaiting();
|
|
162
|
-
} else if (PWA_RELOAD_POPUP) {
|
|
163
|
-
const renderReloadPopup = (await import('./renderReloadPopup')).default;
|
|
164
|
-
await renderReloadPopup({
|
|
165
|
-
onReload() {
|
|
166
|
-
wb.addEventListener('controlling', () => {
|
|
167
|
-
window.location.reload();
|
|
168
|
-
});
|
|
169
|
-
sendSkipWaiting();
|
|
170
|
-
},
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
if (debug) {
|
|
176
|
-
if (registration.active) {
|
|
177
|
-
console.log(
|
|
178
|
-
'[Docusaurus-PWA][registerSw]: registration.active',
|
|
179
|
-
registration,
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
if (registration.installing) {
|
|
183
|
-
console.log(
|
|
184
|
-
'[Docusaurus-PWA][registerSw]: registration.installing',
|
|
185
|
-
registration,
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
if (registration.waiting) {
|
|
189
|
-
console.log(
|
|
190
|
-
'[Docusaurus-PWA][registerSw]: registration.waiting',
|
|
191
|
-
registration,
|
|
192
|
-
);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Update the current service worker when the next one has finished
|
|
197
|
-
// installing and transitions to waiting state.
|
|
198
|
-
wb.addEventListener('waiting', (event) => {
|
|
199
|
-
if (debug) {
|
|
200
|
-
console.log('[Docusaurus-PWA][registerSw]: event waiting', event);
|
|
201
|
-
}
|
|
202
|
-
handleServiceWorkerWaiting();
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
// Update current service worker if the next one finishes installing and
|
|
206
|
-
// moves to waiting state in another tab.
|
|
207
|
-
wb.addEventListener('externalwaiting', (event) => {
|
|
208
|
-
if (debug) {
|
|
209
|
-
console.log('[Docusaurus-PWA][registerSw]: event externalwaiting', event);
|
|
210
|
-
}
|
|
211
|
-
handleServiceWorkerWaiting();
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
// Update service worker if the next one is already in the waiting state.
|
|
215
|
-
// This happens when the user doesn't click on `reload` in the popup.
|
|
216
|
-
if (registration.waiting) {
|
|
217
|
-
await handleServiceWorkerWaiting();
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// TODO these events still works in chrome but have been removed from the spec in 2019!
|
|
222
|
-
// See https://github.com/w3c/manifest/pull/836
|
|
223
|
-
function addLegacyAppInstalledEventsListeners() {
|
|
224
|
-
if (typeof window !== 'undefined') {
|
|
225
|
-
if (debug) {
|
|
226
|
-
console.log(
|
|
227
|
-
'[Docusaurus-PWA][registerSw]: addLegacyAppInstalledEventsListeners',
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
window.addEventListener('appinstalled', async (event) => {
|
|
232
|
-
if (debug) {
|
|
233
|
-
console.log('[Docusaurus-PWA][registerSw]: event appinstalled', event);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
AppInstalledEventFiredStorage.set('true');
|
|
237
|
-
if (debug) {
|
|
238
|
-
console.log(
|
|
239
|
-
"[Docusaurus-PWA][registerSw]: AppInstalledEventFiredStorage.set('true')",
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// After the app is installed, we register a service worker with the path
|
|
244
|
-
// `/sw?enabled`. Since the previous service worker was `/sw`, it'll be
|
|
245
|
-
// treated as a new one. The previous registration will need to be
|
|
246
|
-
// cleared, otherwise the reload popup will show.
|
|
247
|
-
await clearRegistrations();
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
// TODO this event still works in chrome but has been removed from the spec in 2019!!!
|
|
251
|
-
window.addEventListener('beforeinstallprompt', async (event) => {
|
|
252
|
-
if (debug) {
|
|
253
|
-
console.log(
|
|
254
|
-
'[Docusaurus-PWA][registerSw]: event beforeinstallprompt',
|
|
255
|
-
event,
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
// TODO instead of default browser install UI, show custom docusaurus prompt?
|
|
259
|
-
// event.preventDefault();
|
|
260
|
-
if (debug) {
|
|
261
|
-
console.log(
|
|
262
|
-
'[Docusaurus-PWA][registerSw]: AppInstalledEventFiredStorage.get()',
|
|
263
|
-
AppInstalledEventFiredStorage.get(),
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
if (AppInstalledEventFiredStorage.get()) {
|
|
267
|
-
AppInstalledEventFiredStorage.del();
|
|
268
|
-
if (debug) {
|
|
269
|
-
console.log(
|
|
270
|
-
'[Docusaurus-PWA][registerSw]: AppInstalledEventFiredStorage.del()',
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
// After uninstalling the app, if the user doesn't clear all data, then
|
|
274
|
-
// the previous service worker will continue serving cached files. We
|
|
275
|
-
// need to clear registrations and reload, otherwise the popup will show.
|
|
276
|
-
await clearRegistrations();
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
if (debug) {
|
|
281
|
-
console.log(
|
|
282
|
-
'[Docusaurus-PWA][registerSw]: legacy appinstalled and beforeinstallprompt event listeners installed',
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/*
|
|
289
|
-
Init code to run on the client!
|
|
290
|
-
*/
|
|
291
|
-
if (typeof window !== 'undefined') {
|
|
292
|
-
if (debug) {
|
|
293
|
-
console.log('[Docusaurus-PWA][registerSw]: debug mode enabled');
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
if ('serviceWorker' in navigator) {
|
|
297
|
-
// First: add the listeners asap/synchronously
|
|
298
|
-
addLegacyAppInstalledEventsListeners();
|
|
299
|
-
|
|
300
|
-
// Then try to register the SW using lazy/dynamic imports
|
|
301
|
-
registerSW().catch((e) => console.error('registerSW failed', e));
|
|
302
|
-
}
|
|
303
|
-
}
|