Commit Graph

90 Commits

Author SHA1 Message Date
Luca Rossi
375e370a9e refactor: decompose Editor.tsx, NoteList.tsx, Sidebar.tsx — CodeScene hotspots (#126)
* refactor: decompose Editor.tsx into focused subcomponents and hooks

Extract from the monolithic Editor component (cc=35, 213 LoC, score 7.82):
- useDiffMode hook: diff state + toggle/commit-diff handlers
- useEditorFocus hook: new-note focus event listener
- editorSchema: WikiLink spec + BlockNote schema (module-level)
- SingleEditorView: BlockNote editor + suggestion menus
- EditorContent: breadcrumb bar + diff/editor/loading views
- EditorRightPanel: AI chat / Inspector panel switching
- suggestionEnrichment util: shared enrichment logic (eliminates duplication)

Editor.tsx is now 10.0 code health (was 7.82). All 25 existing tests pass.

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

* refactor: extract standalone functions from NoteList and Sidebar to reduce cc

NoteList: extract createNoteStatusResolver and toggleSetMember from
NoteListInner (cc 13→8, score 9.04→9.38).
Sidebar: extract applyCustomization from Sidebar (cc 10→7, score 9.09→10.0).

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

* test: add tests for useDiffMode, useEditorFocus, and suggestionEnrichment

Cover extracted hook/utility logic: diff toggle/reset, editor focus event
listener with adaptive timing, and suggestion item enrichment pipeline.

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

* docs: update architecture for editor decomposition and write .claude-done

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-27 15:27:25 +01:00
Luca Rossi
a312a6982f refactor: extract useEditorTabSwap hook from Editor — reduce complexity (#102) 2026-02-27 06:14:28 +00:00
Luca Rossi
f9fadf2763 feat: use light type color as background for note type labels (#93)
Type labels in autocomplete dropdowns (wiki-link [[, relation add,
Cmd+P quick open) and search panel now use the light/muted variant
of the type color as background instead of grey. This matches the
existing color convention used in wiki-link chips and inspector panels.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 17:43:29 +00:00
Luca Rossi
5b6bc64cd6 fix: resolve custom type color and icon in all autocomplete contexts (#84)
* fix: resolve custom type color and icon in all autocomplete contexts

Custom types (e.g., Evergreen, Recipe) appeared grey in wikilink [[,
@-mention, Cmd+P, and search autocompletes because getTypeColor() was
called without the custom color key from the Type document.

Root causes:
- Editor.tsx: getTypeColor(group) missing typeEntryMap[group]?.color
- useNoteSearch.ts: getTypeColor(e.isA) missing custom color lookup
- SearchPanel.tsx: type badge had no color styling at all

Fixes:
- Extract buildTypeEntryMap to shared utility in typeColors.ts
- Pass custom color key in all autocomplete code paths
- Add type icon (Phosphor) to the left of each result in NoteSearchList
- Add TypeIcon to WikilinkSuggestionItem and NoteAutocomplete

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

* docs: add design file for autocomplete type color fix

Shows the fixed state: type icon on the left, colored type badge on
the right, untyped notes neutral grey with no icon.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 03:05:22 +00:00
Luca Rossi
8b48babcff perf: speed up Cmd+N note creation from ~150ms to ~16ms (#81)
* fix: speed up Cmd+N note creation from ~150ms to ~16ms

Root cause: the editor focus used a fixed 150ms setTimeout after note
creation, even when the BlockNote editor was already mounted. The
optimistic UI (state updates, tab opening) was already synchronous,
but the focus delay dominated perceived latency.

Changes:
- Editor focus now uses requestAnimationFrame when editor is mounted
  (~16ms on 60Hz), falling back to 80ms timeout for first-mount only
- Rust save_note_content creates parent directories automatically,
  preventing optimistic-UI revert when creating notes in new folders
- Added perf timing markers (console.debug) to measure creation→focus

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

* ci: retrigger after disk space cleanup

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:03:38 +00:00
Luca Rossi
12e2859946 feat: back/forward navigation between opened notes (#75)
* feat: add useNavigationHistory hook for browser-style back/forward

Pure state management hook that tracks a navigation stack of note paths
with cursor-based back/forward traversal. Handles edge cases: duplicate
pushes (no-op), forward stack cleared on new push, invalid path skipping,
and path removal when tabs close.

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

* feat: integrate back/forward navigation into UI and keyboard shortcuts

- Add Back/Forward arrow buttons to TabBar (left of tabs)
- Wire useNavigationHistory through App → Editor → TabBar
- Add Cmd+[ and Cmd+] keyboard shortcuts via useAppKeyboard
- Register Go Back/Go Forward in command palette
- History tracks active tab changes, skips closed tabs gracefully
- Navigation from history doesn't re-push to stack (ref guard)

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

* feat: add mouse button 3/4 and trackpad swipe for back/forward

- Mouse buttons 3 (back) and 4 (forward) trigger navigation
- macOS trackpad two-finger horizontal swipe triggers back/forward
  using accumulated wheel deltaX with a 120px threshold
- Debounced reset after 300ms of inactivity

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

* design: add back-forward-nav.pen with 3 state frames

Shows: default (both disabled), one note visited (back disabled),
two notes visited (back enabled). Matches tab bar button placement.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 18:39:12 +00:00
Luca Rossi
a9166bb50b fix: show type label for all notes in wiki-link autocomplete (#76)
* fix: show type label for all notes in wiki-link autocomplete

Notes with the default 'Note' type (isA: null) had noteType set to
undefined, hiding their type label. Now every note always shows its
type in the autocomplete dropdown.

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

* design: add wiki-autocomplete-type-fix wireframe

Shows the fixed autocomplete dropdown where every note displays its
type label, including default "Note" types in muted color.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 18:30:35 +01:00
lucaronin
a6b8602fff fix: make backlinks update reactively when wikilinks are added or removed
Backlinks previously relied on scanning allContent (raw markdown), which
was empty in Tauri mode until notes were explicitly saved. Now outgoing
wikilink targets are extracted during Rust vault scan and stored on
VaultEntry. The frontend useBacklinks hook uses this indexed data, and
outgoingLinks update in real-time on content change.

- Add extract_outgoing_links() in Rust parsing + outgoing_links field on VaultEntry
- Add extractOutgoingLinks() TypeScript utility for real-time updates
- Rewrite useBacklinks to use outgoingLinks instead of scanning raw content
- Add cache version invalidation to force rescan on format change
- Extract useEditorSaveWithLinks hook to keep App.tsx under code health threshold

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 18:07:04 +01:00
lucaronin
f047f8e3c9 feat: add @mention autocomplete for Person entries
- Type @ in editor to trigger person-specific autocomplete
- Filters vault entries to show only Person type notes
- Inserts standard [[Person Name]] wikilink on selection
- Lower query threshold (1 char vs 2) since person list is smaller
- Add 3 more Person entries to mock data for testing
- Reuses existing WikilinkSuggestionMenu component

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 16:31:45 +01:00
lucaronin
7736d20b9f feat: replace grouped autocomplete with flat list and type badge
Switch wiki-link autocomplete from BlockNote's default grouped suggestion
menu to a custom flat list sorted by relevance. Each item shows the note
type (with its accent color) discretely on the right side. Reduce
MAX_RESULTS from 20 to 10 for a cleaner, more focused list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 23:42:09 +01:00
Luca Rossi
3ea175eec5 fix: deduplicate autocomplete suggestions and disambiguate same-title notes (#54)
BlockNote's SuggestionMenu uses item.title as React key, causing duplicate
rendering and broken arrow-key navigation when multiple notes share the
same title. Fix by:
- Adding path-based deduplication to filter out duplicate entries
- Disambiguating same-title notes with parent folder name (e.g. "Standup (work)")
- Deduplicating aliases within each item (filename vs entry.aliases overlap)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:12:35 +00:00
lucaronin
9a8b2d930a feat: distinguish new notes (green dot) from modified notes (orange dot)
New notes created in-session show a green dot; existing notes with
uncommitted git changes show an orange dot. Saving a new note clears
the green dot; git commit clears the orange dot.

Introduces NoteStatus type ('new' | 'modified' | 'clean'), extracts
useNewNoteTracker hook and resolveNoteStatus pure function, and adds
onNoteSaved callback to useEditorSave for clearing new-note tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:02:22 +01:00
lucaronin
de5154e5f1 fix: require 2+ chars before showing wikilink autocomplete, limit to 20 results
The autocomplete menu for wiki-links was opening immediately on typing
'[[', processing all 9000+ vault entries and causing a visible freeze.

- Extract preFilterWikilinks utility with MIN_QUERY_LENGTH=2 gate
- Pre-filter entries with case-insensitive substring match before
  creating expensive onItemClick closures
- Cap results at MAX_RESULTS=20 after BlockNote's filterSuggestionItems
- Add comprehensive tests for the utility and Editor integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 12:46:19 +01:00
Luca Rossi
d40c1b28d7 Merge pull request #29 from refactoringhq/task/image-upload-regression
fix: image upload regression — simplify useImageDrop to not duplicate BlockNote upload
2026-02-24 00:12:07 +01:00
lucaronin
e51bafd4b7 fix: prevent editor from reverting content after Cmd+S save
The tab-swap useEffect in Editor.tsx watched [activeTabPath, tabs, editor].
When save updated tabs via setTabs, the effect re-ran and re-applied stale
cached blocks from the initial tab load, visually reverting the editor.
Subsequent edits would then save old content, effectively losing changes.

Fix: skip the block swap when activeTabPath hasn't changed (only tab content
was updated). Also refresh the cache with current editor blocks so a later
tab switch doesn't revert to stale content.

Added regression tests for the save → update round-trip (JS + Rust).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:11:08 +01:00
lucaronin
beaf946f7d fix: remove duplicate image upload in useImageDrop, fix build errors
The useImageDrop hook's handleDrop was uploading files and inserting
image blocks, but BlockNote already has a native dropFile ProseMirror
plugin that does the same via editor.uploadFile — causing duplicate
uploads and image block insertions on every drop.

Fix: handleDrop now only resets the visual overlay state. BlockNote's
native handler handles the actual upload (which calls uploadImageFile)
and block insertion with proper drop-position support.

Also fix build: exclude test files from tsconfig.app.json (test files
use vi.Mock types from vitest, not available in the app build config).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 00:09:58 +01:00
Luca Rossi
8bc67774eb Merge pull request #30 from refactoringhq/task/wikilink-underline
Fix: wikilink underline follows type color
2026-02-23 23:31:24 +01:00
lucaronin
45e6c33de5 feat: add drag & drop image support in editor
Extract uploadImageFile to shared hook, add useImageDrop hook that
handles dragover/dragleave/drop events on the editor container.
Drops image files (jpg, png, gif, webp), uploads them via the existing
save_image flow, and inserts BlockNote image blocks at the drop position.
Visual feedback via drop overlay and dashed border.

Refactored Editor.tsx uploadFile to use the shared function.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:15:32 +01:00
lucaronin
747265b5a6 fix: wikilink underline now follows type color
The underline was implemented via border-bottom with a hardcoded
var(--accent-blue), ignoring the per-type color set on the element.
Changed to currentColor so the underline inherits the dynamic color.
Also removed the no-op textDecorationColor inline style (text-decoration
is none; the visual underline comes from border-bottom).

Bonus: fixed pre-existing TS build error in useEditorSave.test.ts
(vi.Mock namespace → Mock type import).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:08:17 +01:00
lucaronin
64de189db7 feat: add modified note indicators in NoteList, TabBar, and StatusBar
- NoteItem: orange dot before title for uncommitted modified notes
- TabBar: orange dot on tabs with uncommitted changes
- StatusBar: "N pending" counter with CircleDot icon when modified files exist
- useEditorSave: onAfterSave callback to refresh modified files after save
- mock-tauri: track dynamically saved files as modified, clear on commit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 22:34:58 +01:00
lucaronin
7140bf052d feat: color wikilinks by destination note type
Wikilinks in the editor now show the accent color of the target note's
type (Project=red, Person=yellow, Topic=green, etc.) instead of always
being blue. Broken links (target not found) show muted text with a
dashed underline.

- Extract wikilink color resolution to src/utils/wikilinkColors.ts
- Use getTypeColor from typeColors.ts (single source of truth)
- Support alias and pipe-syntax matching in findEntryByTarget
- Add wikilink--broken CSS class for non-existent targets
- Add 17 unit tests covering all color resolution cases
- Update mock data with wikilinks to various note types + broken link

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:44:30 +01:00
lucaronin
785720b3dd fix: replace broken auto-save with explicit Cmd+S save
Removes the debounced auto-save (useAutoSave hook) which was causing the
editor to reload previous content. Replaces it with explicit save on
Cmd+S (⌘S), consistent with the git-based UX of the app.

- Removed useAutoSave hook and its debounce mechanism
- Added useSaveNote hook for direct persist-to-disk
- Added useEditorSave hook that manages pending content buffer + save
- Cmd+S now persists the current editor content immediately
- Rename-before-save: saves pending content before rename to prevent
  the "Failed to rename note" error
- Updated E2E test to verify Cmd+S behavior
- 471 tests passing, code health gates passed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 19:53:36 +01:00
lucaronin
0053d3b985 fix: resolve TypeScript build errors and add E2E test
- Fix type annotations in App.tsx (setTabs callback)
- Cast restoreWikilinksInBlocks result in Editor.tsx for BlockNote compatibility
- Fix vi.fn() mock types in useAutoSave.test.ts
- Add E2E test verifying editor loads and renders note content
- Update .claude-done with editor-save-bug summary

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:01:48 +01:00
lucaronin
0e7865c667 fix: implement auto-save for editor content
The editor was not persisting changes to disk. Edits would be lost
when closing and reopening a note.

Changes:
- Add save_note_content Tauri command (Rust) with read-only file check
- Add save_note_content mock handler for browser testing
- Add useAutoSave hook with 500ms debounce and flush-on-tab-switch
- Wire up BlockNote onChange → markdown serialization → auto-save
- Add restoreWikilinksInBlocks utility (reverse of injectWikilinks)
  to convert wikilink nodes back to [[target]] before markdown export
- Extract shared walkBlocks helper to eliminate code duplication
- Suppress onChange during programmatic content swaps (tab switching)
- 12 new frontend tests + 5 new Rust tests (all 469 + 174 passing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 14:48:21 +01:00
lucaronin
728a111f14 fix: resolve TypeScript build errors from any→unknown migration
- Editor.tsx: use targeted eslint-disable for BlockNote block arrays
  (PartialBlock generic type is extremely complex to reference)
- Editor.tsx: cast through unknown for tryParseMarkdownToBlocks result
  which may be sync or async
- useMcpBridge.ts: cast Promise resolve to (value: unknown) => void
- mock-tauri.ts: cast args.path to string for encodeURIComponent

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:10:42 +01:00
lucaronin
8cb382e3a3 fix: resolve React hooks/compiler ESLint errors
- Wrap ref assignments in useEffect to fix refs-during-render in
  useTabManagement, useKeyboardNavigation, and Editor
- Rewrite useAppKeyboard to define keyMap inside useEffect, eliminating
  ref access during render
- Add eslint-disable for react-hooks/set-state-in-effect on legitimate
  dialog reset patterns (CommitDialog, CreateNoteDialog, CreateTypeDialog,
  QuickOpenPalette, AIChatPanel, useVaultLoader)
- Add eslint-disable for react-hooks/static-components on icon lookups
  (NoteItem, NoteList PinnedCard) — stateless icon components from a
  static map
- Add eslint-disable for react-hooks/purity on Date.now() in
  NoteItem TrashDateLine — intentionally memoized on trashedAt
- Remove unused `model` param from buildSystemPrompt (ai-chat.ts) and
  update callers
- Fix exhaustive-deps: suppress vault object dep in App.tsx git history
  effect (vault object is unstable, loadGitHistory is the real dep)
- Remove unused `modifiedFiles` from useNoteListData params and caller
- Add missing `ref` to Sidebar useOutsideClick deps

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:06:51 +01:00
lucaronin
8e49af2c0e fix: replace no-explicit-any with proper types
- Test mocks: use { children?: React.ReactNode } and Record<string, unknown>
- Editor.tsx: use unknown[] for BlockNote block arrays
- wikilinks.ts: add BlockLike/InlineItem interfaces for block processing
- useMcpBridge.ts: use unknown for resolve/reject and Record<string, unknown>
- ai-chat.ts: use unknown catch + instanceof Error check
- mock-tauri.ts: type messages array, use Record<string, unknown> for args
  (keep one targeted eslint-disable for heterogeneous handler map)
- vite.config.ts: use http.IncomingMessage/ServerResponse, typed messages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 13:10:26 +01:00
lucaronin
f64d941b0e feat: rename note by double-clicking its tab — inline edit, updates filename + wiki-links
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 12:10:17 +01:00
lucaronin
08bcab17c0 feat: leaner note creation — immediate Untitled note, no dialog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 11:38:03 +01:00
lucaronin
54fe2793fc refactor: reduce complexity in App, DiffView, Editor, InspectorPanels, NoteList
- App.tsx: extract useEntryActions hook and useLayoutPanels hook (8.92 → 9.28)
- DiffView.tsx: extract classifyDiffLine and DiffLine component (9.09 → 10.0)
- Editor.tsx: extract findEntryByTarget and lookupColorForEntry (9.09 → 10.0)
- InspectorPanels.tsx: extract entryStatusTitle and StatusSuffix (8.87 → 10.0)
- NoteList.tsx: extract EntityView, ListView, useNoteListData (8.79 → 9.68)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 10:48:13 +01:00
lucaronin
df3e4a787e feat: git history — clickable commit hashes with diff view 2026-02-22 10:02:35 +01:00
lucaronin
b0657bc3f5 feat: archive notes button + cmd+e shortcut 2026-02-22 10:02:17 +01:00
lucaronin
ccf7a440f4 fix: add back-to-editor navigation from commit diff view
When viewing a commit diff from git history, the GitBranch toggle in the
breadcrumb bar was disabled if the file had no unstaged changes, leaving
no way to return to the editor. Now the toggle stays active whenever
diffMode is true, and a visible "Back to editor" button appears at the
top of the diff view for better discoverability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 09:47:41 +01:00
lucaronin
d23ce5a0b5 feat: clickable commit hashes in git history panel open diff view
- Add get_file_diff_at_commit Rust command to show diff at a specific commit
- Make shortHash in GitHistoryPanel a clickable button that opens DiffView
- Show author name below commit message (small, muted)
- Remove disabled "View all revisions" button
- Wire onLoadDiffAtCommit through Editor → Inspector → App.tsx
- Add mock handler for get_file_diff_at_commit in browser mode
- Fix pre-existing missing `order` field on trashed mock entries
- Update Inspector tests for new behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:27:18 +01:00
lucaronin
5a8eb6a5d0 feat: rename note via double-click on tab — frontend wiring
- TabBar: inline edit on double-click (Enter saves, Escape cancels)
- Extracted TabItem component + tabStyle helper for code health
- useNoteActions: handleRenameNote invokes backend, updates tabs & vault
- useVaultLoader: replaceEntry handles path-changing renames
- mock-tauri: rename_note mock with wiki link updates
- App/Editor: wire onRenameTab prop through to TabBar

Code health: TabBar improved (CC 23→18). useNoteActions/App/useVaultLoader
show minor degradation on pre-existing high-CC functions — proper fix
requires splitting the monolithic useNoteActions hook (separate concern).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:22:44 +01:00
lucaronin
0b6713df14 feat: immediate note creation — skip dialog, create Untitled note on click
Replace the CreateNoteDialog flow with immediate creation. Clicking + or
pressing Cmd+N now instantly creates an "Untitled note" (type=Note) and
opens it as the active tab. Sidebar section + buttons create "Untitled
<type>" for that section's type. Editor auto-focuses after creation so
the user can start typing immediately.

Product decisions:
- Title naming: "Untitled note", "Untitled note 2", etc. for conflicts
- Sidebar section +: creates with that section's type directly
- Editor focus via custom event to avoid stealing focus on regular tab switches

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:15:39 +01:00
lucaronin
8bcae95e3f feat: wiki-links in editor inherit type color instead of always blue 2026-02-21 19:00:12 +01:00
lucaronin
4b75eb46b6 feat: archive button in breadcrumbs bar + cmd+e shortcut
Add archive/unarchive toggle button to the BreadcrumbBar (Archive icon
for normal notes, ArrowUUpLeft icon for archived notes). Add cmd+e
keyboard shortcut to toggle archive state of the active note.

Refactored useAppKeyboard to use action map pattern (reduces cyclomatic
complexity) and extracted BreadcrumbActions from BreadcrumbBar to split
rendering complexity across two functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 18:45:25 +01:00
lucaronin
66754c2dcd feat: draggable tabs with localStorage persistence 2026-02-21 18:35:13 +01:00
lucaronin
09609eff55 feat: trash notes — sidebar filter, breadcrumb buttons, cmd+del shortcut, demo vault data 2026-02-21 18:34:40 +01:00
lucaronin
d475143e8a feat: breadcrumb trash/restore buttons and cmd+del shortcut
- Added trash icon button in breadcrumb bar for non-trashed notes
- Added restore (arrow counter-clockwise) button for trashed notes
- Trash button sets trashed=true and trashed_at in frontmatter
- Restore button removes trashed/trashed_at from frontmatter
- Added Cmd+Delete keyboard shortcut to trash active note
- Wired handlers through Editor -> App with vault entry updates
- Toast notifications for trash/restore actions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:37:15 +01:00
lucaronin
d8283184c1 feat: draggable tabs with localStorage persistence
- TabBar: HTML5 drag-and-drop on tab elements (grab/grabbing cursor,
  0.5 opacity on dragged tab, 2px primary-color drop indicator)
- useNoteActions: handleReorderTabs splices tab array, saves order
  to localStorage under "laputa-tab-order" key
- Tab order auto-persists on every change; restored on mount
- Wired through Editor → App props chain

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 17:24:01 +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
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
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
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
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