diff --git a/frontend/app.js b/frontend/app.js index 8b67fb8..27ac065 100755 --- a/frontend/app.js +++ b/frontend/app.js @@ -2992,17 +2992,34 @@ function showUpdateBanner() { { label: 'Later', onClick: closeModal }, { label: 'Refresh UI', primary: true, onClick: async () => { closeModal(); - await hardReloadUI(); + await applyUpdate(); }}, ]); } +// Tracks the current SW registration so applyUpdate() can reach the +// waiting worker without re-querying getRegistration(). +let _swReg = null; + +// Applies a pending SW update in place (see sw-update.js for the full +// rationale — this used to call hardReloadUI(), which caused the "Update +// ready" banner to reappear right after being applied). +async function applyUpdate() { + const reg = _swReg || (('serviceWorker' in navigator) ? await navigator.serviceWorker.getRegistration() : null); + await window.SwUpdate.applyUpdate({ + reg, + container: navigator.serviceWorker, + reload: () => window.location.reload(), + }); +} + async function registerServiceWorker() { if (!WEB || !('serviceWorker' in navigator)) return; try { // updateViaCache:'none' prevents the browser from serving a stale // cached copy of sw.js — the server always returns it fresh (no-store). const reg = await navigator.serviceWorker.register('/sw.js', { updateViaCache: 'none' }); + _swReg = reg; // If a new SW is already waiting (e.g. user refreshed after an update), // show the dialog right away. diff --git a/frontend/index.html b/frontend/index.html index cfae38d..015cf2c 100755 --- a/frontend/index.html +++ b/frontend/index.html @@ -307,6 +307,7 @@ + diff --git a/frontend/sw-update.js b/frontend/sw-update.js new file mode 100644 index 0000000..b219bba --- /dev/null +++ b/frontend/sw-update.js @@ -0,0 +1,70 @@ +/* ============================================================================ + * sw-update — applies a waiting service-worker update in place. + * + * Framework-free and dependency-free on purpose (same pattern as + * async-guard.js): + * • Loads as a plain