feat: note subtitle — show metadata (date + word count) (#94)

* feat: show metadata subtitle (date + word count) instead of snippet

Replace the note list subtitle with a compact metadata summary showing
relative date and word count (e.g. "2d ago · 342 words") instead of
the first paragraph of note content. Adds word_count to VaultEntry on
the Rust backend, computed during vault scan.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: cargo fmt formatting

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Luca Rossi
2026-02-26 20:50:29 +01:00
committed by GitHub
parent 1c2f0ee193
commit 4664f3360e
30 changed files with 279 additions and 21 deletions

View File

@@ -13,7 +13,7 @@ import {
type SortOption, type SortDirection, type SortConfig, type RelationshipGroup,
getSortComparator,
buildRelationshipGroups, filterEntries,
relativeDate, getDisplayDate,
formatSubtitle,
loadSortPreferences, saveSortPreferences,
} from '../utils/noteListHelpers'
@@ -29,11 +29,10 @@ interface NoteListProps {
onCreateNote: () => void
}
function PinnedCard({ entry, typeEntryMap, onClickNote, showDate }: {
function PinnedCard({ entry, typeEntryMap, onClickNote }: {
entry: VaultEntry
typeEntryMap: Record<string, VaultEntry>
onClickNote: (entry: VaultEntry, e: React.MouseEvent) => void
showDate?: boolean
}) {
const te = typeEntryMap[entry.isA ?? '']
const color = getTypeColor(entry.isA ?? '', te?.color)
@@ -44,8 +43,7 @@ function PinnedCard({ entry, typeEntryMap, onClickNote, showDate }: {
{/* eslint-disable-next-line react-hooks/static-components */}
<Icon width={16} height={16} className="absolute right-3 top-3.5" style={{ color }} data-testid="type-icon" />
<div className="pr-6 text-[14px] font-bold" style={{ color }}>{entry.title}</div>
<div className="mt-1 text-[12px] leading-[1.5] opacity-80" style={{ color, display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden' }}>{entry.snippet}</div>
{showDate && <div className="mt-1 text-[11px] opacity-60" style={{ color }}>{relativeDate(getDisplayDate(entry))}</div>}
<div className="mt-1 text-[11px] opacity-60" style={{ color }}>{formatSubtitle(entry)}</div>
</div>
)
}
@@ -120,7 +118,7 @@ function EntityView({ entity, groups, query, collapsedGroups, sortPrefs, onToggl
}) {
return (
<div className="h-full overflow-y-auto">
<PinnedCard entry={entity} typeEntryMap={typeEntryMap} onClickNote={onClickNote} showDate />
<PinnedCard entry={entity} typeEntryMap={typeEntryMap} onClickNote={onClickNote} />
{groups.length === 0
? <EmptyMessage text={query ? 'No matching items' : 'No related items'} />
: groups.map((group) => (