Commit Graph

117 Commits

Author SHA1 Message Date
lucaronin
261d2f986c feat(ai-chat): Rust ai_chat command
Add Tauri command for AI chat via reqwest:
- ai_chat module with send_chat() using Anthropic Messages API
- ANTHROPIC_API_KEY from environment variable
- Proper error handling for missing key, API errors, parse failures
- Unit tests for request building and response extraction
- Mock handler added to mock-tauri.ts for browser testing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:55:49 +01:00
lucaronin
f4ca64f229 feat(ai-chat): context picker + Anthropic API
Rewrite AIChatPanel with:
- Context picker: current note auto-added, search to add more notes,
  removable context pills, token estimation badge
- Real Anthropic API integration via Vite dev server proxy (SSE streaming)
- API key stored in localStorage, configurable via dialog
- Model selector: Haiku 3.5, Sonnet 4, Opus 4
- Mock fallback when no API key is configured
- Extracted useAIChat hook and ai-chat utilities for clean separation

Decision: Using Vite middleware proxy for dev mode to avoid CORS issues
with direct browser-to-Anthropic calls. Phase 2 will add Rust backend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:52:56 +01:00
lucaronin
238edaa6a9 refactor: extract useAppKeyboard hook from App.tsx
Moves global keyboard shortcut handling into a dedicated hook.
App.tsx now scores 10.0 code health.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:59:05 +01:00
lucaronin
1050a10403 refactor: extract BreadcrumbBar component from Editor.tsx
Moves breadcrumb bar with action icons into a dedicated memoized
component. Editor.tsx now scores 10.0 code health.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:58:14 +01:00
lucaronin
647421b3a7 refactor: extract TabBar component from Editor.tsx
Reduces Editor component LoC by ~80 lines and lowers cyclomatic
complexity. TabBar is now a memoized presentational component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:57:03 +01:00
lucaronin
399b8b58a0 feat: add mock AI chat panel
Replaces Inspector panel when activated via Sparkle button in editor
info bar. Includes context pills, message list with typing indicator,
quick action pills (Summarize/Expand/Fix grammar), model selector,
and mock responses with 1200ms delay. E2E test covers full flow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 16:06:51 +01:00
lucaronin
663f7b199b feat: add vault API middleware for browser testing with real vault files
Add a Vite dev server middleware plugin that serves vault data over HTTP,
allowing the browser version of the app to read real markdown files instead
of hardcoded mock data. The mock layer now checks for API availability at
load time and falls back to hardcoded data when the API is unavailable.

- GET /api/vault/ping — health check
- GET /api/vault/list?path=<dir> — scan dir, parse frontmatter → VaultEntry[]
- GET /api/vault/content?path=<file> — raw file content
- GET /api/vault/all-content?path=<dir> — all .md files content map
- gray-matter added as dev dependency for frontmatter parsing
- useVaultLoader now passes vaultPath to mock invoke calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:39:45 +01:00
lucaronin
0053eb3009 feat: UI polish — typography, layout, and sidebar fixes
- font-mono-label: font-weight 500, remove letter-spacing
- NoteList: move timestamp below snippet in note items
- Sidebar: add border-r with sidebar-border color
- ResizeHandle: overlap sidebar border with -ml-1 (no visible gap)
- Sidebar items: text-muted-foreground for inactive group items
- NoteList: uniform 14px vertical padding across all note items
- NoteList header: fixed height 45px to match tab bar
2026-02-18 10:52:01 +01:00
lucaronin
b4d6dc8d55 feat: remove redundant RELATIONSHIPS heading from Inspector
The relationship groups (BELONGS_TO, RELATED_TO, etc.) are self-evident;
an extra section heading was visual clutter. Removed from both the active
Inspector and EmptyInspector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 22:48:20 +01:00
lucaronin
6643b8db8f feat: remove duplicate PROPERTIES section heading from Inspector
The panel title already says "Properties" — the section heading was
redundant. Removed from both DynamicPropertiesPanel and EmptyInspector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 22:47:49 +01:00
lucaronin
3f006a5726 feat: set Inspector label font-weight to 400 and reduce letter-spacing
The .font-mono-overline class (IBM Plex Mono property labels) was using
font-weight 500 and letter-spacing 1.5px. Changed to 400 (regular) and
0.02em per design spec.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 22:47:19 +01:00
lucaronin
c68b60c207 feat: color-code Inspector relationship items with type icons
Relationship and backlink items now use getTypeColor/getTypeLightColor
for text and background colors based on the linked note's type. Text
type labels replaced with Phosphor icons matching the NoteList/Sidebar
icon mapping (Wrench=Project, Tag=Topic, Users=Person, etc.).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:59:15 +01:00
lucaronin
6c63abc9c5 feat: reduce font weight of sidebar entity items to 400
Section group headers and nav items stay at font-weight 500 (medium).
Individual entity items under sections now use font-weight 400 (normal)
to create better visual hierarchy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:57:31 +01:00
lucaronin
45a6d8800a feat: move timestamp below title in NoteList items
Title now takes full width on top, with timestamp displayed below
in 10px muted text, followed by the snippet. Applies to both flat
list and context view items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:56:41 +01:00
lucaronin
f30733932a feat: apply IBM Plex Mono to labels per design spec
Update NoteList group headers (RELATED NOTES, EVENTS, etc.) to use
font-mono-label class with bg-muted background bar per design.

Update Inspector section titles (Properties, Relationships, Backlinks,
History) and property labels (Type, Status, Modified, Words) to use
font-mono-overline class. Update status badge to IBM Plex Mono with
border-radius 16px per design spec.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:41:15 +01:00
lucaronin
c6265cf888 feat: add Inter font import and IBM Plex Mono CSS utility classes
Add Inter to Google Fonts import alongside IBM Plex Mono. Update root
font-family to use Inter as primary. Add .font-mono-label (11px/600/ls1.2)
and .font-mono-overline (10px/500/ls1.5) utility classes per design spec.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:41:08 +01:00
lucaronin
2c4808851f fix: remove unused constants and fix BACKLINKS_KEY reference
Removes unused GROUP_PRIORITY and BACKLINKS_KEY constants, replaces
the reference with a string literal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:17:03 +01:00
lucaronin
63768d0a6b fix: handle wikilink aliases in resolveRefs and refsMatch
Strips the |display-text alias from wikilinks before matching (e.g.
[[essay/foo|Foo]] now correctly resolves to essay/foo.md). This was
preventing the Has, Topics, and other relationship groups from resolving
entries whose wikilink references included aliases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:16:19 +01:00
lucaronin
7da76688d2 feat: use generic relationships map in NoteList context view
Updates buildRelationshipGroups to use the new relationships map from
VaultEntry instead of only belongsTo/relatedTo. Now shows Has, Topics,
and all other wikilink-containing frontmatter fields as groups. Group
order: Has, Children, Events, Topics, other fields alphabetically,
Referenced By, Backlinks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:11:01 +01:00
lucaronin
06e6964da3 feat: add relationships field to TypeScript VaultEntry and mock data
Adds `relationships: Record<string, string[]>` to the VaultEntry
interface. Updates mock data with realistic relationship fields (Has,
Topics, Owner, Notes) and adds essay mock entries for testing the
context view.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:08:42 +01:00
lucaronin
f0a8f7d014 feat: implement context view in NoteList
When a note is selected from the sidebar (entity selection), NoteList
now shows a context view instead of a flat list:

- Prominent top card with type-colored background, bold title, snippet,
  timestamp, and type icon
- Grouped relationship sections (Children, Events, Referenced By,
  Belongs To, Related To, Backlinks) with collapse/expand chevrons
- Backlinks detected by scanning allContent for wikilink references
- Groups show ALL-CAPS headers with count and CaretDown/CaretRight toggle
- Normal flat list shown when sidebar selection is "All Notes"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:47:38 +01:00
lucaronin
484f0672b0 feat: add type icons to NoteList items
Add a small (14px) Phosphor icon in the top-right corner of each note
item, colored by type using getTypeColor(). Uses the same icon mapping
as Sidebar: Wrench=Project, Flask=Experiment, Target=Responsibility,
ArrowsClockwise=Procedure, Users=Person, CalendarBlank=Event,
Tag=Topic, FileText=Note (default).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:45:34 +01:00
lucaronin
1c0bb2a71c feat: remove type filter pills from NoteList
Remove the filter pills row ("All 12", "Projects 1", etc.) and all
associated filtering logic (typeFilter state, typeCounts memo, displayed
memo, TYPE_PILLS constant). The note list now always shows all notes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:44:03 +01:00
lucaronin
2eb0705f00 feat: show type label on relationship items in Inspector
Each related note in the Relationships section now displays the note
title on the left and the type label on the right.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:21:20 +01:00
lucaronin
3939ba1e97 feat: increase Inspector section spacing to 16px with flex gap
Replace individual mb-4 margins with a flex column gap-4 on the
container, ensuring consistent 16px spacing between Inspector sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:20:26 +01:00
lucaronin
444dd03ca6 refactor: use shared getTypeColor utility in Sidebar
Replace inline color strings in SECTION_GROUPS and the string-replace
hack for light colors with the shared typeColors utility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:18:41 +01:00
lucaronin
0f49886f4e feat: use dynamic type colors for active filter pills
Active filter pills now show the accent color matching the type they
represent, instead of hardcoded blue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:17:50 +01:00
lucaronin
ebc77002d2 feat: use dynamic type colors for selected note in NoteList
The selected note's border-left and background now reflect the note's
type color instead of hardcoded blue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:17:21 +01:00
lucaronin
952d8afd05 feat: add shared type color utility for note type→color mapping
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:16:47 +01:00
lucaronin
02ff193988 fix: handle sync return from tryParseMarkdownToBlocks
The method returns blocks directly (not a Promise) in the current
BlockNote version, causing 'then is not a function' error.
2026-02-17 18:04:18 +01:00
lucaronin
408e23f572 fix: use prosemirrorView check for editor mount and simplify content swap 2026-02-17 18:00:18 +01:00
lucaronin
91659ad56b fix: editor content not displaying after single-instance refactor
The single BlockNote editor instance was calling replaceBlocks before the
editor was mounted in the DOM, causing content swaps to silently fail.
Now tracks mount state via editor.onMount() and defers content swaps
until the editor is ready. Also guards against stale async parses when
the user switches tabs before markdown parsing completes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:56:57 +01:00
lucaronin
b239de3719 fix: prevent crash when opening notes
Move setActiveTabPath after tab content is loaded to prevent Editor's
useEffect from firing before the tab exists in the tabs array. Add
try/catch around editor.replaceBlocks for defensive error handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:52:10 +01:00
lucaronin
829cd2ad95 feat: add vault switcher in status bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:45:31 +01:00
lucaronin
2f59d1d6c8 perf: single editor instance with document swapping
Replace per-tab BlockNote instances with one shared editor that swaps
content via replaceBlocks(). Cached blocks per tab path make subsequent
switches instant — only first open parses markdown. Cache entries are
cleaned up when tabs close.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:38:57 +01:00
lucaronin
0714184e3c perf: keep tab editors mounted for instant switching (Obsidian pattern)
Instead of unmounting/remounting BlockNoteTab on every tab switch
(via key={activeTabPath}), render all open tabs simultaneously and
toggle visibility with CSS display:none/block. This eliminates
editor recreation and markdown re-parsing on switch. Also adds a
loading skeleton for new tabs and uses a ref for tabs to avoid
stale closures in handleSelectNote.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:32:57 +01:00
lucaronin
b74771aa8f perf: fix resize jank with RAF throttle and React.memo on Sidebar
Add requestAnimationFrame throttling to ResizeHandle so mouse move
events are batched per frame instead of triggering setState on every
pixel. Wrap Sidebar in React.memo so it skips re-rendering when only
the parent wrapper div width changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:14:50 +01:00
lucaronin
2f6bc97cf5 perf: memoize Editor component and wikilink suggestion items
Wrap Editor in React.memo to prevent re-renders from parent width
changes. Memoize the base wikilink items array with useMemo so it
only recomputes when entries change, not on every keystroke.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:14:43 +01:00
lucaronin
60f2a545f1 perf: virtualize NoteList with react-virtuoso and add useMemo
Replace plain .map() rendering with Virtuoso for virtual scrolling of
9000+ notes. Add useMemo to all filtering/sorting chains (filtered,
sorted, searched, typeCounts, displayed). Use entry.snippet directly
instead of computing snippets from allContent. Wrap NoteList in
React.memo to prevent unnecessary re-renders.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:14:36 +01:00
lucaronin
f613335f97 feat: add snippet field to frontend types and mock data
Add snippet: string to VaultEntry TypeScript interface to match the
Rust backend. Update mock data with snippets for all entries. Add
.laputa-cache.json to .gitignore.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:14:29 +01:00
lucaronin
1f8740e4af feat: add native macOS title bar with transparent overlay
- Use titleBarStyle: Transparent for native window frame on top
- Add paddingTop: 38px to Sidebar to make room for title bar
- Keep solution simple: native traffic lights + dragging work out-of-the-box
- Removed custom traffic lights and drag handlers
2026-02-17 16:55:23 +01:00
lucaronin
517148f2a6 feat: replace sidebar header with native macOS title bar (38px) 2026-02-17 16:39:23 +01:00
lucaronin
348b028e2a fix: use dynamic color-coding for active note states based on type 2026-02-17 14:24:13 +01:00
lucaronin
a7b6726964 feat: update sidebar colors and spacing - accent colors, increased gaps 2026-02-17 14:12:56 +01:00
lucaronin
0b3d190644 feat: sidebar redesign - chevron right, remove section badges, align groups 2026-02-17 13:47:48 +01:00
lucaronin
5c7c06705f feat: update Sidebar to match design - traffic lights, wrench icon, proper indentation 2026-02-17 13:45:09 +01:00
lucaronin
f9d9bdabf7 refactor: decompose Inspector.tsx into EditableValue, DynamicPropertiesPanel, and frontmatter utils 2026-02-17 12:12:32 +01:00
lucaronin
47deb6f3b7 refactor: extract useVaultLoader and useNoteActions hooks from App.tsx 2026-02-17 12:10:21 +01:00
lucaronin
e805970c17 refactor: extract wikilink utils and DiffView from Editor.tsx 2026-02-17 12:08:03 +01:00
lucaronin
27e1d71488 refactor: extract DiffView into its own file from Editor.tsx 2026-02-17 12:07:23 +01:00