Skip to content

feat: add drag-and-drop text file support to create notes on branch cards#108

Merged
wesbillman merged 4 commits intomainfrom
matt2e/drag-note
Feb 13, 2026
Merged

feat: add drag-and-drop text file support to create notes on branch cards#108
wesbillman merged 4 commits intomainfrom
matt2e/drag-note

Conversation

@matt2e
Copy link
Copy Markdown
Contributor

@matt2e matt2e commented Feb 13, 2026

Add the ability to drag and drop text files (e.g. .txt, .md) from the OS file manager onto branch cards to create notes from their contents.

Changes

  • Tauri backend (lib.rs): Add read_text_file command so the frontend can read dropped file contents.
  • Commands (commands.ts): Expose readTextFile binding to the new Tauri command.
  • Drag-drop service (dragDrop.ts): New shared module that registers a single global Tauri onDragDropEvent listener and dispatches to the correct branch card via hit-testing. Subscribers register/unregister as cards mount/unmount.
  • BranchCard (BranchCard.svelte): Subscribe to drag-drop events, filter for text file extensions, show placeholder timeline items while notes are being created asynchronously, and refresh the timeline on completion. Avoids UI freezes by skipping the loading spinner on subsequent timeline refreshes.
  • BranchTimeline (BranchTimeline.svelte): Accept and render pendingDropNotes placeholder items with an "adding..." indicator.

…ards

Drop .txt, .md, or other text files onto a branch card to automatically
create notes from their contents. The file name (without extension) becomes
the note title and the file content becomes the note body.

Changes:
- Add create_note Tauri command for standalone note creation (no session)
- Add createNote wrapper in commands.ts
- Add drag-and-drop event handlers on BranchCard with visual feedback
Tauri v2 intercepts file drops at the OS level, preventing standard
browser drag/drop events (ondragenter, ondragover, ondrop) from firing
for files dragged from Finder/Explorer into the webview.

Replace browser drag event handlers with Tauri's onDragDropEvent API:
- Use getCurrentWebview().onDragDropEvent() which provides file paths
  and physical screen position for each drag phase
- Hit-test the physical position against each BranchCard's bounding
  rect (converting physical pixels to logical via devicePixelRatio)
  to determine which card is being targeted
- Add read_text_file Rust command since Tauri drag-drop gives file
  paths rather than File objects, requiring server-side file reading
- Add readTextFile wrapper in commands.ts
- Preserve visual drag-over feedback and note creation on drop
Two issues fixed:

1. Branch detection: Remove devicePixelRatio division from hit-testing.
   Tauri on macOS provides logical coordinates that already match
   getBoundingClientRect(), so dividing by DPR caused only the first
   branch card to be targetable.

2. UI freeze on drop: Make handleFileDrop synchronous (non-async) so it
   returns immediately after setting up placeholders. File reading and
   note creation run via Promise.all in the background. Each pending
   file shows a 'generating-note' spinner row in the BranchTimeline
   that disappears as each note is created, then the full timeline
   reloads once all files are processed.
Three changes to fix the freezes that occurred after dropping files:

1. Shared drag-drop service (dragDrop.ts): Replace per-BranchCard
   onDragDropEvent listeners with a single global Tauri listener that
   dispatches via hit-testing. Previously, N branch cards meant N
   duplicate global listeners all firing on every drag-over event
   (~60fps), each doing getBoundingClientRect + reactive state updates.

2. Non-destructive timeline refresh: loadTimeline() no longer sets
   loading=true on subsequent calls, so the existing timeline stays
   visible during reload instead of being replaced by a spinner that
   triggers a full re-render flash.

3. Proper untrack usage: The $effect that subscribes to drag-drop
   uses untrack() to avoid Svelte tracking dragOver state inside the
   callback, which could cause the effect to re-run and re-register
   the subscription.
@wesbillman wesbillman merged commit d477efb into main Feb 13, 2026
3 checks passed
@wesbillman wesbillman deleted the matt2e/drag-note branch February 13, 2026 22:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants