Skip to content

Add attachment upload: drop, paste, picker with progress - #8

Merged
unforced merged 1 commit into
mainfrom
attachment-upload
Apr 18, 2026
Merged

Add attachment upload: drop, paste, picker with progress#8
unforced merged 1 commit into
mainfrom
attachment-upload

Conversation

@unforced

Copy link
Copy Markdown
Contributor

Summary

  • Drag-drop, paste-from-clipboard, and a picker button upload files to the vault storage endpoint; markdown (![alt](url) for images, [filename](url) otherwise) is inserted at the cursor on success
  • /notes/:id/edit links attachments immediately; /new stages uploads and links them after the note is created (no orphan blobs if the draft is cancelled)
  • XHR-backed uploads so we can show per-file progress + cancel mid-flight; AbortController wired through useAttachmentUploader
  • Inline images in preview go through VaultImage, which blob-fetches past the auth-gated storage endpoint
  • Client-side size cap 100 MB + extension allowlist (wav/mp3/m4a/ogg/webm/png/jpg/jpeg/gif/webp) — rejected with a toast before any network call; PDF + mp4 tracked in parachute-vault#127

Sequencing

Attachment sidebar is read-only this PR. Remove button is sequenced to PR #8.5, after the vault-side DELETE /api/notes/:id/attachments/:attId endpoint lands.

Test plan

  • bun run lint — clean
  • bun run typecheck — clean
  • bun run test — 100/100 pass (14 files), including:
    • client.test.ts: uploadStorageFile multipart + Bearer + progress; 401 → VaultAuthError; 413 → VaultUploadError; abort → AbortError; linkAttachment POST + 401
    • NoteNew.test.tsx: drop → upload → insert + stage; paste-image; oversized-file rejected; happy-path drop → stage → create → link
    • NoteEditor.test.tsx: drop → upload → insert + immediate link; oversized-file rejected
  • bun run build — green (1.18 MB gzip 381 KB; bundle-split follow-up already filed)
  • Smoke in dev server against live vault (deferred — needs running vault, not available in this environment)

🤖 Generated with Claude Code

… on /new

Drag & drop, paste-from-clipboard, and a picker button upload files to the
vault storage endpoint, then insert the right markdown (![alt](url) for
images, [filename](url) otherwise). On /notes/:id/edit attachments link to
the note immediately; on /new they stage and link after create to avoid
orphan storage blobs on cancel. XHR backs the upload so we can show per-file
progress and cancel mid-flight. Inline images in the preview go through
VaultImage, which blob-fetches past the auth-gated storage endpoint.

Size cap 100 MB and extension allowlist (wav/mp3/m4a/ogg/webm/png/jpg/jpeg/
gif/webp) are enforced client-side before any network request. PDF + mp4
tracked upstream in parachute-vault#127. Attachment sidebar is read-only
this PR; remove button is sequenced to #8.5 after the vault DELETE endpoint
lands.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant