mirror of
https://gitlab.com/ArkHost/HelixNotes.git
synced 2026-07-24 07:45:57 +02:00
Fix Android note creation delay: throttle file watcher IPC (#191)
This commit is contained in:
+26
-38
@@ -5,6 +5,22 @@ use crate::vault::{operations, watcher};
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use tauri::{AppHandle, Manager, State};
|
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 ──
|
// ── Vault Management ──
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@@ -338,12 +354,8 @@ pub fn save_note(
|
|||||||
|
|
||||||
operations::save_note(&path, &meta, &body)?;
|
operations::save_note(&path, &meta, &body)?;
|
||||||
|
|
||||||
// Re-index note so search picks up changes immediately
|
// Re-index note so search picks up changes (background to avoid blocking on FUSE fsync)
|
||||||
if let Ok(search_guard) = state.search_index.lock() {
|
index_note_bg(&state, &path);
|
||||||
if let Some(ref search) = *search_guard {
|
|
||||||
let _ = search.index_note(&path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -358,12 +370,8 @@ pub fn create_note(
|
|||||||
let vault_path = config.active_vault.as_ref().ok_or("No active vault")?;
|
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 entry = operations::create_note(vault_path, notebook_relative.as_deref(), &title)?;
|
||||||
|
|
||||||
// Index new note
|
// Index new note (background to avoid blocking on FUSE fsync)
|
||||||
if let Ok(search_guard) = state.search_index.lock() {
|
index_note_bg(&state, &entry.path);
|
||||||
if let Some(ref search) = *search_guard {
|
|
||||||
let _ = search.index_note(&entry.path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(entry)
|
Ok(entry)
|
||||||
}
|
}
|
||||||
@@ -374,11 +382,7 @@ pub fn create_daily_note(state: State<'_, AppState>, date: Option<String>) -> Re
|
|||||||
let vault_path = config.active_vault.as_ref().ok_or("No active vault")?;
|
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)?;
|
let entry = operations::create_daily_note(vault_path, date.as_deref(), &config.daily_title_format)?;
|
||||||
|
|
||||||
if let Ok(search_guard) = state.search_index.lock() {
|
index_note_bg(&state, &entry.path);
|
||||||
if let Some(ref search) = *search_guard {
|
|
||||||
let _ = search.index_note(&entry.path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(entry)
|
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")?;
|
let vault_path = config.active_vault.as_ref().ok_or("No active vault")?;
|
||||||
operations::delete_note(vault_path, &path)?;
|
operations::delete_note(vault_path, &path)?;
|
||||||
|
|
||||||
// Remove from index
|
// Remove from index (background to avoid blocking on FUSE fsync)
|
||||||
if let Ok(search_guard) = state.search_index.lock() {
|
remove_note_bg(&state, &path);
|
||||||
if let Some(ref search) = *search_guard {
|
|
||||||
let _ = search.remove_note(&path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -781,11 +781,7 @@ pub fn set_task_done(
|
|||||||
}
|
}
|
||||||
operations::save_note(¬e_path, &meta, &new_body)?;
|
operations::save_note(¬e_path, &meta, &new_body)?;
|
||||||
|
|
||||||
if let Ok(guard) = state.search_index.lock() {
|
index_note_bg(&state, ¬e_path);
|
||||||
if let Some(search) = guard.as_ref() {
|
|
||||||
let _ = search.index_note(¬e_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -842,11 +838,7 @@ pub fn set_task_priority(
|
|||||||
}
|
}
|
||||||
operations::save_note(¬e_path, &meta, &new_body)?;
|
operations::save_note(¬e_path, &meta, &new_body)?;
|
||||||
|
|
||||||
if let Ok(guard) = state.search_index.lock() {
|
index_note_bg(&state, ¬e_path);
|
||||||
if let Some(search) = guard.as_ref() {
|
|
||||||
let _ = search.index_note(¬e_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,11 +894,7 @@ pub fn set_task_due(
|
|||||||
}
|
}
|
||||||
operations::save_note(¬e_path, &meta, &new_body)?;
|
operations::save_note(¬e_path, &meta, &new_body)?;
|
||||||
|
|
||||||
if let Ok(guard) = state.search_index.lock() {
|
index_note_bg(&state, ¬e_path);
|
||||||
if let Some(search) = guard.as_ref() {
|
|
||||||
let _ = search.index_note(¬e_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,15 @@ pub fn start_watcher(app: AppHandle, vault_path: String) -> Result<RecommendedWa
|
|||||||
};
|
};
|
||||||
let _ = app.emit("file-changed", &fe);
|
let _ = app.emit("file-changed", &fe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On mobile, throttle event emission to prevent IPC flooding
|
||||||
|
// on FUSE filesystems where Syncthing/other apps generate
|
||||||
|
// constant file activity that blocks the Tauri command channel.
|
||||||
|
#[cfg(mobile)]
|
||||||
|
{
|
||||||
|
std::thread::sleep(Duration::from_secs(2));
|
||||||
|
while rx.try_recv().is_ok() {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("File watcher error: {}", e);
|
log::error!("File watcher error: {}", e);
|
||||||
|
|||||||
@@ -915,7 +915,7 @@
|
|||||||
<Sidebar bind:this={sidebar} onViewChanged={handleViewChanged} />
|
<Sidebar bind:this={sidebar} onViewChanged={handleViewChanged} />
|
||||||
</div>
|
</div>
|
||||||
<div class="mobile-panel" class:active={$mobileView === 'notelist'}>
|
<div class="mobile-panel" class:active={$mobileView === 'notelist'}>
|
||||||
<NoteList bind:this={noteList} onNoteSelected={handleNoteSelected} onBeforeNoteSwitch={() => editor?.flushSave()} onNoteMoved={() => sidebar?.refresh()} onNoteCreated={() => { editor?.focusTitle(); sidebar?.refresh(); }} onToggleTask={toggleTask} onSetTaskPriority={changeTaskPriority} onSetTaskDue={changeTaskDue} />
|
<NoteList bind:this={noteList} onNoteSelected={handleNoteSelected} onBeforeNoteSwitch={() => editor?.flushSave()} onNoteMoved={() => sidebar?.refresh()} onNoteCreated={() => { editor?.focusTitle(); }} onToggleTask={toggleTask} onSetTaskPriority={changeTaskPriority} onSetTaskDue={changeTaskDue} />
|
||||||
</div>
|
</div>
|
||||||
<div class="mobile-panel" class:active={$mobileView === 'editor'}>
|
<div class="mobile-panel" class:active={$mobileView === 'editor'}>
|
||||||
<Editor bind:this={editor} />
|
<Editor bind:this={editor} />
|
||||||
@@ -976,7 +976,7 @@
|
|||||||
|
|
||||||
{#if !$notelistCollapsed}
|
{#if !$notelistCollapsed}
|
||||||
<div class="notelist-panel" style="width: {$notelistWidth}px">
|
<div class="notelist-panel" style="width: {$notelistWidth}px">
|
||||||
<NoteList bind:this={noteList} onNoteSelected={handleNoteSelected} onBeforeNoteSwitch={() => editor?.flushSave()} onNoteMoved={() => sidebar?.refresh()} onNoteCreated={() => { editor?.focusTitle(); sidebar?.refresh(); }} onToggleTask={toggleTask} onSetTaskPriority={changeTaskPriority} onSetTaskDue={changeTaskDue} />
|
<NoteList bind:this={noteList} onNoteSelected={handleNoteSelected} onBeforeNoteSwitch={() => editor?.flushSave()} onNoteMoved={() => sidebar?.refresh()} onNoteCreated={() => { editor?.focusTitle(); }} onToggleTask={toggleTask} onSetTaskPriority={changeTaskPriority} onSetTaskDue={changeTaskDue} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ResizeHandle onResize={handleNotelistResize} />
|
<ResizeHandle onResize={handleNotelistResize} />
|
||||||
|
|||||||
@@ -442,8 +442,12 @@
|
|||||||
const entry = await createNote(nbRelative, 'Untitled');
|
const entry = await createNote(nbRelative, 'Untitled');
|
||||||
if ($sortMode === 'custom') appendManualNoteOrder(entry.path);
|
if ($sortMode === 'custom') appendManualNoteOrder(entry.path);
|
||||||
noteCache.clear();
|
noteCache.clear();
|
||||||
await refresh();
|
$notes = [entry, ...$notes];
|
||||||
await selectNote(entry);
|
onBeforeNoteSwitch();
|
||||||
|
$activeNote = { path: entry.path, meta: entry.meta, content: '\n', raw: '' };
|
||||||
|
$activeNotePath = entry.path;
|
||||||
|
$editorDirty = false;
|
||||||
|
onNoteSelected(entry.path, '\n');
|
||||||
onNoteCreated();
|
onNoteCreated();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to create note:', e);
|
console.error('Failed to create note:', e);
|
||||||
|
|||||||
Reference in New Issue
Block a user