|
1 | 1 | // cached-version.js — Discloses when AcreetionOS is being viewed from the |
2 | | -// service-worker cache (offline or fallback). Honest transparency: a fixed |
3 | | -// bottom-right bubble in site branding links to the live site. No bubble is |
4 | | -// shown when the page is served live from the network. |
| 2 | +// service-worker cache (offline or fallback). An honest little "i" info bubble |
| 3 | +// sits bottom-right; clicking it expands the cached-version notice with the |
| 4 | +// force-refresh shortcuts. No bubble is shown when the page is served live. |
5 | 5 | // Maintainers: AcreetionOS |
6 | 6 |
|
7 | 7 | (function () { |
8 | 8 | "use strict"; |
9 | 9 | if (!("serviceWorker" in navigator)) return; |
10 | 10 |
|
11 | | - var shown = false; |
| 11 | + var created = false; |
12 | 12 |
|
13 | 13 | function showBubble() { |
14 | | - if (shown) return; |
15 | | - shown = true; |
16 | | - |
17 | | - var b = document.createElement("div"); |
18 | | - b.style.cssText = |
19 | | - "all:initial;position:fixed;right:16px;bottom:16px;z-index:2147483647;" + |
20 | | - "font:13px/1.45,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;" + |
21 | | - "color:#e5e5e5;background:#1a1a1a;border:1px solid #2ecc71;border-left:4px solid #2ecc71;" + |
22 | | - "border-radius:10px;padding:12px 14px;max-width:300px;" + |
23 | | - "box-shadow:0 6px 18px rgba(0,0,0,0.55);"; |
24 | | - |
25 | | - b.innerHTML = |
26 | | - '<div style="font-weight:700;color:#2ecc71;margin-bottom:4px;">Cached version</div>' + |
27 | | - '<div style="color:#b2b2b2;">You are looking at a locally cached copy' + |
28 | | - ' of this page because the network version could not be loaded right now.' + |
29 | | - ' To force-load the live page, press <b style="color:#e5e5e5;">Ctrl + Shift + R</b>' + |
30 | | - ' (Windows/Linux) or <b style="color:#e5e5e5;">Cmd + Shift + R</b> (macOS).' + |
31 | | - ' <a href="' + location.pathname + '" style="color:#2ecc71;font-weight:600;text-decoration:none;">Reload live →</a></div>'; |
32 | | - |
33 | | - // Clicking anywhere except the link dismisses the notice. |
34 | | - b.addEventListener("click", function (e) { |
35 | | - if (e.target.tagName !== "A") b.style.display = "none"; |
| 14 | + if (created) return; |
| 15 | + created = true; |
| 16 | + |
| 17 | + var wrap = document.createElement("div"); |
| 18 | + // Outer "i" button — small circular info icon, site green-on-dark. |
| 19 | + wrap.innerHTML = |
| 20 | + '<button aria-label="Cached version info" title="This page is a cached copy" style="' + |
| 21 | + 'all:initial;cursor:pointer;position:fixed;right:16px;bottom:16px;z-index:2147483647;' + |
| 22 | + 'width:36px;height:36px;border-radius:50%;border:2px solid #2ecc71;' + |
| 23 | + 'background:#1a1a1a;color:#2ecc71;font:700 20px/1 -apple-system,BlinkMacSystemFont,\'Segoe UI\',Roboto,sans-serif;' + |
| 24 | + 'font-style:italic;display:flex;align-items:center;justify-content:center;' + |
| 25 | + 'box-shadow:0 4px 14px rgba(0,0,0,0.55);user-select:none;' + |
| 26 | + '">i</button>' + |
| 27 | + '<div class="acc-cached-note" style="' + |
| 28 | + 'position:fixed;right:16px;bottom:64px;z-index:2147483647;display:none;max-width:310px;' + |
| 29 | + 'font:13px/1.5 -apple-system,BlinkMacSystemFont,\'Segoe UI\',Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;' + |
| 30 | + 'color:#e5e5e5;background:#1a1a1a;border:1px solid #2ecc71;border-left:4px solid #2ecc71;' + |
| 31 | + 'border-radius:10px;padding:12px 14px;box-shadow:0 6px 18px rgba(0,0,0,0.55);' + |
| 32 | + '">' + |
| 33 | + '<div style="font-weight:700;color:#2ecc71;margin-bottom:4px;">Cached version</div>' + |
| 34 | + '<div style="color:#b2b2b2;">You are looking at a locally cached copy of this page ' + |
| 35 | + 'because the network version could not be loaded right now. To force-load the live page, ' + |
| 36 | + 'press <b style="color:#e5e5e5;">Ctrl + Shift + R</b> (Windows/Linux) ' + |
| 37 | + 'or <b style="color:#e5e5e5;">Cmd + Shift + R</b> (macOS). ' + |
| 38 | + '<a href="' + location.pathname + '" style="color:#2ecc71;font-weight:600;text-decoration:none;">Reload live →</a>' + |
| 39 | + '</div>' + |
| 40 | + '</div>'; |
| 41 | + |
| 42 | + var btn = wrap.firstElementChild; |
| 43 | + var note = wrap.lastElementChild; |
| 44 | + |
| 45 | + function toggle(force) { |
| 46 | + note.style.display = typeof force === "boolean" ? (force ? "block" : "none") : (note.style.display === "block" ? "none" : "block"); |
| 47 | + } |
| 48 | + |
| 49 | + btn.addEventListener("click", function (e) { |
| 50 | + e.stopPropagation(); |
| 51 | + toggle(); |
| 52 | + }); |
| 53 | + // Hover also reveals it (discoverable), click finishes interaction. |
| 54 | + btn.addEventListener("mouseenter", function () { toggle(true); }); |
| 55 | + btn.addEventListener("mouseleave", function () { toggle(false); }); |
| 56 | + // Dismiss when clicking outside. |
| 57 | + document.addEventListener("click", function (e) { |
| 58 | + if (!wrap.contains(e.target)) toggle(false); |
36 | 59 | }); |
37 | 60 |
|
38 | | - (document.body || document.documentElement).appendChild(b); |
| 61 | + (document.body || document.documentElement).appendChild(wrap); |
39 | 62 | } |
40 | 63 |
|
41 | 64 | navigator.serviceWorker.addEventListener("message", function (e) { |
|
0 commit comments