diff --git a/src/lib/components/AppLayout.svelte b/src/lib/components/AppLayout.svelte index d81093e..9a5a8dd 100644 --- a/src/lib/components/AppLayout.svelte +++ b/src/lib/components/AppLayout.svelte @@ -39,6 +39,7 @@ rootNoteCount, viewMode, sortMode, + groupNotesByDate, tasksLayout, tasksHideCompleted, tasksOnlyFlagged, @@ -210,6 +211,7 @@ notebook_order: $notebookOrder, note_order: $noteOrder, sort_mode: $sortMode, + group_notes_by_date: $groupNotesByDate, last_view_mode: $viewMode, last_notebook: $activeNotebook?.relative_path ?? null, last_tag: $activeTag, @@ -553,6 +555,7 @@ $effect(() => { $sortMode; + $groupNotesByDate; $tasksLayout; $tasksHideCompleted; $tasksOnlyFlagged; @@ -584,6 +587,7 @@ $notebookOrder = state.notebook_order ?? {}; $noteOrder = state.note_order ?? {}; if (state.sort_mode === 'created' || state.sort_mode === 'title' || state.sort_mode === 'modified' || state.sort_mode === 'custom') $sortMode = state.sort_mode; + if (typeof state.group_notes_by_date === 'boolean') $groupNotesByDate = state.group_notes_by_date; 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; diff --git a/src/lib/components/NoteList.svelte b/src/lib/components/NoteList.svelte index 5dbc2a8..69ffa7f 100644 --- a/src/lib/components/NoteList.svelte +++ b/src/lib/components/NoteList.svelte @@ -9,6 +9,7 @@ activeNotebook, activeTag, sortMode, + groupNotesByDate, editorDirty, quickAccessPaths, appConfig, @@ -37,7 +38,7 @@ getAllTags, createDailyNote } from '$lib/api'; - import { formatRelativeTime, formatDate } from '$lib/utils/time'; + import { formatRelativeTime, formatDate, dateBucketLabel } from '$lib/utils/time'; import { openNoteWindow } from '$lib/utils/window'; import { revealItemInDir } from '@tauri-apps/plugin-opener'; import type { NoteEntry, TrashNotebookEntry, SortMode, TaskItem } from '$lib/types'; @@ -212,6 +213,24 @@ const customOrderViews = new Set(['all', 'notebook', 'tag']); let canCustomReorder = $derived($sortMode === 'custom' && customOrderViews.has($viewMode)); + // Relative-date grouping (All Notes + date sorts only). Pinned notes form their own leading group. + let groupingActive = $derived($groupNotesByDate && $viewMode === 'all' && ($sortMode === 'created' || $sortMode === 'modified')); + let noteGroups = $derived.by(() => { + if (!groupingActive) return [] as { label: string; notes: NoteEntry[] }[]; + const pinned: NoteEntry[] = []; + const rest: NoteEntry[] = []; + for (const n of $sortedNotes) (n.meta.pinned ? pinned : rest).push(n); + const groups: { label: string; notes: NoteEntry[] }[] = []; + if (pinned.length) groups.push({ label: 'Pinned', notes: pinned }); + let cur: { label: string; notes: NoteEntry[] } | null = null; + for (const n of rest) { + const label = dateBucketLabel($sortMode === 'created' ? n.meta.created : n.meta.modified); + if (!cur || cur.label !== label) { cur = { label, notes: [] }; groups.push(cur); } + cur.notes.push(n); + } + return groups; + }); + // Virtual scroll let listContainer = $state(null!); let scrollTop = $state(0); @@ -955,6 +974,13 @@ + {#if $viewMode === 'all' && ($sortMode === 'created' || $sortMode === 'modified')} + + {/if} {#if $viewMode !== 'trash'}