diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 428c55b..ac123ed 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -5,6 +5,22 @@ use crate::vault::{operations, watcher}; use std::path::Path; use tauri::{AppHandle, Manager, State}; +fn index_note_bg(state: &State<'_, AppState>, path: &str) { + let search = state.search_index.lock().ok().and_then(|g| g.clone()); + if let Some(search) = search { + let p = path.to_string(); + std::thread::spawn(move || { let _ = search.index_note(&p); }); + } +} + +fn remove_note_bg(state: &State<'_, AppState>, path: &str) { + let search = state.search_index.lock().ok().and_then(|g| g.clone()); + if let Some(search) = search { + let p = path.to_string(); + std::thread::spawn(move || { let _ = search.remove_note(&p); }); + } +} + // ── Vault Management ── #[tauri::command] @@ -338,12 +354,8 @@ pub fn save_note( operations::save_note(&path, &meta, &body)?; - // Re-index note so search picks up changes immediately - if let Ok(search_guard) = state.search_index.lock() { - if let Some(ref search) = *search_guard { - let _ = search.index_note(&path); - } - } + // Re-index note so search picks up changes (background to avoid blocking on FUSE fsync) + index_note_bg(&state, &path); Ok(()) } @@ -354,18 +366,14 @@ pub fn create_note( notebook_relative: Option, title: String, ) -> Result { - let config = state.config.lock().map_err(|e| e.to_string())?; - let vault_path = config.active_vault.as_ref().ok_or("No active vault")?; - let entry = operations::create_note(vault_path, notebook_relative.as_deref(), &title)?; + let config = state.config.lock().map_err(|e| e.to_string())?; + let vault_path = config.active_vault.as_ref().ok_or("No active vault")?; + let entry = operations::create_note(vault_path, notebook_relative.as_deref(), &title)?; - // Index new note - if let Ok(search_guard) = state.search_index.lock() { - if let Some(ref search) = *search_guard { - let _ = search.index_note(&entry.path); - } - } + // Index new note (background to avoid blocking on FUSE fsync) + index_note_bg(&state, &entry.path); - Ok(entry) + Ok(entry) } #[tauri::command] @@ -374,11 +382,7 @@ pub fn create_daily_note(state: State<'_, AppState>, date: Option) -> Re let vault_path = config.active_vault.as_ref().ok_or("No active vault")?; let entry = operations::create_daily_note(vault_path, date.as_deref(), &config.daily_title_format)?; - if let Ok(search_guard) = state.search_index.lock() { - if let Some(ref search) = *search_guard { - let _ = search.index_note(&entry.path); - } - } + index_note_bg(&state, &entry.path); Ok(entry) } @@ -397,12 +401,8 @@ pub fn delete_note(state: State<'_, AppState>, path: String) -> Result<(), Strin let vault_path = config.active_vault.as_ref().ok_or("No active vault")?; operations::delete_note(vault_path, &path)?; - // Remove from index - if let Ok(search_guard) = state.search_index.lock() { - if let Some(ref search) = *search_guard { - let _ = search.remove_note(&path); - } - } + // Remove from index (background to avoid blocking on FUSE fsync) + remove_note_bg(&state, &path); Ok(()) } @@ -781,11 +781,7 @@ pub fn set_task_done( } operations::save_note(¬e_path, &meta, &new_body)?; - if let Ok(guard) = state.search_index.lock() { - if let Some(search) = guard.as_ref() { - let _ = search.index_note(¬e_path); - } - } + index_note_bg(&state, ¬e_path); Ok(()) } @@ -842,11 +838,7 @@ pub fn set_task_priority( } operations::save_note(¬e_path, &meta, &new_body)?; - if let Ok(guard) = state.search_index.lock() { - if let Some(search) = guard.as_ref() { - let _ = search.index_note(¬e_path); - } - } + index_note_bg(&state, ¬e_path); Ok(()) } @@ -902,11 +894,7 @@ pub fn set_task_due( } operations::save_note(¬e_path, &meta, &new_body)?; - if let Ok(guard) = state.search_index.lock() { - if let Some(search) = guard.as_ref() { - let _ = search.index_note(¬e_path); - } - } + index_note_bg(&state, ¬e_path); Ok(()) } diff --git a/src-tauri/src/vault/watcher.rs b/src-tauri/src/vault/watcher.rs index 2338d7d..cce1544 100644 --- a/src-tauri/src/vault/watcher.rs +++ b/src-tauri/src/vault/watcher.rs @@ -61,6 +61,15 @@ pub fn start_watcher(app: AppHandle, vault_path: String) -> Result { log::error!("File watcher error: {}", e); diff --git a/src/lib/components/AppLayout.svelte b/src/lib/components/AppLayout.svelte index e47fde8..11e3680 100644 --- a/src/lib/components/AppLayout.svelte +++ b/src/lib/components/AppLayout.svelte @@ -915,7 +915,7 @@
- editor?.flushSave()} onNoteMoved={() => sidebar?.refresh()} onNoteCreated={() => { editor?.focusTitle(); sidebar?.refresh(); }} onToggleTask={toggleTask} onSetTaskPriority={changeTaskPriority} onSetTaskDue={changeTaskDue} /> + editor?.flushSave()} onNoteMoved={() => sidebar?.refresh()} onNoteCreated={() => { editor?.focusTitle(); }} onToggleTask={toggleTask} onSetTaskPriority={changeTaskPriority} onSetTaskDue={changeTaskDue} />
@@ -976,7 +976,7 @@ {#if !$notelistCollapsed}
- editor?.flushSave()} onNoteMoved={() => sidebar?.refresh()} onNoteCreated={() => { editor?.focusTitle(); sidebar?.refresh(); }} onToggleTask={toggleTask} onSetTaskPriority={changeTaskPriority} onSetTaskDue={changeTaskDue} /> + editor?.flushSave()} onNoteMoved={() => sidebar?.refresh()} onNoteCreated={() => { editor?.focusTitle(); }} onToggleTask={toggleTask} onSetTaskPriority={changeTaskPriority} onSetTaskDue={changeTaskDue} />
diff --git a/src/lib/components/NoteList.svelte b/src/lib/components/NoteList.svelte index 3b5424f..204c135 100644 --- a/src/lib/components/NoteList.svelte +++ b/src/lib/components/NoteList.svelte @@ -442,8 +442,12 @@ const entry = await createNote(nbRelative, 'Untitled'); if ($sortMode === 'custom') appendManualNoteOrder(entry.path); noteCache.clear(); - await refresh(); - await selectNote(entry); + $notes = [entry, ...$notes]; + onBeforeNoteSwitch(); + $activeNote = { path: entry.path, meta: entry.meta, content: '\n', raw: '' }; + $activeNotePath = entry.path; + $editorDirty = false; + onNoteSelected(entry.path, '\n'); onNoteCreated(); } catch (e) { console.error('Failed to create note:', e);