1// AUTO-GENERATED â DO NOT EDIT 2// Source: shared/version-poll.js 3// Regenerated by scripts/sync-workshop-modules.mjs (apps/home Hosting target â workshop reception console). 4// Hand-edits to this file will be overwritten on the next deploy. 5 6/* ââ SHIROFES OS â Standalone version-polling + hard-refresh helper âââââââââ 7 * 8 * v135.105 â extracted from shared/state.js so pages that don't load state.js 9 * (the "exception pages" â post-event, mc, mc-script, cast, crew, portal, 10 * register, register-cast, reflect, debrief, timetable, rundown, index) get 11 * stale-tab detection consistent with admin/staff/kiosk/etc. 12 * 13 * Pre-v135.105 only `state.js`-loading pages + dj.html + live.html (rolled 14 * their own inline pollers) had the toast. mc-script.html during a live 15 * SHIROFES set could sit on stale code if the operator left a tab open 16 * across a hotfix deploy. This module closes that gap without forcing 17 * `state.js` onto pages that intentionally don't carry it (cf. EXECUTION_ 18 * STATE.md "Exception-page architecture variance is intentional"). 19 * 20 * Contract: 21 * - Idempotent: `window.__versionPollActive` guards re-entry. State.js's 22 * `setupVersionPolling` (still present for back-compat) checks the same 23 * flag and no-ops when this module has already booted. 24 * - Self-bootstraps: first poll seeds the local-version baseline from 25 * `window.SHIROFES_APP_VERSION` if present (set by firebase-config.js 26 * on script-tag-loaded pages), else from the first version.json read 27 * itself. Subsequent polls compare against the seeded baseline. 28 * This makes the module work uniformly on script-tag pages (admin/ 29 * staff/etc.) AND on ES-module pages (mc.html) that don't load 30 * firebase-config.js synchronously. 31 * - Polls `version.json` 30s after load, then every 5min. 32 * - Banner is identical to state.js's (same id `versionUpdateBanner`, same 33 * hard-refresh CTA) so operators see one consistent UI across all pages. 34 * 35 * Hard-refresh exposed at `window.__shirofesHardRefresh` â pages that already 36 * defined it (state.js) keep theirs; this module's definition only attaches 37 * if absent. 38 * ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ */ 39 40(function () { 41 'use strict'; 42 43 if (typeof window === 'undefined') return; 44 45 // Idempotent guard â if state.js or another instance already booted the 46 // poller, don't double-schedule. Both share the same banner element id 47 // so visual state stays consistent. 48 if (window.__versionPollActive) return; 49 window.__versionPollActive = true; 50 51 var POLL_INTERVAL = 5 * 60 * 1000; // 5 minutes 52 var FIRST_CHECK_DELAY = 30 * 1000; // 30 seconds (let page settle) 53 var _versionToastShown = false; 54 var _baselineVersion = (window.SHIROFES_APP_VERSION || '').toString() || null; 55 56 function checkVersion() { 57 if (_versionToastShown) return; // already prompted, don't spam 58 // Cache-busting query param so the SW's cache-first handler doesn't 59 // serve a stale version.json. cache:'no-store' on the fetch is a 60 // belt-and-suspenders second layer. 61 // v136.23 â the URL is configurable for the isolated apps/home Hosting 62 // target, whose pages live under /workshops/ or /club/ so a relative 63 // './version.json' would miss the one home-root version.json. Those
64 // pages set window.SHIROFES_VERSION_URL = '/version.json'. Root pages 65 // leave it unset â './version.json' as before (backward-compatible). 66 var _versionUrl = (window.SHIROFES_VERSION_URL || './version.json'); 67 fetch(_versionUrl + '?_t=' + Date.now(), { cache: 'no-store' }) 68 .then(function (r) { return r.ok ? r.json() : null; }) 69 .then(function (data) { 70 if (!data || !data.v) return; 71 var fetched = String(data.v); 72 if (!_baselineVersion) { 73 // First poll on a page that didn't pre-set the baseline 74 // (ES-module pages without firebase-config.js script tag). 75 // Seed and exit â drift gets detected on the NEXT poll. 76 _baselineVersion = fetched; 77 return; 78 } 79 if (fetched !== _baselineVersion && !_versionToastShown) { 80 _versionToastShown = true; 81 showVersionUpdateBanner(); 82 } 83 }) 84 .catch(function () { /* offline or fetch fail â try again next tick */ }); 85 } 86 87 // Hard-refresh: unregister SW + purge Cache Storage before reload so the 88 // user actually gets the new code. Plain location.reload() goes through 89 // the SW's cache-first handler and can serve stale HTML/JS indefinitely. 90 if (typeof window.__shirofesHardRefresh !== 'function') { 91 window.__shirofesHardRefresh = async function hardRefresh() { 92 try { 93 if ('serviceWorker' in navigator) { 94 var regs = await navigator.serviceWorker.getRegistrations(); 95 await Promise.all(regs.map(function (r) { return r.unregister(); })); 96 } 97 if (typeof caches !== 'undefined' && caches && caches.keys) { 98 var keys = await caches.keys(); 99 await Promise.all(keys.map(function (k) { return caches.delete(k); })); 100 } 101 } catch (e) { /* best effort â reload anyway */ } 102 // Cache-busting query param forces even Chrome's HTTP disk cache to fetch fresh. 103 var u = new URL(location.href); 104 u.searchParams.set('_rv', Date.now()); 105 location.replace(u.toString()); 106 }; 107 } 108 109 function showVersionUpdateBanner() { 110 // Don't double-render if state.js already did. 111 if (document.getElementById('versionUpdateBanner')) return; 112 var banner = document.createElement('div'); 113 banner.id = 'versionUpdateBanner'; 114 banner.style.cssText = 'position:fixed;top:0;left:0;right:0;z-index:9999;background:var(--info,#2563eb);color:#fff;text-align:center;padding:0.6rem 1rem;font-size:0.85rem;font-weight:600;display:flex;align-items:center;justify-content:center;gap:0.75rem;box-shadow:0 2px 8px rgba(0,0,0,0.3);'; 115 banner.innerHTML = '<span>æ°ãããã¼ã¸ã§ã³ãããã¾ã / New version available</span>' + 116 '<button onclick="window.__shirofesHardRefresh()" style="background:#fff;color:var(--info,#2563eb);border:none;border-radius:6px;padding:0.3rem 0.8rem;font-weight:700;font-size:0.8rem;cursor:pointer;min-height:32px;">æ´æ° / Refresh</button>' + 117 '<button onclick="this.parentElement.remove()" style="background:transparent;color:#fff;border:1px solid rgba(255,255,255,0.4);border-radius:6px;padding:0.3rem 0.6rem;font-size:0.75rem;cursor:pointer;min-height:32px;">å¾ã§ / Later</button>'; 118 if (document.body) document.body.prepend(banner); 119 else document.addEventListener('DOMContentLoaded', function () { document.body.prepend(banner); }); 120 } 121 122 // First check after 30s (let page settle), then every 5 minutes. 123 setTimeout(checkVersion, FIRST_CHECK_DELAY); 124 setInterval(checkVersion, POLL_INTERVAL); 125 126 // Expose for pages that want to force a check on visibility-change etc. 127 window.__shirofesCheckVersion = checkVersion; 128})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.