Commit Graph

167 Commits

Author SHA1 Message Date
lucaronin
f4feac3b08 feat: sort notes by property in relationship subsections 2026-02-21 17:14:18 +01:00
lucaronin
c1102c508a content: add createdAt values and varied statuses to mock data
All MOCK_ENTRIES now have realistic createdAt timestamps (always before
modifiedAt). Stock Screener status changed to 'Paused' for sort-by-status
testing variety.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:12:53 +01:00
lucaronin
74649f29c5 test: add tests for sort notes functionality
Tests for getSortComparator (6 tests):
- Sort by modified date descending
- Sort by created date descending (with fallback)
- Sort by title alphabetically
- Sort by status with priority ordering
- Status sort with modified-date tiebreaker

Tests for NoteList sort controls (6 tests):
- Sort button visible in flat list header
- Sort dropdown per relationship subsection
- Sort menu opens with all options
- Sort order changes on option selection
- Menu closes after selection
- Relationship subsection sorting works

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:12:45 +01:00
lucaronin
5a8952c290 feat: sort notes by property in relationship subsections
Each relationship subsection header now has a sort dropdown control
(ArrowsDownUp icon + current sort label). Users can choose to sort by:
- Modified date (default, newest first)
- Created date (newest first)
- Title (alphabetical A-Z)
- Status (Active > Paused > Done > Finished)

The sort control also appears in the main note list header for flat
list views. Sort preferences are persisted per group in localStorage.

Also updates mock data with varied createdAt/status values for testing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:09:29 +01:00
lucaronin
01c89f3646 test: regression tests for flushSync-in-lifecycle editor bug
Add unit test verifying content blocks are applied via deferred microtask
(not synchronously in useEffect). Convert debug E2E test into a proper
regression test that checks editor content appears after clicking a note
and no flushSync errors are logged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:07:30 +01:00
lucaronin
102a7233d2 wip: initial fix attempt for editor content not appearing on first load 2026-02-21 17:04:11 +01:00
lucaronin
11db4f3527 feat: sidebar section groups collapsed by default 2026-02-21 16:47:10 +01:00
lucaronin
311c5e434b feat: archive notes — filter sidebar, hide archived, relationship indicators 2026-02-21 16:44:09 +01:00
lucaronin
07e730f172 feat: customize which type sections are shown in sidebar 2026-02-21 16:41:34 +01:00
lucaronin
4f56873201 test: add tests for sidebar section visibility customization
Tests cover:
- Customize button renders
- Popover opens with toggles for all sections
- Hiding a section removes it and its items from sidebar
- Re-showing a section restores it
- Persistence to/from localStorage
- Hidden sections don't affect top nav (All Notes, Favorites)
- Popover closes on outside click

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:38:35 +01:00
lucaronin
b73bda1aa9 feat: customize which type sections are shown in sidebar
Adds a "Customize sections" button above section groups in the sidebar.
Clicking it opens a popover with per-type toggle switches. Hidden sections
disappear from the sidebar entirely but notes remain accessible via
All Notes and search. Visibility state is persisted in localStorage.

- New useSectionVisibility hook: manages hidden sections set in localStorage
- Sidebar: "Customize sections" button + popover with toggle UI
- Outside-click closes the popover
- allSectionGroups (built-in + custom) filtered by visibility before render

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:37:00 +01:00
lucaronin
41b28a19eb fix: disable native WebKit context menu in Tauri to allow custom right-click menus 2026-02-21 16:36:45 +01:00
lucaronin
a28e4528bd fix: add archived field to all VaultEntry test fixtures
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:36:18 +01:00
lucaronin
c0bb2ded0e feat: archive notes UI — filter, sidebar hiding, relationship indicators
- 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 <noreply@anthropic.com>
2026-02-21 16:36:14 +01:00
lucaronin
4d2f96dfab feat: add archived boolean property to VaultEntry
Add archived field to both TypeScript VaultEntry interface and Rust
VaultEntry struct. Parse Archived frontmatter field in Rust backend.
Add archived mock entries (Website Redesign, Twitter Thread Experiment)
for visual testing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:36:06 +01:00
lucaronin
356797d410 feat: tag-pill UI for array properties in inspector 2026-02-21 16:29:48 +01:00
lucaronin
df6aa7241f feat: color and icon customization for sidebar type sections 2026-02-21 16:27:43 +01:00
lucaronin
23daf47353 fix: remove unused getSectionColor function (TS build fix) 2026-02-21 16:26:32 +01:00
lucaronin
527a63b3b5 feat: tag-pill UI for array properties in inspector
Replace vertical EditableList with horizontal TagPillList component.
Array property values now render as inline pill chips with hover X
to remove and a + button to add new items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 16:26:22 +01:00
lucaronin
b1e15dd5ea feat: implement icon & color customization for types
- Add TypeCustomizePopover component with color swatches (6 accent colors)
  and icon grid (35 curated Phosphor icons)
- Add right-click context menu on sidebar section group headers with
  "Customize icon & color…" option
- Sidebar renders custom icons/colors from type entry frontmatter
- NoteList uses custom icons/colors for type badges and pinned cards
- Wire up onCustomizeType in App.tsx to update type frontmatter
- Add updateEntry to useVaultLoader for instant in-memory updates
- Add --accent-orange-light CSS variable
- typeColors utility now accepts optional custom color key overrides

Product decision: Built-in types can also be customized (override their
defaults), not just custom types. The picker is a simple popover that
appears after right-click → "Customize icon & color…".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:27:33 +01:00
lucaronin
f36cfd1808 feat: add icon and color fields to VaultEntry
- Add icon (string|null) and color (string|null) to VaultEntry interface
- Update Rust VaultEntry struct and frontmatter parsing to read icon/color
- Add icon/color to SKIP_KEYS so they don't appear as relationships
- Set mock data: Recipe type → cooking-pot/orange, Book type → book-open/green
- Update all test files with the new required fields

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:23:10 +01:00
lucaronin
692bc8edc4 feat: move properties icon to toolbar when inspector panel is closed 2026-02-21 13:16:31 +01:00
lucaronin
fb31c78efd feat: move properties icon to toolbar when panel is closed
When the inspector panel is collapsed, the SlidersHorizontal icon now
appears inline with the other BreadcrumbBar toolbar icons (search, diff,
cursor, AI, more) with no visual separator. The collapsed Inspector
sidebar is no longer rendered — clicking the toolbar icon reopens it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:16:05 +01:00
lucaronin
cdf203de1a fix: use stable asset URLs for image uploads (blob URL fix) 2026-02-21 13:08:29 +01:00
lucaronin
deea70a098 fix: use stable asset URLs for image uploads instead of ephemeral blob URLs
Blob URLs are session-scoped and don't survive page reloads — images
would break on Cmd+Shift+R. Now uploadFile awaits save_image (which
persists to vault/attachments/) and returns a convertFileSrc asset URL
that the Tauri webview can resolve indefinitely.

- Editor.tsx: await save_image → convertFileSrc for Tauri mode;
  FileReader.readAsDataURL fallback for browser dev mode
- tauri.conf.json: enable assetProtocol with scope ["**"]
- mock-tauri.ts: save_image returns a plausible file path
- E2E test: expect data: URLs in browser dev mode

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 13:06:04 +01:00
lucaronin
6f35a5ea26 content: add array properties to mock data for tag-pill testing
Added non-wikilink array properties (tags, tools, domains) to mock
frontmatter content so the upcoming tag-pill UI has realistic test data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 12:17:51 +01:00
lucaronin
722d57843a feat: keyboard navigation between tabs and notes 2026-02-21 12:13:05 +01:00
lucaronin
1697c00cf5 feat: show Laputa vault only in native Tauri mode, remove Demo vault 2026-02-21 11:07:47 +01:00
lucaronin
e02db50533 fix: use blob URLs for image uploads instead of data URLs
The uploadFile callback was converting images to data URLs via FileReader,
which caused images to get stuck on "Loading..." in the editor. Switched
to URL.createObjectURL() which returns a lightweight blob URL immediately.
The Tauri vault-save path is now fully fire-and-forget so it never blocks
the URL return.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 11:00:41 +01:00
lucaronin
827ec42d6c feat: add keyboard navigation between tabs and notes
- Tab navigation: Cmd+Option+Left/Right (Tauri), Cmd+Shift+Left/Right (browser)
- Note list navigation: Cmd+Option+Up/Down moves through visible notes
- Navigating notes replaces the current tab content (no new tab opened)
- Wraps around at list boundaries
- New useKeyboardNavigation hook detects Tauri vs browser environment
- Extracted loadNoteContent and replaceTabWithEntry helpers to reduce
  complexity in useNoteActions
- Exported filterEntries, sortByModified, buildRelationshipGroups from
  NoteList for reuse in keyboard navigation

Note: useNoteActions (30→31 CC) and App (143→153 LOC) show minimal
degradation on pre-existing code health issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 10:50:50 +01:00
lucaronin
5f2a6495db feat: AI chat panel 2026-02-21 10:38:41 +01:00
lucaronin
4b843f94f6 feat: Allow to create new types 2026-02-21 10:32:36 +01:00
lucaronin
db1da4430e fix: wire up BlockNote uploadFile to enable image uploads in editor
The editor's useCreateBlockNote was missing the uploadFile callback,
so BlockNote had no handler for image uploads (drag-drop, paste, or
toolbar button). Images now convert to data URLs for immediate display.

In Tauri mode, uploaded images are also persisted to the vault's
attachments/ directory via a new save_image backend command.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 10:07:02 +01:00
lucaronin
5ec9af98c5 test: add tests for create type dialog and dynamic sidebar sections
- CreateTypeDialog: 8 tests covering open/close, validation, submit, cancel
- Sidebar dynamic sections: 5 tests covering custom type rendering,
  instance display, + button behavior, and built-in type deduplication

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:42:45 +01:00
lucaronin
170de2a7e0 feat: implement create new type feature
Core implementation:
- CreateTypeDialog: simple dialog with name field for creating new types
- handleCreateType in useNoteActions: creates Type documents in type/ folder
- Dynamic sidebar sections: custom types (Recipe, Book, etc.) appear as new
  sidebar sections after built-in ones, each with a + button for instances
- Updated CreateNoteDialog: accepts custom types, shows them with blue accent
- handleCreateNote now supports custom types (folder = lowercased type name)

Product decisions:
- The + on Types section opens CreateTypeDialog (not CreateNoteDialog)
- Custom type sections use FileText icon and blue accent color by default
- Section labels are pluralized (e.g., "Recipes", "Books")

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:41:46 +01:00
lucaronin
4e4cffe6a3 fix: ensure editor has full width regardless of title/content length
The BlockNote editor container (.bn-container) had no explicit width,
so it sized based on content. With short or empty document titles,
the editor collapsed to a very small width.

Fix: set width: 100% on .bn-container and .bn-editor so the editor
always fills available space. Added margin: 0 auto on .bn-editor to
keep the 760px text column centered.

Also adds an E2E test verifying editor width stays above 300px.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:39:37 +01:00
lucaronin
e739ae0028 feat: add custom type mock data (Recipe, Book) with instances
Add mock data for two user-created types (Recipe, Book) plus example
instances (Pasta Carbonara, Designing Data-Intensive Applications).
This enables testing the create-new-types feature in the browser.

Also fix pre-existing test: Sidebar.test expected 7 section groups
but there are 8 (Types was added but test count wasn't updated).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:38:55 +01:00
lucaronin
388160998f Merge task/create-from-sidebar: Create new items from sidebar 2026-02-21 09:17:30 +01:00
lucaronin
f0c5461fba test: add tests for sidebar + button create-from-type feature
- Test that + buttons render for all 7 section groups
- Test that clicking + calls onCreateType with correct type
- Test that + buttons are hidden when callback not provided

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:50:12 +01:00
lucaronin
89e5a2eb79 feat: add + button to sidebar section groups for quick note creation
Each sidebar section header (Projects, People, Topics, etc.) now shows
a + button on hover. Clicking it opens the CreateNoteDialog pre-filled
with that section's type, so users can quickly create new items without
manually selecting the type.

- Add defaultType prop to CreateNoteDialog for pre-selecting type
- Add onCreateType callback to Sidebar with hover-visible + button
- Wire up in App.tsx with unified openCreateDialog handler

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:49:30 +01:00
lucaronin
6fd145702e fix: resolve pre-existing TypeScript build errors
- Accept string | null in typeColors functions (matches VaultEntry.isA type)
- Add missing snippet/relationships fields to test mock entries
- Remove unused imports (AIChatPanel in App, cn in Editor)
- Fix Promise type cast in Editor.tsx tryParseMarkdownToBlocks
- Fix null coalescing in Inspector resolveRefType return
- Remove unused container variable in NoteList test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:49:22 +01:00
lucaronin
53558c2cbe fix(notelist): exclude Type from relationship groups
Type is a special relationship handled separately by the sidebar,
so it should not appear as one of the generic relationship groups
in the note list entity view. Added case-insensitive filter to
exclude the "type" key from the otherKeys loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:43:39 +01:00
lucaronin
bca6b3c8e8 docs: AI chat architecture + fix pre-existing build errors
Update docs/ARCHITECTURE.md with:
- AI Chat system architecture (context picker, streaming, MCP)
- WebSocket bridge protocol
- New files listing and data flow diagrams
- Updated tech stack table

Update mock-tauri.ts with richer AI chat mock responses
(context-aware summarize, expand, grammar responses).

Fix pre-existing TypeScript build errors:
- Add missing snippet/relationships to test VaultEntry fixtures
- Fix string|null → string type mismatches in Sidebar, NoteList, Inspector
- Remove unused imports (cn in Editor, AIChatPanel in App)
- Fix tryParseMarkdownToBlocks Promise cast

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 23:07:10 +01:00
lucaronin
7d235d723f feat(ai-chat): WebSocket bridge for MCP vault ops
Add WebSocket bridge connecting MCP server tools to the frontend:
- mcp-server/ws-bridge.js: WebSocket server exposing vault tools
  (read_note, create_note, search_notes, append_to_note)
- src/hooks/useMcpBridge.ts: React hook for typed tool invocations
  with lazy connection, request/response correlation, timeouts
- Vite MCP bridge info endpoint (/api/mcp/info)

Protocol: client sends {id, tool, args}, server responds {id, result}
Default port: 9710 (configurable via WS_PORT env var)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:59:00 +01:00
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
2286385244 fix: resolve TypeScript build errors across components
Fix null-safety issues (string | null → string), add missing VaultEntry
fields in test fixtures, remove unused imports, and fix type assertion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:02:04 +01:00
lucaronin
9a2f7f0370 feat(inspector): make Type property a clickable navigation chip
The Type field in the Inspector's properties panel is now a colored
clickable chip (styled like relationship chips) that navigates to the
type document when clicked. The "Type" key is also excluded from the
relationships panel to avoid duplication.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:49:55 +01:00
lucaronin
d0370731a6 feat(notelist): add Instances group for type documents in entity view
When viewing a type document (e.g., type/project.md) in entity view,
show an "Instances" relationship group listing all entries of that
type. For example, the Project type document shows all projects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:48:15 +01:00
lucaronin
05c840d6cf feat(notelist): pin type document at top in section group view
When viewing a section group (e.g., Projects), the corresponding type
document (type/project.md) is now pinned at the top of the NoteList
as a prominent card. Clicking it navigates to the type document.
Instances of that type are listed below.

This makes the type document the entry point for each category,
reinforcing the "types are files" mental model.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 21:47:42 +01:00