fix: split category fetch, safe localStorage, aria-labels on icon buttons
- TreeLibraryPage: split categories into a mount-only fetch so filter changes only re-fetch trees (not categories every time) - Add safeGetItem/safeSetItem/safeRemoveItem helpers in utils.ts to prevent crashes in private browsing or when storage is unavailable - Replace raw localStorage calls in ScratchpadSidebar, TreeNavigationPage, TreeEditorPage, and treeEditorStore with safe wrappers - Add aria-label to 20 icon-only buttons across 8 component files for screen reader accessibility Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -58,8 +58,16 @@ export function TreeLibraryPage() {
|
||||
}
|
||||
}, [])
|
||||
|
||||
// Load categories once on mount (they rarely change)
|
||||
useEffect(() => {
|
||||
loadData()
|
||||
categoriesApi.list()
|
||||
.then(setCategories)
|
||||
.catch((err) => console.error('Failed to load categories:', err))
|
||||
}, [])
|
||||
|
||||
// Load trees when filters change
|
||||
useEffect(() => {
|
||||
loadTrees()
|
||||
}, [selectedCategoryId, selectedTags, selectedFolderId, treeLibrarySortBy, showDrafts])
|
||||
|
||||
// Load folders on mount and listen for changes
|
||||
@@ -70,21 +78,17 @@ export function TreeLibraryPage() {
|
||||
return () => window.removeEventListener('folder-changed', handleFolderChange)
|
||||
}, [loadFolders])
|
||||
|
||||
const loadData = async () => {
|
||||
const loadTrees = async () => {
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const [treesData, categoriesData] = await Promise.all([
|
||||
treesApi.list({
|
||||
category_id: selectedCategoryId || undefined,
|
||||
tags: selectedTags.length > 0 ? selectedTags.join(',') : undefined,
|
||||
folder_id: selectedFolderId || undefined,
|
||||
sort_by: treeLibrarySortBy,
|
||||
include_drafts: showDrafts || undefined,
|
||||
}),
|
||||
categoriesApi.list(),
|
||||
])
|
||||
const treesData = await treesApi.list({
|
||||
category_id: selectedCategoryId || undefined,
|
||||
tags: selectedTags.length > 0 ? selectedTags.join(',') : undefined,
|
||||
folder_id: selectedFolderId || undefined,
|
||||
sort_by: treeLibrarySortBy,
|
||||
include_drafts: showDrafts || undefined,
|
||||
})
|
||||
setTrees(treesData)
|
||||
setCategories(categoriesData)
|
||||
} catch (err) {
|
||||
toast.error('Failed to load trees')
|
||||
console.error(err)
|
||||
@@ -95,7 +99,7 @@ export function TreeLibraryPage() {
|
||||
|
||||
const handleSearch = async () => {
|
||||
if (!searchQuery.trim()) {
|
||||
loadData()
|
||||
loadTrees()
|
||||
return
|
||||
}
|
||||
setIsLoading(true)
|
||||
@@ -413,7 +417,7 @@ export function TreeLibraryPage() {
|
||||
setFolderModalOpen(false)
|
||||
setNewFolderParentId(null)
|
||||
}}
|
||||
onSave={loadData}
|
||||
onSave={loadTrees}
|
||||
/>
|
||||
|
||||
{/* Delete Confirmation */}
|
||||
|
||||
Reference in New Issue
Block a user