From c0bb2ded0ef91f4a7845d287d19b250106bee36f Mon Sep 17 00:00:00 2001 From: lucaronin Date: Sat, 21 Feb 2026 16:36:14 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20archive=20notes=20UI=20=E2=80=94=20filt?= =?UTF-8?q?er,=20sidebar=20hiding,=20relationship=20indicators?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Archive filter in sidebar with count badge - Hide archived notes from section groups and All Notes count - Exclude archived notes from sectionGroup and topic filtering - Show (archived) indicator on relationship chips and backlinks - Show ARCHIVED badge on note list items - Display 'Archive' header in NoteList when filter is active Co-Authored-By: Claude Opus 4.6 --- src/components/Inspector.tsx | 35 +++++++++++++++++++++++++---------- src/components/NoteList.tsx | 24 ++++++++++++++++++++---- src/components/Sidebar.tsx | 29 +++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/components/Inspector.tsx b/src/components/Inspector.tsx index efa3d838..6dca232a 100644 --- a/src/components/Inspector.tsx +++ b/src/components/Inspector.tsx @@ -62,18 +62,18 @@ function wikilinkTarget(ref: string): string { return pipeIdx !== -1 ? inner.slice(0, pipeIdx) : inner } -function resolveRefType(ref: string, entries: VaultEntry[]): string | undefined { +function resolveRef(ref: string, entries: VaultEntry[]): VaultEntry | undefined { const target = wikilinkTarget(ref) - const match = entries.find((e) => { + return entries.find((e) => { const stem = e.path.replace(/^.*\/Laputa\//, '').replace(/\.md$/, '') if (stem === target) return true const fileStem = e.filename.replace(/\.md$/, '') if (fileStem === target.split('/').pop()) return true return false }) - return match?.isA ?? undefined } + function RelationshipGroup({ label, refs, entries, onNavigate }: { label: string; refs: string[]; entries: VaultEntry[]; onNavigate: (target: string) => void }) { if (refs.length === 0) return null return ( @@ -81,7 +81,9 @@ function RelationshipGroup({ label, refs, entries, onNavigate }: { label: string {label}
{refs.map((ref, idx) => { - const refType = resolveRefType(ref, entries) + const resolved = resolveRef(ref, entries) + const refType = resolved?.isA ?? undefined + const isArchived = resolved?.archived ?? false const color = refType ? getTypeColor(refType) : 'var(--accent-blue)' const bgColor = refType ? getTypeLightColor(refType) : 'var(--accent-blue-light)' const TypeIcon = getTypeIcon(refType) @@ -89,11 +91,20 @@ function RelationshipGroup({ label, refs, entries, onNavigate }: { label: string ) })} @@ -175,11 +186,15 @@ function BacklinksPanel({ backlinks, onNavigate }: { backlinks: VaultEntry[]; on ) })} diff --git a/src/components/NoteList.tsx b/src/components/NoteList.tsx index 47e870ba..4fdc28e6 100644 --- a/src/components/NoteList.tsx +++ b/src/components/NoteList.tsx @@ -201,18 +201,20 @@ export function filterEntries(entries: VaultEntry[], selection: SidebarSelection case 'filter': switch (selection.filter) { case 'all': - return entries + return entries.filter((e) => !e.archived) case 'favorites': return [] + case 'archived': + return entries.filter((e) => e.archived) } break case 'sectionGroup': - return entries.filter((e) => e.isA === selection.type) + return entries.filter((e) => e.isA === selection.type && !e.archived) case 'entity': return [] case 'topic': { const topic = selection.entry - return entries.filter((e) => refsMatch(e.relatedTo, topic)) + return entries.filter((e) => refsMatch(e.relatedTo, topic) && !e.archived) } } } @@ -312,6 +314,14 @@ function NoteListInner({ entries, selection, selectedNote, allContent, modifiedF isSelected ? "font-semibold" : "font-medium" )}> {entry.title} + {entry.archived && ( + + ARCHIVED + + )}
@@ -394,7 +404,13 @@ function NoteListInner({ entries, selection, selectedNote, allContent, modifiedF {/* Header */}

- {isEntityView ? selection.entry.title : (typeDocument ? typeDocument.title : 'Notes')} + {isEntityView + ? selection.entry.title + : typeDocument + ? typeDocument.title + : selection.kind === 'filter' && (selection as { filter: string }).filter === 'archived' + ? 'Archive' + : 'Notes'}