From 2bd6ebe3023039b4b595fc3990ef839a6fbe8bf9 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Sat, 12 Sep 2026 09:18:33 -0700 Subject: [PATCH] fix: purge stale 1-tap mobile pins, make remove pin button bold and prominent, and bust service worker cache --- index.html | 21 +++++++++++++++------ js/auth.js | 16 ++++++++++++++-- js/radar.js | 15 ++++++++++----- sw.js | 42 ++++++++++++++++++++++++++++++------------ 4 files changed, 69 insertions(+), 25 deletions(-) diff --git a/index.html b/index.html index 2777553..cac4c8a 100644 --- a/index.html +++ b/index.html @@ -28,7 +28,7 @@ - + @@ -942,10 +942,19 @@ - - - - - + + + + + + + + diff --git a/js/auth.js b/js/auth.js index 7e001c0..650a8dd 100644 --- a/js/auth.js +++ b/js/auth.js @@ -124,7 +124,13 @@ communityReports = JSON.parse(stored); // Automatically prune any unverified test marks or pins without photo proof const beforeCount = communityReports.length; - communityReports = communityReports.filter(r => r && r.photoUrl && !r.id.startsWith('usr-pin-')); + communityReports = communityReports.filter(r => + r && + r.photoUrl && + !r.id.startsWith('usr-pin-') && + r.notes !== '1-Tap Mobile Driver Pin' && + r.type !== 'Fixed ALPR Camera' + ); if (communityReports.length !== beforeCount) { localStorage.setItem(STORAGE_KEY_REPORTS, JSON.stringify(communityReports)); } @@ -138,7 +144,13 @@ function clearUnverifiedReports() { try { - communityReports = communityReports.filter(r => r && r.photoUrl && !r.id.startsWith('usr-pin-')); + communityReports = communityReports.filter(r => + r && + r.photoUrl && + !r.id.startsWith('usr-pin-') && + r.notes !== '1-Tap Mobile Driver Pin' && + r.type !== 'Fixed ALPR Camera' + ); localStorage.setItem(STORAGE_KEY_REPORTS, JSON.stringify(communityReports)); Object.keys(cameraMetadata).forEach(id => { if (id.startsWith('usr-pin-') || !cameraMetadata[id].photoUrl) { diff --git a/js/radar.js b/js/radar.js index 72c31c9..2775aea 100644 --- a/js/radar.js +++ b/js/radar.js @@ -301,8 +301,12 @@ window.FlockAuth.clearUnverifiedReports(); } - // Filter out any unverified user pins - allCameras = [...DEFAULT_CAMERAS].filter(c => !c.id.startsWith('usr-pin-')); + // Filter out any unverified user pins or accidental test marks + allCameras = [...DEFAULT_CAMERAS].filter(c => + !c.id.startsWith('usr-pin-') && + c.notes !== '1-Tap Mobile Driver Pin' && + c.name !== 'Community Report: Fixed ALPR Camera' + ); // Load crowdsourced reports from auth store (ONLY if photo verified!) if (window.FlockAuth) { @@ -418,9 +422,10 @@ Inspect Agency Records & Sharing ↗ ` : ''} - ${(cam.isCommunity || cam.id.startsWith('rpt-') || cam.id.startsWith('usr-pin-') || cam.id.startsWith('test-') || cam.id.startsWith('cam-test-')) ? ` - ` : ''} diff --git a/sw.js b/sw.js index ae9282a..ed248a3 100644 --- a/sw.js +++ b/sw.js @@ -1,35 +1,53 @@ -// Service Worker for FlockRadar Offline Driving & Caching -const CACHE_NAME = 'flockradar-v2'; +// Service Worker for FlockRadar Offline Driving & Live Updates +const CACHE_NAME = 'flockradar-v6'; const ASSETS_TO_CACHE = [ './', './index.html', - './css/styles.css', - './js/app.js', - './js/auth.js', - './js/radar.js', - './data/portals.js', + './css/styles.css?v=6', + './js/app.js?v=6', + './js/auth.js?v=6', + './js/radar.js?v=6', + './data/portals.js?v=6', './manifest.json' ]; self.addEventListener('install', event => { + self.skipWaiting(); event.waitUntil( caches.open(CACHE_NAME).then(cache => cache.addAll(ASSETS_TO_CACHE)) ); - self.skipWaiting(); }); self.addEventListener('activate', event => { event.waitUntil( caches.keys().then(keys => Promise.all( keys.filter(key => key !== CACHE_NAME).map(key => caches.delete(key)) - )) + )).then(() => self.clients.claim()) ); - self.clients.claim(); }); self.addEventListener('fetch', event => { - // Network first, fallback to cache + // Always network-first for HTML, JS and CSS to ensure instant updates + const url = new URL(event.request.url); + if (url.origin === self.location.origin) { + event.respondWith( + fetch(event.request, { cache: 'no-cache' }) + .then(response => { + if (response && response.status === 200) { + const clone = response.clone(); + caches.open(CACHE_NAME).then(cache => cache.put(event.request, clone)); + } + return response; + }) + .catch(() => caches.match(event.request)) + ); + return; + } + + // Fallback for CDN resources (Leaflet tiles etc) event.respondWith( - fetch(event.request).catch(() => caches.match(event.request)) + caches.match(event.request).then(cached => { + return cached || fetch(event.request); + }) ); });