E2E tests cover:
- Drag & drop image into editor inserts image block with data URL
- Drop zone overlay appears during image drag
- Non-image file drops are correctly ignored
Design file shows three states: idle, drag-over (dashed border +
overlay label), and after-drop (image block inserted inline).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Shows all five type colors (red, yellow, green, purple, blue) with
matching dotted underlines — demonstrating the currentColor fix.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Frames showing the fixed Commit & Push behavior:
- Button enabled state with correct badge count (3 files)
- Button with no changes (badge hidden)
- Commit dialog with correct file count after save+refresh
- Success toast after commit
- Error toast when commit fails
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: Two problems caused "0 files changed":
1. loadModifiedFiles() was only called on mount, never refreshed after saves
2. Pending editor content wasn't flushed to disk before git commit
Fix:
- useEditorSave: add savePending() to flush unsaved content, onAfterSave
callback to refresh git status after Cmd+S
- useCommitFlow: new hook managing save→commit→push flow with proper
sequencing (save pending → refresh files → show dialog → commit)
- App.tsx: wire onAfterSave to loadModifiedFiles, use useCommitFlow
- git.rs: include stdout in error when stderr is empty (fixes "nothing
to commit" message being swallowed)
- mock-tauri: track saved files so get_modified_files reflects edits
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Coverage was 83.83% (below 85% threshold). Added mockito-based HTTP mock
tests for all OAuth device flow functions, list/create repo, get user,
and send_chat. Coverage now at 90.26%.
- github.rs: 55.99% → 94.85% (added mock tests for all HTTP functions)
- ai_chat.rs: 63.27% → 95.70% (added mock tests for send_chat paths)
- Added mockito = "1" as dev-dependency
- Refactored HTTP functions to accept configurable base URLs for testability
Playwright tests verify:
- Connected state shows username and disconnect button
- Login with GitHub button appears after disconnecting
- No token input field is present
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract SettingsHeader, SettingsBody, SettingsFooter, GitHubConnectedRow,
GitHubWaitingView, GitHubLoginButton, and processPollResult helper.
Code health improved from 8.64 to 9.38 (target 9.0+).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copied from ui-design.pen — includes existing Settings Panel frame.
New OAuth states (login button, waiting, connected) are reflected in
the implementation. Pencil editor not available for adding new frames.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add serialization tests for DeviceFlowStart, DeviceFlowPollResult, GitHubUser
- Add SettingsPanel tests for OAuth section: login button, connected state,
disconnect, waiting state with user code, no token field
- All 174 Rust + 475 frontend tests pass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add github_username to Settings type (Rust + TS)
- Add device flow commands: github_device_flow_start, github_device_flow_poll, github_get_user
- Replace manual token KeyField with "Login with GitHub" OAuth button
- Show connected state with username after successful OAuth
- Add disconnect functionality to clear OAuth token
- Update mock-tauri.ts with device flow mock handlers
- Update all tests for new Settings shape
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add new "Vault Module Structure" section documenting the 6 submodules,
their responsibilities, and CodeScene health scores.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pre-existing build error: vi.Mock namespace not found by tsc.
Import Mock type from vitest instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3 frames showing the dirty indicator UI states:
- NoteList: orange dot before title for modified/added notes
- TabBar: orange dot between title and close button
- StatusBar: "N pending" counter with CircleDot icon
Design decision: used accent-orange (--accent-orange) for the
indicator to differentiate from type-colored icons and provide
a warm "uncommitted changes" signal without being alarming.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
Update ARCHITECTURE.md to document react-virtuoso virtual rendering
in NoteList for large vault performance.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace require('react') with ESM imports of createElement and types
from React. This fixes the TS2591 error in tsc build for setup.ts.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 7 new tests covering virtual list behavior with large datasets:
- 9000-entry rendering without crash
- Items rendered via Virtuoso mock
- Search filtering on large dataset
- Sorting correctness with large dataset
- Section group filtering with mixed types
- Selection highlighting in virtualized list
- Click handler on virtualized items
Add design/performance-note-list.pen with 4 frames:
1. Default state — 9000+ notes with scrollbar
2. Scrolled mid-list — items 4500+
3. Search filtering — active query narrowing results
4. Empty search result — no matching notes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the direct .map() rendering in ListView with react-virtuoso's
Virtuoso component. This ensures only visible items are in the DOM,
making the list performant with 9000+ notes.
Key changes:
- ListView now uses <Virtuoso> with data prop and overscan={200}
- PinnedCard and TrashWarningBanner rendered as Virtuoso Header component
- Empty state still renders without virtualization (no items to virtualize)
- mock-tauri.ts now generates 9000 bulk entries for testing
- Test setup mocks react-virtuoso for JSDOM compatibility
Product decision: EntityView (relationship groups) is NOT virtualized
because relationship groups are typically small (<100 items). Only the
flat ListView needed virtualization since it can contain 9000+ items.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move wikilinkTarget/wikilinkDisplay from InspectorPanels.tsx to src/utils/wikilink.ts
(fixes react-refresh/only-export-components lint error — non-component exports
must live in utility files, not component files)
- Remove unused modifiedFiles from useNoteListData deps array and interface
(fixes react-hooks/exhaustive-deps warning — was in dep array but not used)