updateEntry's .map() always returned a new array even when no entry matched, causing unnecessary state changes. During note creation, addEntry uses startTransition (deferred) while markContentPending calls updateEntry synchronously — the entry doesn't exist yet, so the no-op .map() produced a new reference that cascaded into "Maximum update depth exceeded" (which surfaced as React error #185 in the production WKWebView build). The fix makes updateEntry bail out (return prev) when no entry was changed, preventing the spurious state update. Also removes the defensive try-catch from the previous fix attempt and cleans up an unnecessary setToastMessage dependency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.4 KiB
type, id, title, status, date
| type | id | title | status | date |
|---|---|---|---|---|
| ADR | 0033 | Subfolder scanning and folder tree navigation | active | 2026-03-31 |
Context
0032 Status Bar For Git Actions
Supersedes the scanning constraint in ADR-0006 which limited vault indexing to root-level .md files plus protected folders (attachments/, assets/).
Users with folder-based workflows (PARA, Zettelkasten with folders, project directories) could not see or filter notes by directory. The vault scanner silently ignored all subdirectory .md files, making Laputa unsuitable for vaults with any folder structure.
Decision
Extend the Rust vault scanner to index .md files in all visible subdirectories, and expose the vault's folder tree via a new list_vault_folders Tauri command so the sidebar can render a collapsible FOLDERS section.
Hidden directories (names starting with ., plus .git and .laputa) are excluded from both scanning and the folder tree.
Options considered
- Option A (chosen): Scan all subdirectories with
walkdir, expose separatelist_vault_folderscommand — simple, no schema changes to VaultEntry, folder tree is lightweight and independent of the entry cache. - Option B: Add a
folderfield to VaultEntry and derive the tree on the frontend — couples folder metadata to the entry cache, complicates cache invalidation when folders are created/deleted without file changes. - Option C: Keep flat scanning, add a "virtual folders" feature that groups by path prefix from frontmatter — doesn't solve the core problem of missing notes in subdirectories.
Consequences
- All
.mdfiles in the vault are now indexed regardless of depth — vaults with many non-note.mdfiles (e.g. node_modules) will see spurious entries. Mitigation: hidden directories are already excluded; users can add a.laputaignorein the future if needed. - The git-based cache in
cache.rsalready useswalkdirfor change detection, so this change aligns scanning with caching. SidebarSelectiongains a new{ kind: 'folder'; path: string }variant — all exhaustive switches on selection kind must handle it.- ADR-0006's "flat vault" principle is relaxed: notes can now live in subdirectories. Type definitions still live in
type/at the root. - Re-evaluate if users request recursive folder filtering (currently only direct children are shown when a folder is selected).