Persist filter and auto-redact preferences to localStorage
Category toggles and the auto-redact checkbox now survive page reloads. On mount, useFilters reads from localStorage keys session-viewer:enabledCategories and session-viewer:autoRedact, falling back to defaults when storage is empty, corrupted, or contains invalid category names. Each state change writes back to localStorage in a useEffect. Tests cover round-trip persistence, invalid data recovery, corrupted JSON fallback, and the boolean coercion for auto-redact. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,40 @@
|
||||
import { useState, useCallback, useMemo } from "react";
|
||||
import { useState, useCallback, useMemo, useEffect } from "react";
|
||||
import type { MessageCategory, ParsedMessage } from "../lib/types";
|
||||
import { ALL_CATEGORIES, DEFAULT_HIDDEN_CATEGORIES } from "../lib/types";
|
||||
|
||||
const STORAGE_KEY_CATEGORIES = "session-viewer:enabledCategories";
|
||||
const STORAGE_KEY_AUTOREDACT = "session-viewer:autoRedact";
|
||||
|
||||
function loadEnabledCategories(): Set<MessageCategory> {
|
||||
try {
|
||||
const stored = localStorage.getItem(STORAGE_KEY_CATEGORIES);
|
||||
if (stored) {
|
||||
const arr = JSON.parse(stored) as string[];
|
||||
const valid = arr.filter((c) =>
|
||||
ALL_CATEGORIES.includes(c as MessageCategory)
|
||||
) as MessageCategory[];
|
||||
if (valid.length > 0) return new Set(valid);
|
||||
}
|
||||
} catch {
|
||||
// Fall through to default
|
||||
}
|
||||
const set = new Set(ALL_CATEGORIES);
|
||||
for (const cat of DEFAULT_HIDDEN_CATEGORIES) {
|
||||
set.delete(cat);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
function loadAutoRedact(): boolean {
|
||||
try {
|
||||
const stored = localStorage.getItem(STORAGE_KEY_AUTOREDACT);
|
||||
if (stored !== null) return stored === "true";
|
||||
} catch {
|
||||
// Fall through to default
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
interface FilterState {
|
||||
enabledCategories: Set<MessageCategory>;
|
||||
toggleCategory: (cat: MessageCategory) => void;
|
||||
@@ -20,13 +53,7 @@ interface FilterState {
|
||||
export function useFilters(): FilterState {
|
||||
const [enabledCategories, setEnabledCategories] = useState<
|
||||
Set<MessageCategory>
|
||||
>(() => {
|
||||
const set = new Set(ALL_CATEGORIES);
|
||||
for (const cat of DEFAULT_HIDDEN_CATEGORIES) {
|
||||
set.delete(cat);
|
||||
}
|
||||
return set;
|
||||
});
|
||||
>(loadEnabledCategories);
|
||||
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [redactedUuids, setRedactedUuids] = useState<Set<string>>(new Set());
|
||||
@@ -34,7 +61,28 @@ export function useFilters(): FilterState {
|
||||
Set<string>
|
||||
>(new Set());
|
||||
|
||||
const [autoRedactEnabled, setAutoRedactEnabled] = useState(false);
|
||||
const [autoRedactEnabled, setAutoRedactEnabled] = useState(loadAutoRedact);
|
||||
|
||||
// Persist enabledCategories to localStorage
|
||||
useEffect(() => {
|
||||
try {
|
||||
localStorage.setItem(
|
||||
STORAGE_KEY_CATEGORIES,
|
||||
JSON.stringify([...enabledCategories])
|
||||
);
|
||||
} catch {
|
||||
// Ignore storage errors
|
||||
}
|
||||
}, [enabledCategories]);
|
||||
|
||||
// Persist autoRedact to localStorage
|
||||
useEffect(() => {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY_AUTOREDACT, String(autoRedactEnabled));
|
||||
} catch {
|
||||
// Ignore storage errors
|
||||
}
|
||||
}, [autoRedactEnabled]);
|
||||
|
||||
const toggleCategory = useCallback((cat: MessageCategory) => {
|
||||
setEnabledCategories((prev) => {
|
||||
|
||||
Reference in New Issue
Block a user