Persist replacements across refresh (device-local, no account)
A reader who swaps a story away should keep that swap after a refresh; before, the server re-served the original brief. - localStorage now persists seen / dismissed / history (loadJSON/saveJSON). - /api/brief accepts an exclude list; dismissed (replaced-away) ids are dropped and the highlights refill around them, so swaps stick and stay full. - Replace records the swap to dismissed+seen and persists; the seen-set (persisted) keeps Replace from recycling across refreshes too. - History panel survives refresh and gains 'Clear what I've seen (start fresh)' so it never feels suffocating. Saved history/favorites still come with sign-in. Tests: brief exclude + refill (90 total). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,24 @@ export function merge(userPrefs, moodFilter = {}) {
|
||||
return m;
|
||||
}
|
||||
|
||||
// Generic device-local JSON storage (used for session memory: seen / dismissed
|
||||
// / history), so an account-less reader's choices survive a refresh.
|
||||
export function loadJSON(key, fallback) {
|
||||
try {
|
||||
const v = JSON.parse(localStorage.getItem(key));
|
||||
return v == null ? fallback : v;
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
export function saveJSON(key, value) {
|
||||
try {
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
} catch {
|
||||
/* private mode / quota — non-fatal */
|
||||
}
|
||||
}
|
||||
|
||||
// "" or "prefs=<encoded json>" for a query string.
|
||||
export function param(prefs) {
|
||||
const empty =
|
||||
|
||||
Reference in New Issue
Block a user