Frontend State Stores
Relevant source files
The following files were used as context for generating this wiki page:
Frontend state management in Augenblick is built primarily using Zustand, facilitating reactive UI updates and synchronized communication with the Rust-based Tauri backend. These stores manage note data lifecycle, application settings, and UI-specific states like sidebar dimensions and view modes.
The architecture emphasizes a clear separation between transient frontend state (e.g., pending drafts, dirty flags) and persistent backend state (SQLite database and local files). This ensures feature parity with the original Svelte implementation while leveraging React's functional component patterns. Sources: plans/migration.md:31-41, src/stores/notesStore.ts:153
Notes Store Architecture
The notesStore is the central hub for managing note content, metadata, and selection logic. It handles complex operations such as debounced autosaving for drafts and "dirty" tracking for saved notes.
Core Data Structures
The store maintains several key pieces of state to track the status of notes:
| Field | Type | Description |
|---|---|---|
list | NotesList | Contains active and trashed note arrays. |
selectedId | string | null | The ID of the currently active note in the editor. |
contentById | Record<string, string> | A local cache of note content to prevent redundant disk reads. |
dirtySavedById | Record<string, true> | Tracks which saved notes have unpersisted changes. |
sidebarWidth | number | The current width of the navigation sidebar (clamped 200-400). |
Sources: src/stores/notesStore.ts:9-35, src/stores/notesStore.ts:168-171
Data Flow and Synchronization
The store synchronizes with the backend via an API wrapper. When a note is edited, the store determines the save strategy based on the note's storage type.
The diagram shows the logic branching between automatic draft saving and manual persistence for saved files. Sources: src/stores/notesStore.ts:241-260, src/routes/pageActions.ts:88-102
Selection and Lifecycle Logic
When a note is selected, the store checks the local cache (contentById). If the content is missing, it invokes note_get from the backend. Selection also triggers note_set_active to update the last_interaction timestamp, which is critical for the auto-expiry system. Sources: src/stores/notesStore.ts:211-236, src/test/stores/notes.test.ts:192-202
Settings and App State
The application uses a settingsStore to manage user preferences and a debounced mechanism to persist UI state (app state) to the database.
Settings Management
Settings include appearance themes and retention durations for notes and trash.
- Appearance: Supports
light,dark, andsystemmodes. - Note Expiry: Configuration for when inactive notes move to trash.
- Trash Retention: Configuration for when trashed notes are permanently deleted.
Sources: src/stores/settingsStore.ts, plans/migration.md:129-131
App State Persistence
UI configurations like sidebarWidth and viewMode are persisted to the backend SQLite app_state table using a 250ms debounce timer to prevent excessive IPC calls during rapid UI adjustments (like resizing the sidebar). Sources: src/stores/notesStore.ts:79-92, src/test/stores/notes.test.ts:237-251
User Action Orchestration
State changes are often orchestrated through pageActions, which bridge the stores with system-level dialogs and file pickers.
This flow illustrates the safeguard mechanism that prevents data loss when trashing notes with unsaved changes. Sources: src/routes/pageActions.ts:121-144, src/stores/notesStore.ts:333-345
Reorder and History Logic
The notesStore maintains independent undo/redo stacks for sidebar reordering operations.
- Depth: The stacks are limited to the last 20 operations.
- Implementation: When a reorder occurs, the previous state of the section (pinned or unpinned) is pushed to the
reorderUndoStack. - Persistence: Reorder commands are sent to the backend via
api.notes_reorder, which updates thesort_orderin the database.
Sources: src/stores/notesStore.ts:75-76, src/stores/notesStore.ts:366-393, plans/migration.md:46
Expiry and Cleanup
A specialized "heartbeat" and "sweep" system ensures the state remains consistent with the backend's auto-deletion threads.
- Heartbeat: Every 30 seconds, the frontend calls
note_set_activefor the selected note to prevent it from expiring while being viewed. Sources: src/App.tsx:329-331, src/stores/notesStore.ts:394-401 - Expiry Sweep: The frontend can trigger
runExpirySweep, which invokes the backend's expiry logic and then reconciles the locallistandcontentByIdcache to remove notes that were just purged or moved to trash. Sources: src/stores/notesStore.ts:402-441, src/test/stores/notes.test.ts:108-128
Frontend State Stores provide a robust layer of abstraction that handles the complexities of the "ephemeral" note-taking model, ensuring that UI state, local caches, and backend persistence remain in sync throughout the note lifecycle.