From b95371a123507845a2f28b81898bd14e8d3163a2 Mon Sep 17 00:00:00 2001 From: SkateSpots Date: Fri, 30 Oct 2026 00:56:19 +0700 Subject: [PATCH] fix: break native boot reload loops before they trap the app --- public/boot-guard.js | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/public/boot-guard.js b/public/boot-guard.js index 7335175..6a4e04d 100644 --- a/public/boot-guard.js +++ b/public/boot-guard.js @@ -9,6 +9,51 @@ (function () { var shown = false; + // Reload-loop breaker. A stale app-shell worker can reload before the boot + // guard's 12s error panel is ever shown. After three loads inside one minute, + // clear the shell cache/worker once and reload into a clean shell. + try { + var ATTEMPT_KEY = 'skatespots:boot-attempts'; + var now = Date.now(); + var attempts = { count: 0, at: now }; + try { + var stored = JSON.parse(sessionStorage.getItem(ATTEMPT_KEY) || 'null'); + if (stored && typeof stored.at === 'number' && now - stored.at < 60000) { + attempts.count = Number(stored.count) || 0; + } + } catch (e) {} + attempts.count += 1; + attempts.at = now; + try { sessionStorage.setItem(ATTEMPT_KEY, JSON.stringify(attempts)); } catch (e) {} + if (attempts.count >= 3) { + try { sessionStorage.removeItem(ATTEMPT_KEY); } catch (e) {} + var finished = false; + var finish = function () { + if (finished) return; + finished = true; + location.reload(); + }; + var jobs = []; + try { + if ('serviceWorker' in navigator) { + jobs.push(navigator.serviceWorker.getRegistrations().then(function (regs) { + regs.forEach(function (reg) { try { reg.unregister(); } catch (e) {} }); + }).catch(function () {})); + } + if (window.caches) { + jobs.push(window.caches.keys().then(function (keys) { + return Promise.all(keys.filter(function (key) { return key.indexOf('skate-spots-shell-') === 0; }) + .map(function (key) { return window.caches.delete(key).catch(function () {}); })); + }).catch(function () {})); + } + } catch (e) {} + if (jobs.length) Promise.all(jobs).then(finish).catch(finish); + else finish(); + setTimeout(finish, 1000); + return; + } + } catch (e) { /* best effort */ } + // Native WebViews can keep a service worker from an older build forever. // That worker can serve a stale index.html whose hashed chunks no longer // exist, producing a white/black reload loop. The native shell is served from