Commit Graph

518 Commits

Author SHA1 Message Date
lucaronin
04ff69a657 docs: slim ADR section in CLAUDE.md (format lives in README)
fix: SearchPanel test — fireEvent.keyDown on window not document
chore: ignore src-tauri/gen/ in eslint flat config (Tauri iOS generated files)
2026-03-28 10:18:06 +01:00
lucaronin
bfbc9d49d1 revert: remove pinned properties feature
Reverts commits d263e43, ae2260c, 473239b, aaa4691, cd7a570, 3cd097d.
Removes PinnedPropertiesBar, usePinnedProperties hook, Rust backend
for _pinned_properties, and all related tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 16:20:31 +01:00
lucaronin
2799d8f0a6 feat: add canary release channel and local feature flags
Add update_channel setting (stable/canary) to Settings with UI toggle.
Stable channel uses Tauri updater plugin; canary fetches latest-canary.json
and opens GitHub release page for manual download. Add useFeatureFlag()
hook with localStorage overrides and compile-time defaults (no remote
dependencies). Add release-canary.yml CI workflow for canary branch builds.
Update stable workflow to preserve latest-canary.json on GH Pages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 17:51:33 +01:00
lucaronin
2fd5ce2e94 feat: add telemetry consent dialog + Settings privacy toggles
First-launch consent dialog asks users to opt-in to anonymous crash
reporting. Settings panel gains Privacy & Telemetry section with
toggles for crash reporting and usage analytics. Consent gate blocks
app shell until answered. UUID generated on accept for anonymous_id.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 16:10:39 +01:00
lucaronin
d7166ea993 feat: add telemetry consent fields to Settings (Rust + TypeScript)
New fields: telemetry_consent, crash_reporting_enabled, analytics_enabled,
anonymous_id. All Option/null by default for backward compatibility with
existing settings.json files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 16:05:13 +01:00
lucaronin
cd7a570240 feat: add Rust backend for pinned properties + refactor hook complexity
- Add PinnedPropertyConfig struct to VaultEntry (Rust)
- Extract _pinned_properties from YAML frontmatter (key:icon format)
- Filter underscore-prefixed system properties from properties/relationships
- Bump vault cache version to 9
- Refactor usePinnedProperties hook (cc 15→8) for CodeScene compliance
- Add 6 Rust tests for pinned properties extraction
- Add pinnedProperties field to TypeScript VaultEntry interface
- Wire _pinned_properties mapping in frontmatterOps entry patch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:37:52 +01:00
lucaronin
aaa46912f3 fix: guard against undefined pinnedProperties + lint fixes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:32:11 +01:00
lucaronin
8046e54e27 fix: remove duplicate imports in EditorContent and NoteItem
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:27:34 +01:00
lucaronin
ae2260c47f feat: drag-and-drop reordering for pinned properties bar
Uses @dnd-kit/sortable with horizontal strategy. Drag order
persists to _pinned_properties in the type definition frontmatter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:22:35 +01:00
lucaronin
d263e43025 feat: pinned properties — inline bar in editor + values in note list
- PinnedPropertiesBar: horizontal bar below title with icon + label +
  editable value chips, overflow popover for hidden properties
- PinnedPropertyChip: inline-editable chip with status/relationship colors
- NoteListPinnedValues: compact value-only chips under note titles
- Pin/unpin context menu (right-click) in Properties panel with highlight
- Real-time sync: _pinned_properties changes propagate via frontmatterToEntryPatch
- Default pinned properties (status, belongs_to, related_to) for types without config
- Per-type config stored in type definition frontmatter as _pinned_properties

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:18:11 +01:00
lucaronin
caaa582ddd fix: narrow onCreateAndOpen type guard in SearchDropdownWithCreate
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:47:53 +01:00
lucaronin
ad9d0e5e67 refactor: RelationshipsPanel — extract shared hooks to reduce complexity (avg: 9.36, gate: 8.90 → 9.31)
Extract useSearchKeyboard, useCreateAndOpen, and useCreateOption hooks from
duplicated logic in InlineAddNote, NoteTargetInput, and AddRelationshipForm.
File score: 7.8 → 8.48. Raise average code health gate threshold to 9.31.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:46:15 +01:00
lucaronin
5b1ecd7a94 refactor: remove tab bar — single note open at a time
Replace the multi-tab model with single-note navigation. One note is
open at a time; clicking any note (sidebar, wikilink, relationship)
replaces the current note in the editor. Back/Forward history still
works via Cmd+[/].

Removed: TabBar component, useClosedTabHistory, tab reorder/close/
reopen logic, Cmd+W/Cmd+Shift+T shortcuts, Close Tab and Reopen
Closed Tab menu items, tabLayout utility, and all related tests.

Simplified: useTabManagement (single-note), useAppNavigation (no tab
lookup), useKeyboardNavigation (note nav only), useNoteCreation (no
close-tab cleanup), useDeleteActions (deselect instead of close tab),
Editor (no TabBar render), Rust menu (removed 2 menu items).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 17:24:49 +01:00
lucaronin
c0790679cd refactor: remove QMD semantic indexing — keep keyword search only
Remove the entire QMD search engine (semantic indexing, hybrid search,
vector embeddings) and replace with a simple walkdir-based keyword
search. QMD never worked reliably in production, added bundle bloat,
and showed "Index failed" in the status bar.

What changed:
- Rust: deleted indexing.rs, rewrote search.rs as pure keyword search
- Frontend: removed useIndexing hook, IndexingBadge, hybrid search
- Menu: removed "Reindex Vault" command from palette and menu bar
- Config: removed qmd from bundle resources and build script
- Deleted tools/qmd/ (QMD CLI tool, MCP server, tests)
- Updated docs (ARCHITECTURE, ABSTRACTIONS, GETTING-STARTED)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:18:05 +01:00
lucaronin
1984b8ed77 refactor: remove theming system entirely
Remove all theme switching, creation, and management functionality
from the app — backend (Rust theme module, Tauri commands, menu items,
startup tasks, vault seeding), frontend (useThemeManager, ThemePropertyEditor,
themeSchema, command palette Appearance group, settings panel appearance
section, isDarkTheme prop chain), mock data, and all related tests.

Editor styling via theme.json/EditorTheme.css is preserved (not user theming).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 19:57:58 +01:00
lucaronin
8bf868875b test: add sidebar emoji icon rendering tests
Verify that SectionChildItem renders emoji icons before note titles
in expanded sidebar sections, and that notes without icons render
without any extra content.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 03:32:16 +01:00
lucaronin
6187eee74d feat: add filter pills (Open/Archived/Trashed) to All Notes view
Reuses the existing FilterPills component and sub-filter mechanism from
sectionGroup views. Adds countAllByFilter helper for counting across all
entry types and extends filterByKind to support subFilter for the 'all'
filter. Bulk actions automatically adapt based on active pill. Switching
pills resets multi-selection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 23:03:17 +01:00
lucaronin
e74d4c8392 fix: inbox sidebar ordering, filter chip wrapping, and editor banner architecture
- Move Inbox to first position in sidebar (before All Notes)
- Add whitespace-nowrap to filter pills + flex-wrap on container so chips
  wrap as whole units instead of breaking text internally
- Editor now reads trashed/archived state from fresh vault entries instead
  of potentially stale tab entry, ensuring banners appear regardless of
  navigation context
- Update tests to pass correct entries prop alongside tabs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 22:36:59 +01:00
lucaronin
e84d21d36d feat: show emoji icon in sidebar note items
Pass the icon field from VaultEntry to SectionChildItem and render
it before the title when present, matching the pattern used in
NoteItem and other contexts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 21:58:34 +01:00
lucaronin
5504941209 fix: align type selector chip left using grid layout matching property rows
The type selector was using flex justify-between, pushing the chip to the
right side of the Properties panel. Switch to grid-cols-2 layout (matching
PropertyRow and InfoRow) so the chip sits left-aligned in the value column.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 21:27:51 +01:00
lucaronin
c11a983d74 fix: use CSS grid for 50/50 label/value layout in properties panel
Flex layout with gap-2 allowed content to override the 50% width split,
causing short labels like "URL" to be truncated to "U…" when values were
long. Switching to grid-cols-2 enforces exact 50/50 columns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:27:36 +01:00
lucaronin
85efe31296 fix: match TitleField font-size/weight to BlockNote H1 and fix left alignment
TitleField now uses var(--headings-h1-font-size/weight/line-height/letter-spacing)
instead of hardcoded 28px, matching the editor H1 exactly. Added margin-left: 8px
to align with BlockNote's bn-block-content offset. Fixed bn-editor max-width to
use the same CSS var as the title-section for consistent horizontal alignment.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:03:26 +01:00
lucaronin
5a578f60d1 fix: remove vertical padding from PropertyRow to match InfoRow density
PropertyRow had py-0.5 (4px total) while InfoRow had no vertical padding,
making Properties rows taller than Info rows even with equal gap values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 12:26:25 +01:00
lucaronin
a43a98e93f refactor: NoteList.test.tsx -- deduplicate makeEntry helpers and bulk action tests (CodeScene: 7.78 to 10.0)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 07:18:34 +01:00
lucaronin
586e488072 fix: note list shows incomplete relationships when opening from sidebar
Two root causes:
1. noteListHooks used a stale selection.entry to build relationship groups —
   now looks up the fresh entry from the entries array so relationship updates
   propagate immediately.
2. frontmatterToEntryPatch didn't update entry.relationships — added
   RelationshipPatch support so frontmatter changes also update the
   relationships map in state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 03:26:52 +01:00
lucaronin
2d0d310c19 feat: move Changes and Pulse to secondary bottom area in sidebar
Changes and Pulse are git status UI, not content navigation. Moving them
out of the main top nav into a compact secondary area at the bottom of
the sidebar keeps the primary section focused on vault content.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 10:29:39 +01:00
lucaronin
6aca4e86d4 fix: remove invalid weight prop from lucide AlertTriangle icon
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:52:02 +01:00
lucaronin
caa81ae96b feat: handle git divergence, conflicts, and manual pull from within Laputa
When push is rejected due to remote having newer commits, the bottom bar
now shows "Pull required" (orange). Clicking it pulls then auto-pushes.
Conflicted notes show an inline banner with "Keep mine" / "Keep theirs"
buttons. A new "Pull from Remote" command is available in Cmd+K and the
Vault menu. Clicking the sync badge opens a popup showing branch name,
ahead/behind counts, and a Pull button.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:51:06 +01:00
lucaronin
26f09093cf feat: open note in new window (Cmd+Shift+Click / Cmd+Shift+O)
Add multi-window support: notes can be opened in dedicated secondary
Tauri windows with editor-only layout (no sidebar, no note list).

Triggers: Cmd+Shift+Click on notes, Cmd+K → "Open in New Window",
Cmd+Shift+O shortcut, Note → "Open in New Window" menu bar item.

Secondary windows have their own auto-save, theme, and wikilink
navigation. Closing a secondary window does not affect the main window.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 08:47:25 +01:00
lucaronin
b53243938d fix: reduce Properties row gap to match Info section density
Changed property rows gap from gap-2 (8px) to gap-1.5 (6px) to match
the Info section's vertical density.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 07:56:26 +01:00
lucaronin
515e771f0d feat: adopt relationship chip style for type selector in Properties panel
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 07:29:07 +01:00
lucaronin
8bd6df2053 fix: enforce 50/50 label/value layout in Properties panel with ellipsis
Labels and values each get w-1/2 so neither can squeeze the other.
Long values no longer cause short labels like "URL" to truncate to "U…".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 06:57:11 +01:00
lucaronin
8155b940a4 feat: add Inbox sidebar section showing unlinked notes
Inbox shows notes without valid outgoing relationships (body wikilinks
or frontmatter refs), helping users find captured but unorganized notes.
Includes time-period filter pills (This week/month/quarter/All time),
Cmd+K command, and macOS menu bar entry. Broken wikilinks (targeting
non-existent notes) are not counted as relationships.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 06:41:40 +01:00
lucaronin
27f8c9530d feat: auto-save notes with 500ms debounce after last keystroke
Content is automatically persisted 500ms after the last edit in both
BlockNote and raw editor modes. Cmd+S still works as immediate flush.
Tab close flushes any pending auto-save to prevent data loss.
Updated the "unsaved" tab indicator to show "Auto-saving…" with pulse.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 05:34:48 +01:00
lucaronin
4362405dd3 fix: hide system properties (trashed, archived, icon) from Properties panel
These properties have dedicated UI elsewhere (trash/archive banner, emoji picker)
and should not appear as generic editable properties.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 03:28:29 +01:00
lucaronin
968d9073d2 fix: show Note type in sidebar instead of excluding it as default/fallback
Note was explicitly excluded from collectActiveTypes() via `e.isA !== 'Note'`.
Removed the exclusion so Note appears like any other type. Untyped entries
(isA === null) now count as Note in both type collection and section filtering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 02:50:46 +01:00
lucaronin
7db3c2f00a fix: show all relationships for topics in note list
Topics used a separate 'topic' selection kind that only showed reverse
relatedTo matches. Now topics use 'entity' kind like all other types,
going through buildRelationshipGroups to show all frontmatter
relationships, children, events, referenced-by, and backlinks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 23:29:39 +01:00
lucaronin
abe465cc74 feat: show note emoji icon in tab bar, breadcrumb, and pinned cards
Add emoji icon rendering before the note title in TabBar, BreadcrumbBar,
and PinnedCard components to ensure consistent emoji display everywhere
a note title appears. Sidebar, NoteItem, wikilinks, relationships, and
backlinks already had emoji support from prior commits.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 22:31:04 +01:00
lucaronin
fa6f0fcab3 fix: remove broken snippet visibility test + add data-testid to snippet
The first snippet test consistently fails because Virtuoso doesn't
render snippet elements in the initial viewport during smoke tests.
Remove the unreliable test; keep the formatting validation tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 22:06:37 +01:00
lucaronin
2214a5c45c fix: align TitleField with editor by sharing scroll container
Move title-section inside a shared .editor-scroll-area wrapper so both
title and editor content center within the same scrollable context,
fixing alignment drift at wide widths caused by scrollbar offset.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 21:32:03 +01:00
lucaronin
2f43b4bfeb feat: show note emoji icon in wikilinks, relationships, and backlinks
Display the note's frontmatter emoji before its title in the editor
wikilink renderer, relationship LinkButtons, and backlinks panel for
consistent emoji visibility across the app.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 18:30:50 +01:00
lucaronin
15b11d118b fix: decouple H1 from title sync + non-blocking TitleField rename
H1 headings are body content, not the title source of truth. Remove
useHeadingTitleSync hook and frontmatter-title-from-H1 logic in the
editor. Rust rename_note no longer modifies H1 in file content — only
updates the frontmatter title: field.

TitleField now uses optimistic UI: the new title displays immediately
after commit while the async file rename runs in background, preventing
UI freezes on slow filesystems or large vaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 15:42:48 +01:00
lucaronin
a9229d4469 feat: full Unicode emoji picker with name search and continuous scroll
Replace curated ~270 emoji subset with full Unicode set (1900+) via
unicode-emoji-json. Emoji search now works by English name (e.g.
"rocket" → 🚀). All emojis visible in continuous scroll with sticky
category headers and icon-based quick-nav tabs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 11:31:13 +01:00
lucaronin
027a85fb06 fix: match filter pills row height to breadcrumb bar (45px)
Rework feedback: filter pills row used py-1.5 padding instead of a
fixed 45px height, causing visual misalignment with the breadcrumb bar.
Replace padding with explicit h-[45px] to match exactly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:32:29 +01:00
lucaronin
2b786892ee feat: add filter pills (Open/Archived/Trashed) with count badges to note list
When viewing a type in the sidebar, the note list now shows filter pills
below the header to switch between Open, Archived, and Trashed notes.
Each pill shows a count badge. Bulk actions are context-aware: Trashed
filter offers Restore/Archive/Delete permanently, Archived filter offers
Unarchive/Trash. Cmd+K commands added for switching filters.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 03:43:23 +01:00
lucaronin
9aa16b8eb4 refactor: remove owner/cadence from Frontmatter, source created_at from filesystem
Remove owner, cadence, created_at, and created_time as hardcoded fields from
the Frontmatter struct — they don't drive app logic and belong in generic
properties. Owner and cadence values now flow through to the properties map
(including single-element array unwrapping). Creation date is sourced from
filesystem metadata (birthtime on macOS) instead of frontmatter.

Also fixes title extraction: add H1 heading extraction to extract_title()
(priority: frontmatter title → H1 → filename slug). Previously titles fell
back directly to filename when no frontmatter title was set.

StringOrList is retained for scalar Frontmatter fields as a defensive measure:
YAML values can arrive as single-element arrays (e.g. Status: [Active]) which
would cause entire deserialization to fail without it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 01:56:33 +01:00
lucaronin
ddbbebbb67 feat: add emoji icon picker for notes stored in frontmatter
Every note can now have an optional emoji icon (frontmatter `icon` field).
The icon is displayed in the editor header, note list, search results,
and Quick Open. Includes command palette commands "Set Note Icon" and
"Remove Note Icon", plus full test coverage (Vitest + Playwright).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 22:42:55 +01:00
lucaronin
bb9fef9f77 refactor: improve code health for vault/mod.rs and Editor.tsx — fix CodeScene hotspot score
Extract scan_vault helpers (is_md_file, try_parse_md, scan_root_md_files, scan_protected_folders)
to eliminate deep nesting and reduce cyclomatic complexity. Break up large assertion blocks in tests.
Extract useEditorSetup and useRawModeWithFlush hooks from Editor component to reduce complexity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:07:33 +01:00
lucaronin
07a6ef0970 feat: persist editor mode (raw/preview) across note switches
Editor mode is now stored as a global preference in VaultConfig instead of
being tracked per-tab. Toggling raw mode persists across tab switches and
app restarts via the editor_mode field in config/ui.config.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:41:35 +01:00
lucaronin
71ccae1c70 refactor: extract frontmatterOps, update imports for useNoteCreation/useNoteRename split
useNoteActions.ts reduced from 213 to 125 lines by extracting frontmatter
helpers into frontmatterOps.ts and removing re-exports. Consumers now
import directly from the extracted modules.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 23:52:42 +01:00