From d9cb615f1fa8f7898cc281d6f099562059bbe815 Mon Sep 17 00:00:00 2001 From: Yuri Karamian Date: Thu, 11 Jun 2026 22:25:51 +0200 Subject: [PATCH] Tasks: add a free-text filter box (matches task text or note title) (#95) --- src/lib/components/TasksView.svelte | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/lib/components/TasksView.svelte b/src/lib/components/TasksView.svelte index 109535b..3f993fe 100644 --- a/src/lib/components/TasksView.svelte +++ b/src/lib/components/TasksView.svelte @@ -16,6 +16,7 @@ let tasks = $state([]); let loading = $state(true); + let taskQuery = $state(''); let unlisten: (() => void) | null = null; async function load() { @@ -41,11 +42,18 @@ const prioRank: Record = { high: 0, med: 1, low: 2 }; function prank(p: string | null) { return p ? (prioRank[p] ?? 3) : 3; } + // Free-text task filter: matches the task text or its note title (case-insensitive). + function matchesQuery(t: TaskItem): boolean { + const q = taskQuery.trim().toLowerCase(); + if (!q) return true; + return t.text.toLowerCase().includes(q) || t.note_title.toLowerCase().includes(q); + } const filtered = $derived.by(() => { let list = tasks.slice(); if ($tasksHideCompleted) list = list.filter((t) => !t.completed); if ($tasksOnlyFlagged) list = list.filter((t) => !!t.due || !!t.priority); + list = list.filter(matchesQuery); list.sort((a, b) => { if (a.completed !== b.completed) return a.completed ? 1 : -1; // done last if ($tasksSort === 'priority') { @@ -109,7 +117,7 @@ const calDayNames = $derived([...DOW.slice(weekStartsOn), ...DOW.slice(0, weekStartsOn)]); // Calendar tasks share the list's hide-completed filter (no sort). - const calBase = $derived(tasks.filter((t) => (!$tasksHideCompleted || !t.completed) && (!$tasksOnlyFlagged || !!t.due || !!t.priority))); + const calBase = $derived(tasks.filter((t) => (!$tasksHideCompleted || !t.completed) && (!$tasksOnlyFlagged || !!t.due || !!t.priority) && matchesQuery(t))); const tasksByDate = $derived.by(() => { const m = new Map(); @@ -185,6 +193,7 @@ {/if}
+ { if (e.key === 'Escape') taskQuery = ''; }} aria-label="Filter tasks by text" /> {#if !isAndroid} @@ -366,6 +375,17 @@ color: #fff; border-color: var(--accent); } + .tasks-filter { + width: 150px; + padding: 3px 8px; + border: 1px solid var(--border-color); + border-radius: 5px; + background: var(--bg-secondary); + color: var(--text-primary); + font-size: 12px; + } + .tasks-filter::placeholder { color: var(--text-tertiary); } + .tasks-filter:focus { outline: none; border-color: var(--accent); } .tasks-list { flex: 1; overflow-y: auto;