diff --git a/apps/tauri/src/lib/components/TaskDetailView.svelte b/apps/tauri/src/lib/components/TaskDetailView.svelte index 8392600..e54e763 100644 --- a/apps/tauri/src/lib/components/TaskDetailView.svelte +++ b/apps/tauri/src/lib/components/TaskDetailView.svelte @@ -34,9 +34,8 @@ function debouncedSave(fields: Partial) { clearTimeout(saveTimer); - const snapshot = { ...task }; saveTimer = setTimeout(() => { - app.updateTask({ ...snapshot, ...fields, updated_at: new Date().toISOString() }); + app.updateTask({ ...task, ...fields, updated_at: new Date().toISOString() }); }, 400); } diff --git a/apps/tauri/src/lib/components/TaskItem.svelte b/apps/tauri/src/lib/components/TaskItem.svelte index bf922a7..d90f15b 100644 --- a/apps/tauri/src/lib/components/TaskItem.svelte +++ b/apps/tauri/src/lib/components/TaskItem.svelte @@ -19,6 +19,7 @@ let isCompleted = $derived(task.status === "completed"); let justChecked = $state(false); + let toggling = $state(false); $effect(() => { const _ = task.status; @@ -35,6 +36,8 @@ async function handleToggle(e: MouseEvent) { e.stopPropagation(); + if (toggling) return; + toggling = true; justChecked = true; await new Promise((r) => setTimeout(r, 300)); transitioning = true; @@ -42,6 +45,7 @@ await new Promise((r) => setTimeout(r, 200)); justChecked = false; await app.toggleTask(task.id); + toggling = false; } function handleTouchStart(e: TouchEvent) { @@ -57,14 +61,15 @@ } function handleTouchEnd() { - if (Math.abs(swipeX) > 100) { + if (Math.abs(swipeX) > 100 && !toggling) { swipeX = 0; swiping = false; + toggling = true; justChecked = true; setTimeout(() => { transitioning = true; animateInIds.add(task.id); - setTimeout(() => { justChecked = false; app.toggleTask(task.id); }, 200); + setTimeout(() => { justChecked = false; app.toggleTask(task.id).finally(() => { toggling = false; }); }, 200); }, 300); return; } diff --git a/apps/tauri/src/lib/stores/app.svelte.ts b/apps/tauri/src/lib/stores/app.svelte.ts index f6dd48a..fd42e50 100644 --- a/apps/tauri/src/lib/stores/app.svelte.ts +++ b/apps/tauri/src/lib/stores/app.svelte.ts @@ -9,12 +9,8 @@ import type { } from "../types"; // Listen for file system changes from the backend watcher. -// Store the unlisten function so it can be cleaned up if needed. -let _unlistenFs: (() => void) | null = null; listen("fs-changed", () => { loadLists(); -}).then((unlisten) => { - _unlistenFs = unlisten; }); // ── Reactive state ─────────────────────────────────────────────────── @@ -98,7 +94,7 @@ async function switchWorkspace(name: string) { activeListId = null; await loadLists(); const ws = config?.workspaces[name]; - if (ws) invoke("watch_workspace", { path: ws.path }).catch(() => {}); + if (ws) invoke("watch_workspace", { path: ws.path }).catch((e) => console.warn("File watcher failed:", e)); error = null; } catch (e) { error = String(e); @@ -200,7 +196,7 @@ async function toggleTask(taskId: string) { // Move to top of list locally, then persist order in background if (updated.status === "backlog") { tasks = [updated, ...tasks.filter((t) => t.id !== taskId)]; - invoke("reorder_task", { listId: activeListId, taskId, newPosition: 0 }).catch(() => {}); + invoke("reorder_task", { listId: activeListId, taskId, newPosition: 0 }).catch((e) => { error = String(e); }); } else { tasks = tasks.map((t) => (t.id === taskId ? updated : t)); }