Address QA findings: prefetch reset on re-lock, settings gate, HSL validation
W-02: Reset hasPrefetched ref when app re-locks so subsequent unlocks refresh stale cache data. S-01: Validate localStorage HSL values with regex to prevent CSS injection. S-05: Defer prefetch until settings are loaded for accurate upcoming_days. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
379cc74387
commit
aa47ba4136
@ -20,9 +20,9 @@
|
|||||||
var c = localStorage.getItem('umbra-accent-color');
|
var c = localStorage.getItem('umbra-accent-color');
|
||||||
if (c) {
|
if (c) {
|
||||||
var p = JSON.parse(c);
|
var p = JSON.parse(c);
|
||||||
if (p.h) h = p.h;
|
if (p.h && /^\d+$/.test(p.h)) h = p.h;
|
||||||
if (p.s) s = p.s;
|
if (p.s && /^\d+\.?\d*%$/.test(p.s)) s = p.s;
|
||||||
if (p.l) l = p.l;
|
if (p.l && /^\d+\.?\d*%$/.test(p.l)) l = p.l;
|
||||||
}
|
}
|
||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
document.getElementById('umbra-accent').textContent =
|
document.getElementById('umbra-accent').textContent =
|
||||||
|
|||||||
@ -12,14 +12,24 @@ export function usePrefetch(enabled: boolean) {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { settings } = useSettings();
|
const { settings } = useSettings();
|
||||||
const hasPrefetched = useRef(false);
|
const hasPrefetched = useRef(false);
|
||||||
|
const prevEnabled = useRef(false);
|
||||||
|
|
||||||
|
// Reset on re-lock so subsequent unlocks refresh stale data (W-02)
|
||||||
|
useEffect(() => {
|
||||||
|
if (prevEnabled.current && !enabled) {
|
||||||
|
hasPrefetched.current = false;
|
||||||
|
}
|
||||||
|
prevEnabled.current = enabled;
|
||||||
|
}, [enabled]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!enabled || hasPrefetched.current) return;
|
// Wait for settings to load so upcoming_days is accurate (S-05)
|
||||||
|
if (!enabled || hasPrefetched.current || !settings) return;
|
||||||
hasPrefetched.current = true;
|
hasPrefetched.current = true;
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const clientDate = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
|
const clientDate = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
|
||||||
const days = settings?.upcoming_days || 7;
|
const days = settings.upcoming_days || 7;
|
||||||
|
|
||||||
// Prefetch all main page queries (no-op if already cached and fresh)
|
// Prefetch all main page queries (no-op if already cached and fresh)
|
||||||
queryClient.prefetchQuery({
|
queryClient.prefetchQuery({
|
||||||
@ -58,5 +68,5 @@ export function usePrefetch(enabled: boolean) {
|
|||||||
queryKey: ['locations'],
|
queryKey: ['locations'],
|
||||||
queryFn: () => api.get('/locations').then(r => r.data),
|
queryFn: () => api.get('/locations').then(r => r.data),
|
||||||
});
|
});
|
||||||
}, [enabled, queryClient, settings?.upcoming_days]);
|
}, [enabled, queryClient, settings]);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user