mirror of
https://gitlab.com/ArkHost/HelixNotes.git
synced 2026-07-24 07:45:57 +02:00
Tasks: per-vault persistence for the Flagged filter, Hide done, and sort mode (issue #94)
This commit is contained in:
@@ -38,6 +38,9 @@
|
||||
viewMode,
|
||||
sortMode,
|
||||
tasksLayout,
|
||||
tasksHideCompleted,
|
||||
tasksOnlyFlagged,
|
||||
tasksSort,
|
||||
activeTag,
|
||||
updateAvailable as globalUpdateAvailable,
|
||||
settingsTab,
|
||||
@@ -202,7 +205,10 @@
|
||||
last_view_mode: $viewMode,
|
||||
last_notebook: $activeNotebook?.relative_path ?? null,
|
||||
last_tag: $activeTag,
|
||||
tasks_layout: $tasksLayout
|
||||
tasks_layout: $tasksLayout,
|
||||
tasks_hide_completed: $tasksHideCompleted,
|
||||
tasks_only_flagged: $tasksOnlyFlagged,
|
||||
tasks_sort: $tasksSort
|
||||
};
|
||||
try {
|
||||
await saveVaultState(state);
|
||||
@@ -504,6 +510,9 @@
|
||||
$effect(() => {
|
||||
$sortMode;
|
||||
$tasksLayout;
|
||||
$tasksHideCompleted;
|
||||
$tasksOnlyFlagged;
|
||||
$tasksSort;
|
||||
persistState();
|
||||
});
|
||||
|
||||
@@ -529,6 +538,9 @@
|
||||
$notebookOrder = state.notebook_order ?? {};
|
||||
if (state.sort_mode === 'created' || state.sort_mode === 'title' || state.sort_mode === 'modified') $sortMode = state.sort_mode;
|
||||
if (state.tasks_layout === 'calendar' || state.tasks_layout === 'list') $tasksLayout = state.tasks_layout;
|
||||
if (typeof state.tasks_hide_completed === 'boolean') $tasksHideCompleted = state.tasks_hide_completed;
|
||||
if (typeof state.tasks_only_flagged === 'boolean') $tasksOnlyFlagged = state.tasks_only_flagged;
|
||||
if (state.tasks_sort === 'due' || state.tasks_sort === 'priority' || state.tasks_sort === 'note') $tasksSort = state.tasks_sort;
|
||||
lastNotePath = state.last_open_note ?? null;
|
||||
lastViewMode = state.last_view_mode ?? '';
|
||||
lastNotebook = state.last_notebook ?? null;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import { getTasks } from '$lib/api';
|
||||
import { debounce } from '$lib/utils/debounce';
|
||||
import { tasksLayout, appConfig } from '$lib/stores/app';
|
||||
import { tasksLayout, tasksHideCompleted, tasksOnlyFlagged, tasksSort, appConfig } from '$lib/stores/app';
|
||||
import { isAndroid } from '$lib/platform';
|
||||
import type { TaskItem, FileEvent } from '$lib/types';
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
let tasks = $state<TaskItem[]>([]);
|
||||
let loading = $state(true);
|
||||
let hideCompleted = $state(true);
|
||||
let sortBy = $state<'due' | 'priority' | 'note'>('due');
|
||||
let unlisten: (() => void) | null = null;
|
||||
|
||||
async function load() {
|
||||
@@ -46,13 +44,14 @@
|
||||
|
||||
const filtered = $derived.by(() => {
|
||||
let list = tasks.slice();
|
||||
if (hideCompleted) list = list.filter((t) => !t.completed);
|
||||
if ($tasksHideCompleted) list = list.filter((t) => !t.completed);
|
||||
if ($tasksOnlyFlagged) list = list.filter((t) => !!t.due || !!t.priority);
|
||||
list.sort((a, b) => {
|
||||
if (a.completed !== b.completed) return a.completed ? 1 : -1; // done last
|
||||
if (sortBy === 'priority') {
|
||||
if ($tasksSort === 'priority') {
|
||||
const d = prank(a.priority) - prank(b.priority);
|
||||
if (d) return d;
|
||||
} else if (sortBy === 'note') {
|
||||
} else if ($tasksSort === 'note') {
|
||||
const d = a.note_title.localeCompare(b.note_title);
|
||||
if (d) return d;
|
||||
} else {
|
||||
@@ -110,7 +109,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) => !hideCompleted || !t.completed));
|
||||
const calBase = $derived(tasks.filter((t) => (!$tasksHideCompleted || !t.completed) && (!$tasksOnlyFlagged || !!t.due || !!t.priority)));
|
||||
|
||||
const tasksByDate = $derived.by(() => {
|
||||
const m = new Map<string, TaskItem[]>();
|
||||
@@ -186,7 +185,8 @@
|
||||
<button class="prio-backdrop" onclick={() => { prioMenuFor = null; dueMenuFor = null; }} aria-label="Close menu"></button>
|
||||
{/if}
|
||||
<div class="tasks-controls">
|
||||
<button class="tasks-ctl" class:active={hideCompleted} onclick={() => (hideCompleted = !hideCompleted)} title="Hide completed tasks">Hide done</button>
|
||||
<button class="tasks-ctl" class:active={$tasksHideCompleted} onclick={() => ($tasksHideCompleted = !$tasksHideCompleted)} title="Hide completed tasks">Hide done</button>
|
||||
<button class="tasks-ctl" class:active={$tasksOnlyFlagged} onclick={() => ($tasksOnlyFlagged = !$tasksOnlyFlagged)} title="Only show tasks with a due date or priority">Flagged</button>
|
||||
{#if !isAndroid}
|
||||
<div class="tasks-layout">
|
||||
<button class="tasks-ctl" class:active={viewLayout === 'list'} onclick={() => ($tasksLayout = 'list')} title="List view">List</button>
|
||||
@@ -196,7 +196,7 @@
|
||||
{#if viewLayout === 'list'}
|
||||
<div class="tasks-sort">
|
||||
{#each [['due', 'Due'], ['priority', 'Priority'], ['note', 'Note']] as [v, label]}
|
||||
<button class="tasks-ctl" class:active={sortBy === v} onclick={() => (sortBy = v as 'due' | 'priority' | 'note')}>{label}</button>
|
||||
<button class="tasks-ctl" class:active={$tasksSort === v} onclick={() => ($tasksSort = v as 'due' | 'priority' | 'note')}>{label}</button>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -458,7 +458,7 @@
|
||||
background: transparent;
|
||||
color: var(--text-tertiary);
|
||||
border: 1px dashed var(--border-color);
|
||||
opacity: 0;
|
||||
opacity: 0.4;
|
||||
transition: opacity 0.1s;
|
||||
}
|
||||
.task-row:hover .task-prio.prio-none { opacity: 1; }
|
||||
@@ -529,7 +529,7 @@
|
||||
background: transparent;
|
||||
border-style: dashed;
|
||||
color: var(--text-tertiary);
|
||||
opacity: 0;
|
||||
opacity: 0.4;
|
||||
transition: opacity 0.1s;
|
||||
}
|
||||
.task-row:hover .task-due:not(.set) { opacity: 1; }
|
||||
|
||||
Reference in New Issue
Block a user