Skip to content

Commit 356b0e7

Browse files
committed
release: v2.7.228
1 parent 0ca772b commit 356b0e7

File tree

4 files changed

+42
-44
lines changed

4 files changed

+42
-44
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
All notable changes to this project will be documented in this file.
66

7+
## [2.7.228] — 2026-03-15
8+
9+
- refactor(web/sidebar): added shared `safeStorageGetJson(...)` in `apps/web/src/components/Sidebar.tsx` so stored navigation preference hydration now reads and parses localStorage payloads through one helper instead of repeating inline `safeStorageGet(...)` + `JSON.parse(...)` flows.
10+
- changed(web/sidebar): collapsed sections, favorites, recent routes, and recent searches now hydrate through the same storage-read path, reducing parse drift and keeping malformed stored payload handling consistent across Sidebar preference surfaces.
11+
- refactor(web/sidebar): removed the unused component-local `persistRecentRoutes(...)` helper so Sidebar no longer keeps an unreferenced older recent-route persistence path around.
12+
- test(web/navigation): reran focused nav validation/config suites after the Sidebar storage-read convergence cleanup (`37` tests passing).
13+
714
## [2.7.227] — 2026-03-15
815

916
- refactor(web/sidebar): added shared `safeStorageRemoveMany(...)` in `apps/web/src/components/Sidebar.tsx` so reset and clear actions now remove persisted navigation preference keys through one helper instead of repeating inline storage deletes.

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.7.227
1+
2.7.228

VERSION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
# Borg Project Version: 2.7.227
1+
# Borg Project Version: 2.7.228

apps/web/src/components/Sidebar.tsx

Lines changed: 33 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ function safeStorageGet(key: string): string | null {
4949
}
5050
}
5151

52+
function safeStorageGetJson<T>(key: string): T | null {
53+
const raw = safeStorageGet(key);
54+
if (!raw) {
55+
return null;
56+
}
57+
58+
try {
59+
return JSON.parse(raw) as T;
60+
} catch {
61+
return null;
62+
}
63+
}
64+
5265
function safeStorageSet(key: string, value: string): void {
5366
const storage = getSafeLocalStorage();
5467
if (!storage) {
@@ -112,55 +125,39 @@ export function Sidebar({ className }: SidebarProps) {
112125
const paletteInputRef = useRef<HTMLInputElement | null>(null);
113126

114127
useEffect(() => {
115-
try {
116-
const raw = safeStorageGet(SIDEBAR_COLLAPSE_STORAGE_KEY);
117-
if (!raw) {
118-
return;
119-
}
120-
const parsed = JSON.parse(raw);
121-
setCollapsedSections(sanitizeCollapsedSections(parsed, sectionTitles));
122-
} catch {
123-
// ignore invalid stored state
128+
const parsed = safeStorageGetJson<unknown>(SIDEBAR_COLLAPSE_STORAGE_KEY);
129+
if (parsed === null) {
130+
return;
124131
}
132+
133+
setCollapsedSections(sanitizeCollapsedSections(parsed, sectionTitles));
125134
}, [sectionTitles]);
126135

127136
useEffect(() => {
128-
try {
129-
const raw = safeStorageGet(SIDEBAR_FAVORITES_STORAGE_KEY);
130-
if (!raw) {
131-
return;
132-
}
133-
const parsed = JSON.parse(raw);
134-
setFavorites(sanitizeFavoriteRoutes(parsed, allowedNavHrefs));
135-
} catch {
136-
// ignore invalid stored state
137+
const parsed = safeStorageGetJson<unknown>(SIDEBAR_FAVORITES_STORAGE_KEY);
138+
if (parsed === null) {
139+
return;
137140
}
141+
142+
setFavorites(sanitizeFavoriteRoutes(parsed, allowedNavHrefs));
138143
}, [allowedNavHrefs]);
139144

140145
useEffect(() => {
141-
try {
142-
const raw = safeStorageGet(SIDEBAR_RECENT_STORAGE_KEY);
143-
if (!raw) {
144-
return;
145-
}
146-
const parsed = JSON.parse(raw);
147-
setRecentRoutes(sanitizeRecentRoutes(parsed, allowedNavHrefs, MAX_RECENT_ROUTES));
148-
} catch {
149-
// ignore invalid stored state
146+
const parsed = safeStorageGetJson<unknown>(SIDEBAR_RECENT_STORAGE_KEY);
147+
if (parsed === null) {
148+
return;
150149
}
150+
151+
setRecentRoutes(sanitizeRecentRoutes(parsed, allowedNavHrefs, MAX_RECENT_ROUTES));
151152
}, [allowedNavHrefs]);
152153

153154
useEffect(() => {
154-
try {
155-
const raw = safeStorageGet(SIDEBAR_RECENT_SEARCHES_STORAGE_KEY);
156-
if (!raw) {
157-
return;
158-
}
159-
const parsed = JSON.parse(raw);
160-
setRecentSearches(sanitizeRecentSearches(parsed, MAX_RECENT_SEARCHES));
161-
} catch {
162-
// ignore invalid stored state
155+
const parsed = safeStorageGetJson<unknown>(SIDEBAR_RECENT_SEARCHES_STORAGE_KEY);
156+
if (parsed === null) {
157+
return;
163158
}
159+
160+
setRecentSearches(sanitizeRecentSearches(parsed, MAX_RECENT_SEARCHES));
164161
}, []);
165162

166163
const normalizedPathname = normalizeNavHref(pathname);
@@ -339,12 +336,6 @@ export function Sidebar({ className }: SidebarProps) {
339336
persistFavorites([...favorites, normalizedHref]);
340337
};
341338

342-
const persistRecentRoutes = (next: string[]) => {
343-
const normalized = normalizeNavHrefList(next).slice(0, MAX_RECENT_ROUTES);
344-
setRecentRoutes(normalized);
345-
safeStorageSetJson(SIDEBAR_RECENT_STORAGE_KEY, normalized);
346-
};
347-
348339
const persistRecentSearches = (next: string[]) => {
349340
const sanitized = sanitizeRecentSearches(next, MAX_RECENT_SEARCHES);
350341
setRecentSearches(sanitized);

0 commit comments

Comments
 (0)