@eclipse-docks/extension-pwa 0.7.127 → 0.7.132
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-BJRO1uvt.js +11 -0
- package/dist/i18n.de-BJRO1uvt.js.map +1 -0
- package/dist/{i18n.en-BjSrybGY.js → i18n.en-CPtNgwwB.js} +2 -2
- package/dist/i18n.en-CPtNgwwB.js.map +1 -0
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/{install-prompt-capture-fZikSCg3.js → install-prompt-capture-CRH1BlxV.js} +1 -1
- package/dist/{install-prompt-capture-fZikSCg3.js.map → install-prompt-capture-CRH1BlxV.js.map} +1 -1
- package/dist/{pwa-extension-BaUCo7Mu.js → pwa-extension-VQuZNJbI.js} +13 -25
- package/dist/pwa-extension-VQuZNJbI.js.map +1 -0
- package/dist/sw-update-indicator.d.ts +2 -1
- package/dist/sw-update-indicator.d.ts.map +1 -1
- package/dist/vite-pwa-plugin.js.map +1 -1
- package/package.json +1 -1
- package/dist/i18n.de-CorheGJa.js +0 -11
- package/dist/i18n.de-CorheGJa.js.map +0 -1
- package/dist/i18n.en-BjSrybGY.js.map +0 -1
- package/dist/pwa-extension-BaUCo7Mu.js.map +0 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/i18n.de.json
|
|
2
|
+
var EXT_PWA_NAME = "PWA";
|
|
3
|
+
var EXT_PWA_DESC = "Service-Worker-Update-Anzeige in der Haupt-Symbolleiste und Installationshinweis in der mittleren Symbolleiste, wenn der Browser das unterstützt.";
|
|
4
|
+
var i18n_de_default = {
|
|
5
|
+
EXT_PWA_NAME: "PWA",
|
|
6
|
+
EXT_PWA_DESC
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
9
|
+
export { EXT_PWA_DESC, EXT_PWA_NAME, i18n_de_default as default };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=i18n.de-BJRO1uvt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.de-BJRO1uvt.js","names":[],"sources":["../src/i18n.de.json"],"sourcesContent":["{\n \"EXT_PWA_NAME\": \"PWA\",\n \"EXT_PWA_DESC\": \"Service-Worker-Update-Anzeige in der Haupt-Symbolleiste und Installationshinweis in der mittleren 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
|
|
3
|
+
var EXT_PWA_DESC = "Service worker update indicator on the main toolbar and install prompt in the 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-CPtNgwwB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.en-CPtNgwwB.js","names":[],"sources":["../src/i18n.en.json"],"sourcesContent":["{\n \"EXT_PWA_NAME\": \"PWA\",\n \"EXT_PWA_DESC\": \"Service worker update indicator on the main toolbar and install prompt in the center toolbar when the browser supports them.\"\n}\n"],"mappings":""}
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import "./install-prompt-capture-
|
|
1
|
+
import "./install-prompt-capture-CRH1BlxV.js";
|
|
2
2
|
import { extensionRegistry, i18n } from "@eclipse-docks/core";
|
|
3
3
|
import pkg from "../package.json";
|
|
4
4
|
//#region src/index.ts
|
|
5
|
-
var t = await i18n(/*
|
|
6
|
-
"./i18n.de.json": () => import("./i18n.de-
|
|
7
|
-
"./i18n.en.json": () => import("./i18n.en-
|
|
5
|
+
var t = await i18n(/* #__PURE__ */ Object.assign({
|
|
6
|
+
"./i18n.de.json": () => import("./i18n.de-BJRO1uvt.js"),
|
|
7
|
+
"./i18n.en.json": () => import("./i18n.en-CPtNgwwB.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-VQuZNJbI.js"),
|
|
14
14
|
icon: "download"
|
|
15
15
|
});
|
|
16
16
|
//#endregion
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import './install-prompt-capture';\nimport { extensionRegistry, i18n } from '@eclipse-docks/core';\nimport pkg from '../package.json';\n\nconst t = await i18n(import.meta.glob('./i18n*.json'), true);\n\nextensionRegistry.registerExtension({\n id: pkg.name,\n name: t.EXT_PWA_NAME,\n description: t.EXT_PWA_DESC,\n loader: () => import('./pwa-extension'),\n icon: 'download',\n});\n"],"mappings":";;;;AAIA,IAAM,IAAI,MAAM,KAAK,uBAAA,OAAA;CAAA,wBAAA,OAAA;CAAA,wBAAA,OAAA;CAAA,
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import './install-prompt-capture';\nimport { extensionRegistry, i18n } from '@eclipse-docks/core';\nimport pkg from '../package.json';\n\nconst t = await i18n(import.meta.glob('./i18n*.json'), true);\n\nextensionRegistry.registerExtension({\n id: pkg.name,\n name: t.EXT_PWA_NAME,\n description: t.EXT_PWA_DESC,\n loader: () => import('./pwa-extension'),\n icon: 'download',\n});\n"],"mappings":";;;;AAIA,IAAM,IAAI,MAAM,KAAK,uBAAA,OAAA;CAAA,wBAAA,OAAA;CAAA,wBAAA,OAAA;AAAA,CAAA,GAAkC,IAAI;AAE3D,kBAAkB,kBAAkB;CAClC,IAAI,IAAI;CACR,MAAM,EAAE;CACR,aAAa,EAAE;CACf,cAAc,OAAO;CACrB,MAAM;AACR,CAAC"}
|
package/dist/{install-prompt-capture-fZikSCg3.js.map → install-prompt-capture-CRH1BlxV.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install-prompt-capture-
|
|
1
|
+
{"version":3,"file":"install-prompt-capture-CRH1BlxV.js","names":[],"sources":["../src/install-prompt-capture.ts"],"sourcesContent":["/**\n * Chromium fires `beforeinstallprompt` at most once; listeners must be registered early.\n * This module runs from `index.ts` when the package is first imported—before the lazy\n * extension loader and before `extensionRegistry.registerExtension` order matters.\n * App authors should static-import `@eclipse-docks/extension-pwa` ahead of heavy\n * extension entries (or in `main.ts` first) so this runs before top-level `await`\n * chains in other extensions delay evaluation.\n */\nexport interface PwaInstallPromptEvent extends Event {\n prompt(): Promise<void>;\n readonly userChoice: Promise<{ outcome: 'accepted' | 'dismissed' }>;\n}\n\nexport const PWA_INSTALL_PROMPT_AVAILABLE = 'docks-pwa-install-prompt-available';\n\nlet captured: PwaInstallPromptEvent | null = null;\n\nexport function peekInstallPrompt(): PwaInstallPromptEvent | null {\n return captured;\n}\n\nexport function clearInstallPromptCapture(): void {\n captured = null;\n}\n\nfunction isStandaloneShell(): boolean {\n if (typeof window === 'undefined') {\n return true;\n }\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\nfunction init(): void {\n if (typeof window === 'undefined' || isStandaloneShell()) {\n return;\n }\n window.addEventListener(\n 'beforeinstallprompt',\n (e) => {\n e.preventDefault();\n captured = e as PwaInstallPromptEvent;\n window.dispatchEvent(new CustomEvent(PWA_INSTALL_PROMPT_AVAILABLE));\n },\n { passive: false },\n );\n}\n\ninit();\n"],"mappings":";AAaA,IAAa,+BAA+B;AAE5C,IAAI,WAAyC;AAE7C,SAAgB,oBAAkD;CAChE,OAAO;AACT;AAEA,SAAgB,4BAAkC;CAChD,WAAW;AACb;AAEA,SAAS,oBAA6B;CACpC,IAAI,OAAO,WAAW,aACpB,OAAO;CAET,OACE,OAAO,WAAW,4BAA4B,CAAC,CAAC,WAChD,OAAO,WAAW,yCAAyC,CAAC,CAAC,WAC5D,OAAO,UAAmD,eAAe;AAE9E;AAEA,SAAS,OAAa;CACpB,IAAI,OAAO,WAAW,eAAe,kBAAkB,GACrD;CAEF,OAAO,iBACL,wBACC,MAAM;EACL,EAAE,eAAe;EACjB,WAAW;EACX,OAAO,cAAc,IAAI,YAAY,4BAA4B,CAAC;CACpE,GACA,EAAE,SAAS,MAAM,CACnB;AACF;AAEA,KAAK"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as clearInstallPromptCapture, r as peekInstallPrompt, t as PWA_INSTALL_PROMPT_AVAILABLE } from "./install-prompt-capture-
|
|
2
|
-
import { DocksElement, TOOLBAR_MAIN_CENTER, contributionRegistry } from "@eclipse-docks/core";
|
|
1
|
+
import { n as clearInstallPromptCapture, r as peekInstallPrompt, t as PWA_INSTALL_PROMPT_AVAILABLE } from "./install-prompt-capture-CRH1BlxV.js";
|
|
2
|
+
import { DocksElement, TOOLBAR_MAIN, TOOLBAR_MAIN_CENTER, 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";
|
|
@@ -140,7 +140,7 @@ var DocksSwUpdateIndicator = class DocksSwUpdateIndicator extends DocksElement {
|
|
|
140
140
|
registration.update().catch(() => {});
|
|
141
141
|
this.periodicInterval = window.setInterval(() => {
|
|
142
142
|
registration.update().catch(() => {});
|
|
143
|
-
},
|
|
143
|
+
}, 36e5);
|
|
144
144
|
queueMicrotask(() => {
|
|
145
145
|
if (this.registration !== registration) return;
|
|
146
146
|
this.syncUpdateState(registration);
|
|
@@ -178,27 +178,14 @@ var DocksSwUpdateIndicator = class DocksSwUpdateIndicator extends DocksElement {
|
|
|
178
178
|
}
|
|
179
179
|
if (!this.updateAvailable) return html``;
|
|
180
180
|
return html`
|
|
181
|
-
<wa-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
iterations="Infinity"
|
|
187
|
-
?play=${true}
|
|
181
|
+
<wa-button
|
|
182
|
+
variant="brand"
|
|
183
|
+
title="A new version is available. Click to update."
|
|
184
|
+
aria-label="Update available. Click to reload with the latest version."
|
|
185
|
+
@click=${this.onActivateClick}
|
|
188
186
|
>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
title="A new version is available. Click to reload."
|
|
192
|
-
aria-label="A new version is available. Reload to update."
|
|
193
|
-
@click=${this.onActivateClick}
|
|
194
|
-
>
|
|
195
|
-
<wa-icon
|
|
196
|
-
name="arrows-rotate"
|
|
197
|
-
label=""
|
|
198
|
-
style="color: var(--wa-color-success-fill-loud)"
|
|
199
|
-
></wa-icon>
|
|
200
|
-
</wa-button>
|
|
201
|
-
</wa-animation>
|
|
187
|
+
Update Available
|
|
188
|
+
</wa-button>
|
|
202
189
|
`;
|
|
203
190
|
}
|
|
204
191
|
};
|
|
@@ -273,9 +260,10 @@ DocksPwaInstall = _decorate([customElement("docks-pwa-install")], DocksPwaInstal
|
|
|
273
260
|
//#region src/pwa-extension.ts
|
|
274
261
|
var TOOLBAR_SW_UPDATE = "toolbar.swUpdate";
|
|
275
262
|
var TOOLBAR_PWA_INSTALL = "toolbar.pwaInstall";
|
|
276
|
-
contributionRegistry.registerContribution(
|
|
263
|
+
contributionRegistry.registerContribution(TOOLBAR_MAIN, {
|
|
277
264
|
name: TOOLBAR_SW_UPDATE,
|
|
278
265
|
label: "App update",
|
|
266
|
+
slot: "end",
|
|
279
267
|
component: `<docks-sw-update-indicator></docks-sw-update-indicator>`
|
|
280
268
|
});
|
|
281
269
|
contributionRegistry.registerContribution(TOOLBAR_MAIN_CENTER, {
|
|
@@ -285,4 +273,4 @@ contributionRegistry.registerContribution(TOOLBAR_MAIN_CENTER, {
|
|
|
285
273
|
});
|
|
286
274
|
//#endregion
|
|
287
275
|
|
|
288
|
-
//# sourceMappingURL=pwa-extension-
|
|
276
|
+
//# sourceMappingURL=pwa-extension-VQuZNJbI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pwa-extension-VQuZNJbI.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\ntype SwUpdateProgressMessage = {\n type: 'SW_UPDATE_PROGRESS';\n completed: number;\n total: number;\n done?: boolean;\n currentFile?: string;\n};\n\n/**\n * Shows a toolbar button when a new service worker is waiting (vite-plugin-pwa injectManifest + SKIP_WAITING message).\n * Displays download progress while the worker installs; then a brand \"Update Available\" button to activate it.\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 @state()\n private updateProgress = 0;\n @state()\n private updateProgressVisible = false;\n @state()\n private updateCurrentFile = '';\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 private readonly onServiceWorkerMessage = (event: MessageEvent): void => {\n const data = event.data as SwUpdateProgressMessage | undefined;\n if (!data || data.type !== 'SW_UPDATE_PROGRESS') {\n return;\n }\n if (data.total <= 0) {\n return;\n }\n const ratio = Math.max(0, Math.min(1, data.completed / data.total));\n this.updateProgress = ratio;\n this.updateProgressVisible = !this.updateAvailable && !data.done && ratio < 1;\n this.updateCurrentFile = this.toDisplayFileName(data.currentFile);\n };\n\n private toDisplayFileName(pathname?: string): string {\n if (!pathname) {\n return '';\n }\n const normalized = pathname.split('?')[0].split('#')[0];\n const raw = normalized.split('/').filter(Boolean).at(-1) ?? normalized;\n if (!raw) {\n return '';\n }\n const decoded = decodeURIComponent(raw);\n if (decoded.length <= 32) {\n return decoded;\n }\n return `${decoded.slice(0, 29)}...`;\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n if (!('serviceWorker' in navigator)) {\n return;\n }\n navigator.serviceWorker.addEventListener('controllerchange', this.onControllerChange);\n navigator.serviceWorker.addEventListener('message', this.onServiceWorkerMessage);\n void this.findOrAttachRegistration();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n navigator.serviceWorker.removeEventListener('controllerchange', this.onControllerChange);\n navigator.serviceWorker.removeEventListener('message', this.onServiceWorkerMessage);\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 this.updateProgress = 0;\n this.updateProgressVisible = false;\n this.updateCurrentFile = '';\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 if (this.updateAvailable) {\n this.updateProgress = 1;\n this.updateProgressVisible = false;\n this.updateCurrentFile = '';\n }\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 if (navigator.serviceWorker.controller) {\n this.updateProgress = 0;\n this.updateProgressVisible = true;\n this.updateCurrentFile = '';\n }\n const signal = this.attachAbort?.signal;\n if (!signal) {\n return;\n }\n installing.addEventListener(\n 'statechange',\n () => {\n if (installing.state === 'redundant') {\n this.updateProgress = 0;\n this.updateProgressVisible = false;\n this.updateCurrentFile = '';\n return;\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.updateProgressVisible && !this.updateAvailable) {\n const percent = Math.round(this.updateProgress * 100);\n return html`\n <div\n style=\"display: inline-flex; align-items: center; gap: 0.5rem; min-width: 210px;\"\n title=\"Downloading the latest update...\"\n aria-label=\"Downloading the latest update\"\n >\n <wa-progress-bar value=${percent}></wa-progress-bar>\n <div style=\"display: inline-flex; flex-direction: column; gap: 0.1rem; max-width: 140px;\">\n <span style=\"font-size: 0.75rem; opacity: 0.8;\">${percent}%</span>\n ${this.updateCurrentFile\n ? html`<span\n style=\"font-size: 0.7rem; opacity: 0.7; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\"\n title=${this.updateCurrentFile}\n >${this.updateCurrentFile}</span\n >`\n : html``}\n </div>\n </div>\n `;\n }\n\n if (!this.updateAvailable) {\n return html``;\n }\n\n return html`\n <wa-button\n variant=\"brand\"\n title=\"A new version is available. Click to update.\"\n aria-label=\"Update available. Click to reload with the latest version.\"\n @click=${this.onActivateClick}\n >\n Update Available\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, TOOLBAR_MAIN, TOOLBAR_MAIN_CENTER } 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_MAIN, {\n name: TOOLBAR_SW_UPDATE,\n label: 'App update',\n slot: 'end',\n component: `<docks-sw-update-indicator></docks-sw-update-indicator>`,\n} as HTMLContribution);\n\ncontributionRegistry.registerContribution(TOOLBAR_MAIN_CENTER, {\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,6 +1,7 @@
|
|
|
1
1
|
import { DocksElement } from '@eclipse-docks/core';
|
|
2
2
|
/**
|
|
3
|
-
* Shows a toolbar
|
|
3
|
+
* Shows a toolbar button when a new service worker is waiting (vite-plugin-pwa injectManifest + SKIP_WAITING message).
|
|
4
|
+
* Displays download progress while the worker installs; then a brand "Update Available" button to activate it.
|
|
4
5
|
* Hidden when there is no update or when service workers are unavailable.
|
|
5
6
|
*
|
|
6
7
|
* Safe when the extension loads late: attaches via `getRegistration()`, reads `registration.waiting`,
|
|
@@ -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;AAUnD
|
|
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;AAUnD;;;;;;;GAOG;AACH,qBACa,sBAAuB,SAAQ,YAAY;IAEtD,OAAO,CAAC,eAAe,CAAS;IAEhC,OAAO,CAAC,cAAc,CAAK;IAE3B,OAAO,CAAC,qBAAqB,CAAS;IAEtC,OAAO,CAAC,iBAAiB,CAAM;IAE/B,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,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAYrC;IAEF,OAAO,CAAC,iBAAiB;IAgBzB,iBAAiB,IAAI,IAAI;IAUzB,oBAAoB,IAAI,IAAI;YAOd,wBAAwB;IAqBtC,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,kBAAkB;IAe1B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAyC5B;IAEF,OAAO,CAAC,MAAM;IA0Bd,OAAO,CAAC,eAAe;IAUvB,SAAS,CAAC,MAAM;CAuCjB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,2BAA2B,EAAE,sBAAsB,CAAC;KACrD;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite-pwa-plugin.js","names":[],"sources":["../src/vite-pwa-plugin.ts"],"sourcesContent":["import { fileURLToPath } from 'url';\nimport path from 'path';\nimport type { PluginOption, UserConfig } from 'vite';\nimport type { RolldownOptions } from 'rolldown';\nimport { VitePWA } from 'vite-plugin-pwa';\nimport type { CustomInjectManifestOptions } from 'vite-plugin-pwa';\n\n/** vite-plugin-pwa still names this `rollup`; Vite 8’s SW build uses Rolldown. */\ntype VitePwaInjectManifestRollupPlugins = NonNullable<\n NonNullable<CustomInjectManifestOptions['buildPlugins']>['rollup']\n>;\n\n/**\n * JSON-serializable options for the SPA `NavigationRoute` (Workbox). Extra keys are kept for\n * forward-compatible SW parsing.\n */\nexport type DocksPwaNavigationRouteConfig = {\n /**\n * RegExp **sources** for Workbox `denylist` (matched against pathname + search).\n * Pass `[]` so no paths are denied (SPA shell for all navigations within allowlist).\n */\n denylist?: string[];\n /**\n * RegExp **sources** for Workbox `allowlist`. Omit to use Workbox’s default (`[/. /]`).\n * Set when the SPA shell should only apply to a subset of navigations.\n */\n allowlist?: string[];\n} & Record<string, unknown>;\n\n/**\n * JSON-serializable bundle injected into the service worker (`define`). Add sections here as\n * the SW gains more build-time tunables; unknown top-level keys are preserved in JSON for\n * forward-compatible workers.\n */\nexport type DocksPwaServiceWorkerConfig = {\n /** SPA shell fallback: Workbox `NavigationRoute` for `index.html`. */\n navigationRoute?: DocksPwaNavigationRouteConfig;\n} & Record<string, unknown>;\n\nfunction stripUndefinedEntries<T extends Record<string, unknown>>(obj: T): Record<string, unknown> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined));\n}\n\nfunction resolveServiceWorkerConfig(user?: DocksPwaServiceWorkerConfig): DocksPwaServiceWorkerConfig {\n const u = stripUndefinedEntries((user ?? {}) as Record<string, unknown>);\n const navRaw = u.navigationRoute;\n const rest = Object.fromEntries(Object.entries(u).filter(([k]) => k !== 'navigationRoute'));\n\n if (navRaw === undefined) {\n return rest as DocksPwaServiceWorkerConfig;\n }\n if (typeof navRaw !== 'object' || navRaw === null || Array.isArray(navRaw)) {\n throw new Error('createDocksPwaPlugin.serviceWorkerConfig.navigationRoute must be a plain object');\n }\n\n const navigationRoute = stripUndefinedEntries(navRaw as Record<string, unknown>) as DocksPwaNavigationRouteConfig;\n\n return {\n ...rest,\n navigationRoute,\n } as DocksPwaServiceWorkerConfig;\n}\n\nexport type CreateDocksPwaPluginOptions = {\n basePath: string;\n appName: string;\n appDescription: string;\n maximumFileSizeToCacheInBytes: number;\n shortName?: string;\n /**\n * Serializable object injected into the SW build. No implicit defaults: set `navigationRoute`\n * (e.g. `denylist`) only when your deployment needs it.\n */\n serviceWorkerConfig?: DocksPwaServiceWorkerConfig;\n /** Extra Vite / Rolldown plugins for the injectManifest service worker build only. */\n injectManifestBuildPlugins?: {\n vite?: UserConfig['plugins'];\n /** Rolldown plugins (Vite 8+). Passed through to vite-plugin-pwa as `buildPlugins.rollup`. */\n rolldown?: RolldownOptions['plugins'];\n };\n};\n\nconst DEFAULT_GLOB_PATTERNS = ['**/*.{js,css,html,ico,png,svg,webp,woff2,woff,ttf,wasm}'];\nconst DEFAULT_ASSETS = ['favicon.svg', 'logo.svg', 'logo-loading.svg'];\nconst pwaSwPath = fileURLToPath(import.meta.resolve('@eclipse-docks/extension-pwa/sw'));\nconst pwaSwDir = path.dirname(pwaSwPath);\nconst pwaSwFilename = path.basename(pwaSwPath);\n\nexport function createDocksPwaPlugin({\n basePath,\n appName,\n appDescription,\n maximumFileSizeToCacheInBytes,\n shortName = appName,\n serviceWorkerConfig,\n injectManifestBuildPlugins,\n}: CreateDocksPwaPluginOptions): PluginOption {\n const resolvedSwConfig = resolveServiceWorkerConfig(serviceWorkerConfig);\n\n return VitePWA({\n registerType: 'autoUpdate',\n injectRegister: 'inline',\n strategies: 'injectManifest',\n srcDir: pwaSwDir,\n filename: pwaSwFilename,\n manifest: {\n name: appName,\n short_name: shortName,\n description: appDescription,\n theme_color: '#1a1a1a',\n background_color: '#1a1a1a',\n display: 'standalone',\n start_url: basePath,\n scope: basePath,\n icons: [\n {\n src: 'logo.svg',\n sizes: 'any',\n type: 'image/svg+xml',\n purpose: 'any',\n },\n {\n src: 'favicon.svg',\n sizes: 'any',\n type: 'image/svg+xml',\n purpose: 'monochrome',\n },\n ],\n },\n includeAssets: DEFAULT_ASSETS,\n injectManifest: {\n maximumFileSizeToCacheInBytes,\n globPatterns: DEFAULT_GLOB_PATTERNS,\n buildPlugins: {\n vite: [\n {\n name: 'docks-pwa-sw-injected-config',\n config() {\n return {\n define: {\n __DOCKS_SW_INJECTED_CONFIG__: JSON.stringify(resolvedSwConfig),\n },\n };\n },\n },\n ...(injectManifestBuildPlugins?.vite ?? []),\n ],\n rollup: injectManifestBuildPlugins?.rolldown as VitePwaInjectManifestRollupPlugins,\n },\n },\n devOptions: {\n enabled: false,\n },\n });\n}\n"],"mappings":";;;;AAuCA,SAAS,sBAAyD,KAAiC;
|
|
1
|
+
{"version":3,"file":"vite-pwa-plugin.js","names":[],"sources":["../src/vite-pwa-plugin.ts"],"sourcesContent":["import { fileURLToPath } from 'url';\nimport path from 'path';\nimport type { PluginOption, UserConfig } from 'vite';\nimport type { RolldownOptions } from 'rolldown';\nimport { VitePWA } from 'vite-plugin-pwa';\nimport type { CustomInjectManifestOptions } from 'vite-plugin-pwa';\n\n/** vite-plugin-pwa still names this `rollup`; Vite 8’s SW build uses Rolldown. */\ntype VitePwaInjectManifestRollupPlugins = NonNullable<\n NonNullable<CustomInjectManifestOptions['buildPlugins']>['rollup']\n>;\n\n/**\n * JSON-serializable options for the SPA `NavigationRoute` (Workbox). Extra keys are kept for\n * forward-compatible SW parsing.\n */\nexport type DocksPwaNavigationRouteConfig = {\n /**\n * RegExp **sources** for Workbox `denylist` (matched against pathname + search).\n * Pass `[]` so no paths are denied (SPA shell for all navigations within allowlist).\n */\n denylist?: string[];\n /**\n * RegExp **sources** for Workbox `allowlist`. Omit to use Workbox’s default (`[/. /]`).\n * Set when the SPA shell should only apply to a subset of navigations.\n */\n allowlist?: string[];\n} & Record<string, unknown>;\n\n/**\n * JSON-serializable bundle injected into the service worker (`define`). Add sections here as\n * the SW gains more build-time tunables; unknown top-level keys are preserved in JSON for\n * forward-compatible workers.\n */\nexport type DocksPwaServiceWorkerConfig = {\n /** SPA shell fallback: Workbox `NavigationRoute` for `index.html`. */\n navigationRoute?: DocksPwaNavigationRouteConfig;\n} & Record<string, unknown>;\n\nfunction stripUndefinedEntries<T extends Record<string, unknown>>(obj: T): Record<string, unknown> {\n return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined));\n}\n\nfunction resolveServiceWorkerConfig(user?: DocksPwaServiceWorkerConfig): DocksPwaServiceWorkerConfig {\n const u = stripUndefinedEntries((user ?? {}) as Record<string, unknown>);\n const navRaw = u.navigationRoute;\n const rest = Object.fromEntries(Object.entries(u).filter(([k]) => k !== 'navigationRoute'));\n\n if (navRaw === undefined) {\n return rest as DocksPwaServiceWorkerConfig;\n }\n if (typeof navRaw !== 'object' || navRaw === null || Array.isArray(navRaw)) {\n throw new Error('createDocksPwaPlugin.serviceWorkerConfig.navigationRoute must be a plain object');\n }\n\n const navigationRoute = stripUndefinedEntries(navRaw as Record<string, unknown>) as DocksPwaNavigationRouteConfig;\n\n return {\n ...rest,\n navigationRoute,\n } as DocksPwaServiceWorkerConfig;\n}\n\nexport type CreateDocksPwaPluginOptions = {\n basePath: string;\n appName: string;\n appDescription: string;\n maximumFileSizeToCacheInBytes: number;\n shortName?: string;\n /**\n * Serializable object injected into the SW build. No implicit defaults: set `navigationRoute`\n * (e.g. `denylist`) only when your deployment needs it.\n */\n serviceWorkerConfig?: DocksPwaServiceWorkerConfig;\n /** Extra Vite / Rolldown plugins for the injectManifest service worker build only. */\n injectManifestBuildPlugins?: {\n vite?: UserConfig['plugins'];\n /** Rolldown plugins (Vite 8+). Passed through to vite-plugin-pwa as `buildPlugins.rollup`. */\n rolldown?: RolldownOptions['plugins'];\n };\n};\n\nconst DEFAULT_GLOB_PATTERNS = ['**/*.{js,css,html,ico,png,svg,webp,woff2,woff,ttf,wasm}'];\nconst DEFAULT_ASSETS = ['favicon.svg', 'logo.svg', 'logo-loading.svg'];\nconst pwaSwPath = fileURLToPath(import.meta.resolve('@eclipse-docks/extension-pwa/sw'));\nconst pwaSwDir = path.dirname(pwaSwPath);\nconst pwaSwFilename = path.basename(pwaSwPath);\n\nexport function createDocksPwaPlugin({\n basePath,\n appName,\n appDescription,\n maximumFileSizeToCacheInBytes,\n shortName = appName,\n serviceWorkerConfig,\n injectManifestBuildPlugins,\n}: CreateDocksPwaPluginOptions): PluginOption {\n const resolvedSwConfig = resolveServiceWorkerConfig(serviceWorkerConfig);\n\n return VitePWA({\n registerType: 'autoUpdate',\n injectRegister: 'inline',\n strategies: 'injectManifest',\n srcDir: pwaSwDir,\n filename: pwaSwFilename,\n manifest: {\n name: appName,\n short_name: shortName,\n description: appDescription,\n theme_color: '#1a1a1a',\n background_color: '#1a1a1a',\n display: 'standalone',\n start_url: basePath,\n scope: basePath,\n icons: [\n {\n src: 'logo.svg',\n sizes: 'any',\n type: 'image/svg+xml',\n purpose: 'any',\n },\n {\n src: 'favicon.svg',\n sizes: 'any',\n type: 'image/svg+xml',\n purpose: 'monochrome',\n },\n ],\n },\n includeAssets: DEFAULT_ASSETS,\n injectManifest: {\n maximumFileSizeToCacheInBytes,\n globPatterns: DEFAULT_GLOB_PATTERNS,\n buildPlugins: {\n vite: [\n {\n name: 'docks-pwa-sw-injected-config',\n config() {\n return {\n define: {\n __DOCKS_SW_INJECTED_CONFIG__: JSON.stringify(resolvedSwConfig),\n },\n };\n },\n },\n ...(injectManifestBuildPlugins?.vite ?? []),\n ],\n rollup: injectManifestBuildPlugins?.rolldown as VitePwaInjectManifestRollupPlugins,\n },\n },\n devOptions: {\n enabled: false,\n },\n });\n}\n"],"mappings":";;;;AAuCA,SAAS,sBAAyD,KAAiC;CACjG,OAAO,OAAO,YAAY,OAAO,QAAQ,GAAG,CAAC,CAAC,QAAQ,GAAG,OAAO,MAAM,KAAA,CAAS,CAAC;AAClF;AAEA,SAAS,2BAA2B,MAAiE;CACnG,MAAM,IAAI,sBAAuB,QAAQ,CAAC,CAA6B;CACvE,MAAM,SAAS,EAAE;CACjB,MAAM,OAAO,OAAO,YAAY,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,MAAM,iBAAiB,CAAC;CAE1F,IAAI,WAAW,KAAA,GACb,OAAO;CAET,IAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GACvE,MAAM,IAAI,MAAM,iFAAiF;CAGnG,MAAM,kBAAkB,sBAAsB,MAAiC;CAE/E,OAAO;EACL,GAAG;EACH;CACF;AACF;AAqBA,IAAM,wBAAwB,CAAC,yDAAyD;AACxF,IAAM,iBAAiB;CAAC;CAAe;CAAY;AAAkB;AACrE,IAAM,YAAY,cAAc,YAAY,QAAQ,iCAAiC,CAAC;AACtF,IAAM,WAAW,KAAK,QAAQ,SAAS;AACvC,IAAM,gBAAgB,KAAK,SAAS,SAAS;AAE7C,SAAgB,qBAAqB,EACnC,UACA,SACA,gBACA,+BACA,YAAY,SACZ,qBACA,8BAC4C;CAC5C,MAAM,mBAAmB,2BAA2B,mBAAmB;CAEvE,OAAO,QAAQ;EACb,cAAc;EACd,gBAAgB;EAChB,YAAY;EACZ,QAAQ;EACR,UAAU;EACV,UAAU;GACR,MAAM;GACN,YAAY;GACZ,aAAa;GACb,aAAa;GACb,kBAAkB;GAClB,SAAS;GACT,WAAW;GACX,OAAO;GACP,OAAO,CACL;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,SAAS;GACX,GACA;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,SAAS;GACX,CACF;EACF;EACA,eAAe;EACf,gBAAgB;GACd;GACA,cAAc;GACd,cAAc;IACZ,MAAM,CACJ;KACE,MAAM;KACN,SAAS;MACP,OAAO,EACL,QAAQ,EACN,8BAA8B,KAAK,UAAU,gBAAgB,EAC/D,EACF;KACF;IACF,GACA,GAAI,4BAA4B,QAAQ,CAAC,CAC3C;IACA,QAAQ,4BAA4B;GACtC;EACF;EACA,YAAY,EACV,SAAS,MACX;CACF,CAAC;AACH"}
|
package/package.json
CHANGED
package/dist/i18n.de-CorheGJa.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
//#region src/i18n.de.json
|
|
2
|
-
var EXT_PWA_NAME = "PWA";
|
|
3
|
-
var EXT_PWA_DESC = "Service-Worker-Update und Installationshinweis in der mittleren Haupt-Symbolleiste, wenn der Browser das unterstützt.";
|
|
4
|
-
var i18n_de_default = {
|
|
5
|
-
EXT_PWA_NAME: "PWA",
|
|
6
|
-
EXT_PWA_DESC
|
|
7
|
-
};
|
|
8
|
-
//#endregion
|
|
9
|
-
export { EXT_PWA_DESC, EXT_PWA_NAME, i18n_de_default as default };
|
|
10
|
-
|
|
11
|
-
//# sourceMappingURL=i18n.de-CorheGJa.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pwa-extension-BaUCo7Mu.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\ntype SwUpdateProgressMessage = {\n type: 'SW_UPDATE_PROGRESS';\n completed: number;\n total: number;\n done?: boolean;\n currentFile?: string;\n};\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 @state()\n private updateProgress = 0;\n @state()\n private updateProgressVisible = false;\n @state()\n private updateCurrentFile = '';\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 private readonly onServiceWorkerMessage = (event: MessageEvent): void => {\n const data = event.data as SwUpdateProgressMessage | undefined;\n if (!data || data.type !== 'SW_UPDATE_PROGRESS') {\n return;\n }\n if (data.total <= 0) {\n return;\n }\n const ratio = Math.max(0, Math.min(1, data.completed / data.total));\n this.updateProgress = ratio;\n this.updateProgressVisible = !this.updateAvailable && !data.done && ratio < 1;\n this.updateCurrentFile = this.toDisplayFileName(data.currentFile);\n };\n\n private toDisplayFileName(pathname?: string): string {\n if (!pathname) {\n return '';\n }\n const normalized = pathname.split('?')[0].split('#')[0];\n const raw = normalized.split('/').filter(Boolean).at(-1) ?? normalized;\n if (!raw) {\n return '';\n }\n const decoded = decodeURIComponent(raw);\n if (decoded.length <= 32) {\n return decoded;\n }\n return `${decoded.slice(0, 29)}...`;\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n if (!('serviceWorker' in navigator)) {\n return;\n }\n navigator.serviceWorker.addEventListener('controllerchange', this.onControllerChange);\n navigator.serviceWorker.addEventListener('message', this.onServiceWorkerMessage);\n void this.findOrAttachRegistration();\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n navigator.serviceWorker.removeEventListener('controllerchange', this.onControllerChange);\n navigator.serviceWorker.removeEventListener('message', this.onServiceWorkerMessage);\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 this.updateProgress = 0;\n this.updateProgressVisible = false;\n this.updateCurrentFile = '';\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 if (this.updateAvailable) {\n this.updateProgress = 1;\n this.updateProgressVisible = false;\n this.updateCurrentFile = '';\n }\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 if (navigator.serviceWorker.controller) {\n this.updateProgress = 0;\n this.updateProgressVisible = true;\n this.updateCurrentFile = '';\n }\n const signal = this.attachAbort?.signal;\n if (!signal) {\n return;\n }\n installing.addEventListener(\n 'statechange',\n () => {\n if (installing.state === 'redundant') {\n this.updateProgress = 0;\n this.updateProgressVisible = false;\n this.updateCurrentFile = '';\n return;\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.updateProgressVisible && !this.updateAvailable) {\n const percent = Math.round(this.updateProgress * 100);\n return html`\n <div\n style=\"display: inline-flex; align-items: center; gap: 0.5rem; min-width: 210px;\"\n title=\"Downloading the latest update...\"\n aria-label=\"Downloading the latest update\"\n >\n <wa-progress-bar value=${percent}></wa-progress-bar>\n <div style=\"display: inline-flex; flex-direction: column; gap: 0.1rem; max-width: 140px;\">\n <span style=\"font-size: 0.75rem; opacity: 0.8;\">${percent}%</span>\n ${this.updateCurrentFile\n ? html`<span\n style=\"font-size: 0.7rem; opacity: 0.7; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\"\n title=${this.updateCurrentFile}\n >${this.updateCurrentFile}</span\n >`\n : html``}\n </div>\n </div>\n `;\n }\n\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-success-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_MAIN_CENTER } 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_MAIN_CENTER, {\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_MAIN_CENTER, {\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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"}
|