need a status for my status for my .. nate.tngl.io
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

cache results in localStorage, resume countdown across reloads

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

zzstoatzz de129ec5 5ca0d492

+50 -6
+8 -2
site/app.js
··· 1 1 import { GROUPS } from "./services.js"; 2 - import { startAutoRefresh, checkNow } from "./checker.js"; 2 + import { startAutoRefresh, checkNow, loadCache } from "./checker.js"; 3 3 4 4 const groupsEl = document.getElementById("groups"); 5 5 const summaryEl = document.getElementById("summary"); ··· 138 138 checkNow(onResult, onTick); 139 139 }); 140 140 141 - setChecking(); 141 + // show cached results instantly, then start refresh cycle 142 + const cached = loadCache(); 143 + if (cached) { 144 + onResult(cached.byUrl); 145 + } else { 146 + setChecking(); 147 + } 142 148 startAutoRefresh(onResult, onTick);
+42 -4
site/checker.js
··· 1 1 import { PROXY_URL, GROUPS } from "./services.js"; 2 2 3 3 const REFRESH_INTERVAL = 60; 4 + const CACHE_KEY = "evergreen:results"; 5 + const CACHE_TS_KEY = "evergreen:checkedAt"; 4 6 5 7 let countdown = REFRESH_INTERVAL; 6 8 let timer = null; 7 9 8 - export function buildChecks() { 10 + function buildChecks() { 9 11 return GROUPS.flatMap((g) => 10 12 g.services.map((s) => ({ 11 13 url: s.url, ··· 14 16 ); 15 17 } 16 18 17 - export async function checkAll(onResult) { 19 + function saveCache(byUrl) { 20 + try { 21 + const entries = [...byUrl.entries()]; 22 + localStorage.setItem(CACHE_KEY, JSON.stringify(entries)); 23 + localStorage.setItem(CACHE_TS_KEY, String(Date.now())); 24 + } catch {} 25 + } 26 + 27 + export function loadCache() { 28 + try { 29 + const raw = localStorage.getItem(CACHE_KEY); 30 + const ts = Number(localStorage.getItem(CACHE_TS_KEY) || 0); 31 + if (!raw || !ts) return null; 32 + 33 + const age = (Date.now() - ts) / 1000; 34 + if (age > REFRESH_INTERVAL * 3) return null; // stale beyond 3 cycles 35 + 36 + return { 37 + byUrl: new Map(JSON.parse(raw)), 38 + checkedAt: ts, 39 + age, 40 + }; 41 + } catch { 42 + return null; 43 + } 44 + } 45 + 46 + async function checkAll(onResult) { 18 47 const checks = buildChecks(); 19 48 20 49 try { ··· 29 58 for (const r of results) { 30 59 byUrl.set(r.url, r); 31 60 } 61 + saveCache(byUrl); 32 62 onResult(byUrl); 33 63 } catch (e) { 34 64 console.error("batch check failed:", e); ··· 42 72 43 73 export function startAutoRefresh(onResult, onTick) { 44 74 stopAutoRefresh(); 45 - countdown = REFRESH_INTERVAL; 46 75 47 - checkAll(onResult); 76 + // resume countdown if we have recent cached results 77 + const cached = loadCache(); 78 + if (cached) { 79 + const elapsed = Math.floor(cached.age); 80 + const remaining = REFRESH_INTERVAL - (elapsed % REFRESH_INTERVAL); 81 + countdown = Math.max(1, remaining); 82 + } else { 83 + countdown = REFRESH_INTERVAL; 84 + checkAll(onResult); 85 + } 48 86 49 87 timer = setInterval(() => { 50 88 countdown--;