@eclipse-docks/extension-pwa 0.7.80 → 0.7.81
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/dist/{i18n.de-Dls2qCix.js → i18n.de-CorheGJa.js} +2 -2
- package/dist/i18n.de-CorheGJa.js.map +1 -0
- package/dist/{i18n.en-DZPstBWw.js → i18n.en-BjSrybGY.js} +2 -2
- package/dist/i18n.en-BjSrybGY.js.map +1 -0
- package/dist/index.js +3 -3
- package/dist/{pwa-extension-B3u-NX-p.js → pwa-extension-ClLKNADv.js} +36 -12
- package/dist/pwa-extension-ClLKNADv.js.map +1 -0
- package/dist/pwa-extension.d.ts.map +1 -1
- package/dist/sw-update-indicator.d.ts +4 -0
- package/dist/sw-update-indicator.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/i18n.de-Dls2qCix.js.map +0 -1
- package/dist/i18n.en-DZPstBWw.js.map +0 -1
- package/dist/pwa-extension-B3u-NX-p.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/i18n.de.json
|
|
2
2
|
var EXT_PWA_NAME = "PWA";
|
|
3
|
-
var EXT_PWA_DESC = "Service-Worker-Update und Installationshinweis in der
|
|
3
|
+
var EXT_PWA_DESC = "Service-Worker-Update und Installationshinweis in der mittleren Haupt-Symbolleiste, wenn der Browser das unterstützt.";
|
|
4
4
|
var i18n_de_default = {
|
|
5
5
|
EXT_PWA_NAME: "PWA",
|
|
6
6
|
EXT_PWA_DESC
|
|
@@ -8,4 +8,4 @@ var i18n_de_default = {
|
|
|
8
8
|
//#endregion
|
|
9
9
|
export { EXT_PWA_DESC, EXT_PWA_NAME, i18n_de_default as default };
|
|
10
10
|
|
|
11
|
-
//# sourceMappingURL=i18n.de-
|
|
11
|
+
//# sourceMappingURL=i18n.de-CorheGJa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.de-CorheGJa.js","names":[],"sources":["../src/i18n.de.json"],"sourcesContent":["{\n \"EXT_PWA_NAME\": \"PWA\",\n \"EXT_PWA_DESC\": \"Service-Worker-Update und Installationshinweis in der mittleren Haupt-Symbolleiste, wenn der Browser das unterstützt.\"\n}\n"],"mappings":""}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/i18n.en.json
|
|
2
2
|
var EXT_PWA_NAME = "PWA";
|
|
3
|
-
var EXT_PWA_DESC = "Service worker update control and install prompt in the
|
|
3
|
+
var EXT_PWA_DESC = "Service worker update control and install prompt in the main center toolbar when the browser supports them.";
|
|
4
4
|
var i18n_en_default = {
|
|
5
5
|
EXT_PWA_NAME: "PWA",
|
|
6
6
|
EXT_PWA_DESC
|
|
@@ -8,4 +8,4 @@ var i18n_en_default = {
|
|
|
8
8
|
//#endregion
|
|
9
9
|
export { EXT_PWA_DESC, EXT_PWA_NAME, i18n_en_default as default };
|
|
10
10
|
|
|
11
|
-
//# sourceMappingURL=i18n.en-
|
|
11
|
+
//# sourceMappingURL=i18n.en-BjSrybGY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.en-BjSrybGY.js","names":[],"sources":["../src/i18n.en.json"],"sourcesContent":["{\n \"EXT_PWA_NAME\": \"PWA\",\n \"EXT_PWA_DESC\": \"Service worker update control and install prompt in the main center toolbar when the browser supports them.\"\n}\n"],"mappings":""}
|
package/dist/index.js
CHANGED
|
@@ -3,14 +3,14 @@ import { extensionRegistry, i18n } from "@eclipse-docks/core";
|
|
|
3
3
|
import pkg from "../package.json";
|
|
4
4
|
//#region src/index.ts
|
|
5
5
|
var t = await i18n(/* @__PURE__ */ Object.assign({
|
|
6
|
-
"./i18n.de.json": () => import("./i18n.de-
|
|
7
|
-
"./i18n.en.json": () => import("./i18n.en-
|
|
6
|
+
"./i18n.de.json": () => import("./i18n.de-CorheGJa.js"),
|
|
7
|
+
"./i18n.en.json": () => import("./i18n.en-BjSrybGY.js")
|
|
8
8
|
}), true);
|
|
9
9
|
extensionRegistry.registerExtension({
|
|
10
10
|
id: pkg.name,
|
|
11
11
|
name: t.EXT_PWA_NAME,
|
|
12
12
|
description: t.EXT_PWA_DESC,
|
|
13
|
-
loader: () => import("./pwa-extension-
|
|
13
|
+
loader: () => import("./pwa-extension-ClLKNADv.js"),
|
|
14
14
|
icon: "download"
|
|
15
15
|
});
|
|
16
16
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as clearInstallPromptCapture, r as peekInstallPrompt, t as PWA_INSTALL_PROMPT_AVAILABLE } from "./install-prompt-capture-fZikSCg3.js";
|
|
2
|
-
import { DocksElement,
|
|
2
|
+
import { DocksElement, TOOLBAR_BOTTOM_END, contributionRegistry } from "@eclipse-docks/core";
|
|
3
3
|
import { html } from "lit";
|
|
4
4
|
import { customElement, state } from "lit/decorators.js";
|
|
5
5
|
import _decorate from "@oxc-project/runtime/helpers/decorate";
|
|
@@ -21,6 +21,7 @@ var DocksSwUpdateIndicator = class DocksSwUpdateIndicator extends DocksElement {
|
|
|
21
21
|
this.onUpdateFound = () => {
|
|
22
22
|
const registration = this.registration;
|
|
23
23
|
if (!registration) return;
|
|
24
|
+
this.syncUpdateState(registration);
|
|
24
25
|
const installing = registration.installing;
|
|
25
26
|
if (!installing) return;
|
|
26
27
|
const signal = this.attachAbort?.signal;
|
|
@@ -77,8 +78,14 @@ var DocksSwUpdateIndicator = class DocksSwUpdateIndicator extends DocksElement {
|
|
|
77
78
|
this.registration = null;
|
|
78
79
|
this.updateAvailable = false;
|
|
79
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Show only when a new worker is waiting and an older version is already controlling
|
|
83
|
+
* the page (real update). Avoid treating the first install as an “update”.
|
|
84
|
+
*/
|
|
80
85
|
syncUpdateState(registration) {
|
|
81
|
-
|
|
86
|
+
const waiting = Boolean(registration.waiting);
|
|
87
|
+
const hasActiveController = Boolean(navigator.serviceWorker.controller);
|
|
88
|
+
this.updateAvailable = waiting && hasActiveController;
|
|
82
89
|
}
|
|
83
90
|
attach(registration) {
|
|
84
91
|
if (this.registration === registration) return;
|
|
@@ -92,6 +99,10 @@ var DocksSwUpdateIndicator = class DocksSwUpdateIndicator extends DocksElement {
|
|
|
92
99
|
this.periodicInterval = window.setInterval(() => {
|
|
93
100
|
registration.update().catch(() => {});
|
|
94
101
|
}, 3600 * 1e3);
|
|
102
|
+
queueMicrotask(() => {
|
|
103
|
+
if (this.registration !== registration) return;
|
|
104
|
+
this.syncUpdateState(registration);
|
|
105
|
+
});
|
|
95
106
|
}
|
|
96
107
|
onActivateClick() {
|
|
97
108
|
const w = this.registration?.waiting;
|
|
@@ -105,14 +116,27 @@ var DocksSwUpdateIndicator = class DocksSwUpdateIndicator extends DocksElement {
|
|
|
105
116
|
render() {
|
|
106
117
|
if (!this.updateAvailable) return html``;
|
|
107
118
|
return html`
|
|
108
|
-
<wa-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
119
|
+
<wa-animation
|
|
120
|
+
style="display: inline-flex; align-items: center;"
|
|
121
|
+
name="zoomIn"
|
|
122
|
+
duration="1400"
|
|
123
|
+
easing="ease-out"
|
|
124
|
+
iterations="Infinity"
|
|
125
|
+
?play=${true}
|
|
113
126
|
>
|
|
114
|
-
<wa-
|
|
115
|
-
|
|
127
|
+
<wa-button
|
|
128
|
+
appearance="plain"
|
|
129
|
+
title="A new version is available. Click to reload."
|
|
130
|
+
aria-label="A new version is available. Reload to update."
|
|
131
|
+
@click=${this.onActivateClick}
|
|
132
|
+
>
|
|
133
|
+
<wa-icon
|
|
134
|
+
name="arrows-rotate"
|
|
135
|
+
label=""
|
|
136
|
+
style="color: var(--wa-color-danger-fill-loud)"
|
|
137
|
+
></wa-icon>
|
|
138
|
+
</wa-button>
|
|
139
|
+
</wa-animation>
|
|
116
140
|
`;
|
|
117
141
|
}
|
|
118
142
|
};
|
|
@@ -184,16 +208,16 @@ DocksPwaInstall = _decorate([customElement("docks-pwa-install")], DocksPwaInstal
|
|
|
184
208
|
//#region src/pwa-extension.ts
|
|
185
209
|
var TOOLBAR_SW_UPDATE = "toolbar.swUpdate";
|
|
186
210
|
var TOOLBAR_PWA_INSTALL = "toolbar.pwaInstall";
|
|
187
|
-
contributionRegistry.registerContribution(
|
|
211
|
+
contributionRegistry.registerContribution(TOOLBAR_BOTTOM_END, {
|
|
188
212
|
name: TOOLBAR_SW_UPDATE,
|
|
189
213
|
label: "App update",
|
|
190
214
|
component: `<docks-sw-update-indicator></docks-sw-update-indicator>`
|
|
191
215
|
});
|
|
192
|
-
contributionRegistry.registerContribution(
|
|
216
|
+
contributionRegistry.registerContribution(TOOLBAR_BOTTOM_END, {
|
|
193
217
|
name: TOOLBAR_PWA_INSTALL,
|
|
194
218
|
label: "Install app",
|
|
195
219
|
component: `<docks-pwa-install></docks-pwa-install>`
|
|
196
220
|
});
|
|
197
221
|
//#endregion
|
|
198
222
|
|
|
199
|
-
//# sourceMappingURL=pwa-extension-
|
|
223
|
+
//# sourceMappingURL=pwa-extension-ClLKNADv.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pwa-extension-ClLKNADv.js","names":[],"sources":["../src/sw-update-indicator.ts","../src/pwa-install-button.ts","../src/pwa-extension.ts"],"sourcesContent":["import { html } from 'lit';\nimport { customElement, state } from 'lit/decorators.js';\n\nimport { DocksElement } from '@eclipse-docks/core';\n\n/**\n * Shows a toolbar icon when a new service worker is waiting (vite-plugin-pwa injectManifest + SKIP_WAITING message).\n * Hidden when there is no update or when service workers are unavailable.\n *\n * Safe when the extension loads late: attaches via `getRegistration()`, reads `registration.waiting`,\n * and subscribes to `updatefound` for subsequent updates.\n */\n@customElement('docks-sw-update-indicator')\nexport class DocksSwUpdateIndicator extends DocksElement {\n @state()\n private updateAvailable = false;\n\n private pendingReload = false;\n private registration: ServiceWorkerRegistration | null = null;\n private periodicInterval: number | null = null;\n private pollInterval: number | null = null;\n private pollAttempts = 0;\n private attachAbort: AbortController | null = null;\n\n private readonly onControllerChange = (): void => {\n if (!this.pendingReload) {\n return;\n }\n window.location.reload();\n };\n\n connectedCallback(): void {\n super.connectedCallback();\n if (!('serviceWorker' in navigator)) {\n return;\n }\n navigator.serviceWorker.addEventListener('controllerchange', this.onControllerChange);\n void this.findOrAttachRegistration();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n navigator.serviceWorker.removeEventListener('controllerchange', this.onControllerChange);\n this.teardownAttachment();\n }\n\n private async findOrAttachRegistration(): Promise<void> {\n const existing = await navigator.serviceWorker.getRegistration();\n if (existing) {\n this.attach(existing);\n return;\n }\n\n this.pollInterval = window.setInterval(async () => {\n this.pollAttempts += 1;\n const reg = await navigator.serviceWorker.getRegistration();\n if (reg) {\n this.clearPoll();\n this.attach(reg);\n return;\n }\n if (this.pollAttempts >= 30) {\n this.clearPoll();\n }\n }, 1000);\n }\n\n private clearPoll(): void {\n if (this.pollInterval !== null) {\n window.clearInterval(this.pollInterval);\n this.pollInterval = null;\n }\n }\n\n private teardownAttachment(): void {\n this.clearPoll();\n if (this.periodicInterval !== null) {\n window.clearInterval(this.periodicInterval);\n this.periodicInterval = null;\n }\n this.attachAbort?.abort();\n this.attachAbort = null;\n this.registration = null;\n this.updateAvailable = false;\n }\n\n /**\n * Show only when a new worker is waiting and an older version is already controlling\n * the page (real update). Avoid treating the first install as an “update”.\n */\n private syncUpdateState(registration: ServiceWorkerRegistration): void {\n const waiting = Boolean(registration.waiting);\n const hasActiveController = Boolean(navigator.serviceWorker.controller);\n this.updateAvailable = waiting && hasActiveController;\n }\n\n private readonly onUpdateFound = (): void => {\n const registration = this.registration;\n if (!registration) {\n return;\n }\n // Fast installs (common in standalone PWA): worker may already be `waiting` when\n // this runs, with `installing` already null — still an update if a controller exists.\n this.syncUpdateState(registration);\n\n const installing = registration.installing;\n if (!installing) {\n return;\n }\n const signal = this.attachAbort?.signal;\n if (!signal) {\n return;\n }\n installing.addEventListener(\n 'statechange',\n () => {\n if (installing.state !== 'installed') {\n return;\n }\n if (!navigator.serviceWorker.controller) {\n return;\n }\n this.syncUpdateState(registration);\n },\n { signal },\n );\n };\n\n private attach(registration: ServiceWorkerRegistration): void {\n if (this.registration === registration) {\n return;\n }\n this.attachAbort?.abort();\n this.attachAbort = new AbortController();\n const signal = this.attachAbort.signal;\n\n this.registration = registration;\n this.syncUpdateState(registration);\n\n registration.addEventListener('updatefound', this.onUpdateFound, { signal });\n\n void registration.update().catch(() => {});\n this.periodicInterval = window.setInterval(() => {\n void registration.update().catch(() => {});\n }, 60 * 60 * 1000);\n\n queueMicrotask(() => {\n if (this.registration !== registration) {\n return;\n }\n this.syncUpdateState(registration);\n });\n }\n\n private onActivateClick(): void {\n const w = this.registration?.waiting;\n if (w) {\n this.pendingReload = true;\n w.postMessage({ type: 'SKIP_WAITING' });\n return;\n }\n window.location.reload();\n }\n\n protected render() {\n if (!this.updateAvailable) {\n return html``;\n }\n\n return html`\n <wa-animation\n style=\"display: inline-flex; align-items: center;\"\n name=\"zoomIn\"\n duration=\"1400\"\n easing=\"ease-out\"\n iterations=\"Infinity\"\n ?play=${true}\n >\n <wa-button\n appearance=\"plain\"\n title=\"A new version is available. Click to reload.\"\n aria-label=\"A new version is available. Reload to update.\"\n @click=${this.onActivateClick}\n >\n <wa-icon\n name=\"arrows-rotate\"\n label=\"\"\n style=\"color: var(--wa-color-danger-fill-loud)\"\n ></wa-icon>\n </wa-button>\n </wa-animation>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-sw-update-indicator': DocksSwUpdateIndicator;\n }\n}\n","import { html } from 'lit';\nimport { customElement, state } from 'lit/decorators.js';\n\nimport { DocksElement } from '@eclipse-docks/core';\n\nimport {\n clearInstallPromptCapture,\n peekInstallPrompt,\n PWA_INSTALL_PROMPT_AVAILABLE,\n type PwaInstallPromptEvent,\n} from './install-prompt-capture';\n\nfunction isRunningAsInstalledPwa(): boolean {\n return (\n window.matchMedia('(display-mode: standalone)').matches ||\n window.matchMedia('(display-mode: window-controls-overlay)').matches ||\n (window.navigator as Navigator & { standalone?: boolean }).standalone === true\n );\n}\n\n@customElement('docks-pwa-install')\nexport class DocksPwaInstall extends DocksElement {\n @state()\n private showInstall = false;\n\n private deferredPrompt: PwaInstallPromptEvent | null = null;\n\n private readonly onPromptAvailable = (): void => {\n this.applyCapturedPrompt();\n };\n\n private readonly onAppInstalled = (): void => {\n clearInstallPromptCapture();\n this.deferredPrompt = null;\n this.showInstall = false;\n };\n\n private applyCapturedPrompt(): void {\n const p = peekInstallPrompt();\n if (!p) {\n return;\n }\n this.deferredPrompt = p;\n this.showInstall = true;\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n if (isRunningAsInstalledPwa()) {\n return;\n }\n this.applyCapturedPrompt();\n window.addEventListener(PWA_INSTALL_PROMPT_AVAILABLE, this.onPromptAvailable);\n window.addEventListener('appinstalled', this.onAppInstalled);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n window.removeEventListener(PWA_INSTALL_PROMPT_AVAILABLE, this.onPromptAvailable);\n window.removeEventListener('appinstalled', this.onAppInstalled);\n }\n\n private async onInstallClick(): Promise<void> {\n const promptEvent = this.deferredPrompt;\n if (!promptEvent) {\n return;\n }\n await promptEvent.prompt();\n await promptEvent.userChoice.catch(() => {});\n clearInstallPromptCapture();\n this.deferredPrompt = null;\n this.showInstall = false;\n }\n\n protected render() {\n if (!this.showInstall) {\n return html``;\n }\n\n return html`\n <wa-button\n appearance=\"plain\"\n title=\"Install this app on your device\"\n aria-label=\"Install app\"\n @click=${() => void this.onInstallClick()}\n >\n <wa-icon name=\"download\" label=\"\"></wa-icon>\n </wa-button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-pwa-install': DocksPwaInstall;\n }\n}\n","import { contributionRegistry, type HTMLContribution, TOOLBAR_BOTTOM_END } from '@eclipse-docks/core';\nimport './sw-update-indicator';\nimport './pwa-install-button';\n\nconst TOOLBAR_SW_UPDATE = 'toolbar.swUpdate';\nconst TOOLBAR_PWA_INSTALL = 'toolbar.pwaInstall';\n\ncontributionRegistry.registerContribution(TOOLBAR_BOTTOM_END, {\n name: TOOLBAR_SW_UPDATE,\n label: 'App update',\n component: `<docks-sw-update-indicator></docks-sw-update-indicator>`,\n} as HTMLContribution);\n\ncontributionRegistry.registerContribution(TOOLBAR_BOTTOM_END, {\n name: TOOLBAR_PWA_INSTALL,\n label: 'Install app',\n component: `<docks-pwa-install></docks-pwa-install>`,\n} as HTMLContribution);\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pwa-extension.d.ts","sourceRoot":"","sources":["../src/pwa-extension.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pwa-extension.d.ts","sourceRoot":"","sources":["../src/pwa-extension.ts"],"names":[],"mappings":"AACA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,sBAAsB,CAAC"}
|
|
@@ -20,6 +20,10 @@ export declare class DocksSwUpdateIndicator extends DocksElement {
|
|
|
20
20
|
private findOrAttachRegistration;
|
|
21
21
|
private clearPoll;
|
|
22
22
|
private teardownAttachment;
|
|
23
|
+
/**
|
|
24
|
+
* Show only when a new worker is waiting and an older version is already controlling
|
|
25
|
+
* the page (real update). Avoid treating the first install as an “update”.
|
|
26
|
+
*/
|
|
23
27
|
private syncUpdateState;
|
|
24
28
|
private readonly onUpdateFound;
|
|
25
29
|
private attach;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sw-update-indicator.d.ts","sourceRoot":"","sources":["../src/sw-update-indicator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;;;;;GAMG;AACH,qBACa,sBAAuB,SAAQ,YAAY;IAEtD,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,WAAW,CAAgC;IAEnD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAKjC;IAEF,iBAAiB,IAAI,IAAI;IASzB,oBAAoB,IAAI,IAAI;YAMd,wBAAwB;IAqBtC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,eAAe;
|
|
1
|
+
{"version":3,"file":"sw-update-indicator.d.ts","sourceRoot":"","sources":["../src/sw-update-indicator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;;;;;GAMG;AACH,qBACa,sBAAuB,SAAQ,YAAY;IAEtD,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,WAAW,CAAgC;IAEnD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAKjC;IAEF,iBAAiB,IAAI,IAAI;IASzB,oBAAoB,IAAI,IAAI;YAMd,wBAAwB;IAqBtC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,kBAAkB;IAY1B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CA8B5B;IAEF,OAAO,CAAC,MAAM;IA0Bd,OAAO,CAAC,eAAe;IAUvB,SAAS,CAAC,MAAM;CA6BjB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,2BAA2B,EAAE,sBAAsB,CAAC;KACrD;CACF"}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.de-Dls2qCix.js","names":[],"sources":["../src/i18n.de.json"],"sourcesContent":["{\n \"EXT_PWA_NAME\": \"PWA\",\n \"EXT_PWA_DESC\": \"Service-Worker-Update und Installationshinweis in der unteren Symbolleiste, wenn der Browser das unterstützt.\"\n}\n"],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.en-DZPstBWw.js","names":[],"sources":["../src/i18n.en.json"],"sourcesContent":["{\n \"EXT_PWA_NAME\": \"PWA\",\n \"EXT_PWA_DESC\": \"Service worker update control and install prompt in the bottom toolbar when the browser supports them.\"\n}\n"],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pwa-extension-B3u-NX-p.js","names":[],"sources":["../src/sw-update-indicator.ts","../src/pwa-install-button.ts","../src/pwa-extension.ts"],"sourcesContent":["import { html } from 'lit';\nimport { customElement, state } from 'lit/decorators.js';\n\nimport { DocksElement } from '@eclipse-docks/core';\n\n/**\n * Shows a toolbar icon when a new service worker is waiting (vite-plugin-pwa injectManifest + SKIP_WAITING message).\n * Hidden when there is no update or when service workers are unavailable.\n *\n * Safe when the extension loads late: attaches via `getRegistration()`, reads `registration.waiting`,\n * and subscribes to `updatefound` for subsequent updates.\n */\n@customElement('docks-sw-update-indicator')\nexport class DocksSwUpdateIndicator extends DocksElement {\n @state()\n private updateAvailable = false;\n\n private pendingReload = false;\n private registration: ServiceWorkerRegistration | null = null;\n private periodicInterval: number | null = null;\n private pollInterval: number | null = null;\n private pollAttempts = 0;\n private attachAbort: AbortController | null = null;\n\n private readonly onControllerChange = (): void => {\n if (!this.pendingReload) {\n return;\n }\n window.location.reload();\n };\n\n connectedCallback(): void {\n super.connectedCallback();\n if (!('serviceWorker' in navigator)) {\n return;\n }\n navigator.serviceWorker.addEventListener('controllerchange', this.onControllerChange);\n void this.findOrAttachRegistration();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n navigator.serviceWorker.removeEventListener('controllerchange', this.onControllerChange);\n this.teardownAttachment();\n }\n\n private async findOrAttachRegistration(): Promise<void> {\n const existing = await navigator.serviceWorker.getRegistration();\n if (existing) {\n this.attach(existing);\n return;\n }\n\n this.pollInterval = window.setInterval(async () => {\n this.pollAttempts += 1;\n const reg = await navigator.serviceWorker.getRegistration();\n if (reg) {\n this.clearPoll();\n this.attach(reg);\n return;\n }\n if (this.pollAttempts >= 30) {\n this.clearPoll();\n }\n }, 1000);\n }\n\n private clearPoll(): void {\n if (this.pollInterval !== null) {\n window.clearInterval(this.pollInterval);\n this.pollInterval = null;\n }\n }\n\n private teardownAttachment(): void {\n this.clearPoll();\n if (this.periodicInterval !== null) {\n window.clearInterval(this.periodicInterval);\n this.periodicInterval = null;\n }\n this.attachAbort?.abort();\n this.attachAbort = null;\n this.registration = null;\n this.updateAvailable = false;\n }\n\n private syncUpdateState(registration: ServiceWorkerRegistration): void {\n this.updateAvailable = Boolean(registration.waiting);\n }\n\n private readonly onUpdateFound = (): void => {\n const registration = this.registration;\n if (!registration) {\n return;\n }\n const installing = registration.installing;\n if (!installing) {\n return;\n }\n const signal = this.attachAbort?.signal;\n if (!signal) {\n return;\n }\n installing.addEventListener(\n 'statechange',\n () => {\n if (installing.state !== 'installed') {\n return;\n }\n if (!navigator.serviceWorker.controller) {\n return;\n }\n this.syncUpdateState(registration);\n },\n { signal },\n );\n };\n\n private attach(registration: ServiceWorkerRegistration): void {\n if (this.registration === registration) {\n return;\n }\n this.attachAbort?.abort();\n this.attachAbort = new AbortController();\n const signal = this.attachAbort.signal;\n\n this.registration = registration;\n this.syncUpdateState(registration);\n\n registration.addEventListener('updatefound', this.onUpdateFound, { signal });\n\n void registration.update().catch(() => {});\n this.periodicInterval = window.setInterval(() => {\n void registration.update().catch(() => {});\n }, 60 * 60 * 1000);\n }\n\n private onActivateClick(): void {\n const w = this.registration?.waiting;\n if (w) {\n this.pendingReload = true;\n w.postMessage({ type: 'SKIP_WAITING' });\n return;\n }\n window.location.reload();\n }\n\n protected render() {\n if (!this.updateAvailable) {\n return html``;\n }\n\n return html`\n <wa-button\n appearance=\"plain\"\n title=\"A new version is available. Click to reload.\"\n aria-label=\"A new version is available. Reload to update.\"\n @click=${this.onActivateClick}\n >\n <wa-icon name=\"arrows-rotate\" label=\"\"></wa-icon>\n </wa-button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-sw-update-indicator': DocksSwUpdateIndicator;\n }\n}\n","import { html } from 'lit';\nimport { customElement, state } from 'lit/decorators.js';\n\nimport { DocksElement } from '@eclipse-docks/core';\n\nimport {\n clearInstallPromptCapture,\n peekInstallPrompt,\n PWA_INSTALL_PROMPT_AVAILABLE,\n type PwaInstallPromptEvent,\n} from './install-prompt-capture';\n\nfunction isRunningAsInstalledPwa(): boolean {\n return (\n window.matchMedia('(display-mode: standalone)').matches ||\n window.matchMedia('(display-mode: window-controls-overlay)').matches ||\n (window.navigator as Navigator & { standalone?: boolean }).standalone === true\n );\n}\n\n@customElement('docks-pwa-install')\nexport class DocksPwaInstall extends DocksElement {\n @state()\n private showInstall = false;\n\n private deferredPrompt: PwaInstallPromptEvent | null = null;\n\n private readonly onPromptAvailable = (): void => {\n this.applyCapturedPrompt();\n };\n\n private readonly onAppInstalled = (): void => {\n clearInstallPromptCapture();\n this.deferredPrompt = null;\n this.showInstall = false;\n };\n\n private applyCapturedPrompt(): void {\n const p = peekInstallPrompt();\n if (!p) {\n return;\n }\n this.deferredPrompt = p;\n this.showInstall = true;\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n if (isRunningAsInstalledPwa()) {\n return;\n }\n this.applyCapturedPrompt();\n window.addEventListener(PWA_INSTALL_PROMPT_AVAILABLE, this.onPromptAvailable);\n window.addEventListener('appinstalled', this.onAppInstalled);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n window.removeEventListener(PWA_INSTALL_PROMPT_AVAILABLE, this.onPromptAvailable);\n window.removeEventListener('appinstalled', this.onAppInstalled);\n }\n\n private async onInstallClick(): Promise<void> {\n const promptEvent = this.deferredPrompt;\n if (!promptEvent) {\n return;\n }\n await promptEvent.prompt();\n await promptEvent.userChoice.catch(() => {});\n clearInstallPromptCapture();\n this.deferredPrompt = null;\n this.showInstall = false;\n }\n\n protected render() {\n if (!this.showInstall) {\n return html``;\n }\n\n return html`\n <wa-button\n appearance=\"plain\"\n title=\"Install this app on your device\"\n aria-label=\"Install app\"\n @click=${() => void this.onInstallClick()}\n >\n <wa-icon name=\"download\" label=\"\"></wa-icon>\n </wa-button>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'docks-pwa-install': DocksPwaInstall;\n }\n}\n","import { contributionRegistry, type HTMLContribution } from '@eclipse-docks/core';\nimport { TOOLBAR_BOTTOM } from '@eclipse-docks/core';\nimport './sw-update-indicator';\nimport './pwa-install-button';\n\nconst TOOLBAR_SW_UPDATE = 'toolbar.swUpdate';\nconst TOOLBAR_PWA_INSTALL = 'toolbar.pwaInstall';\n\ncontributionRegistry.registerContribution(TOOLBAR_BOTTOM, {\n name: TOOLBAR_SW_UPDATE,\n label: 'App update',\n component: `<docks-sw-update-indicator></docks-sw-update-indicator>`,\n} as HTMLContribution);\n\ncontributionRegistry.registerContribution(TOOLBAR_BOTTOM, {\n name: TOOLBAR_PWA_INSTALL,\n label: 'Install app',\n component: `<docks-pwa-install></docks-pwa-install>`,\n} as HTMLContribution);\n"],"mappings":"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"}
|