Skip to content

feat(desktop): image download, drag-drop prevention, and drop zone indicator#542

Merged
wesbillman merged 4 commits into
mainfrom
rick/fix-image-download
May 11, 2026
Merged

feat(desktop): image download, drag-drop prevention, and drop zone indicator#542
wesbillman merged 4 commits into
mainfrom
rick/fix-image-download

Conversation

@wesbillman

Copy link
Copy Markdown
Collaborator

Summary

  • Image download: Custom right-click context menu on images with a Tauri download_image command. Includes SSRF protection (relay origin + /media/ path validation), 50 MiB OOM cap with streaming enforcement, 60s timeout, MIME validation, and error toast feedback. 10 unit tests for URL validation.
  • Drag-drop prevention: Global dragover/drop prevention in AppShell.tsx stops the webview from navigating to file:/// URLs when files are dropped outside the composer. Scoped to file drags only (text drag-and-drop into inputs still works).
  • Drop zone indicator: Visual dashed-border overlay on the message and forum composer forms when a file is dragged over them. Uses a dragDepth ref counter for reliable enter/leave tracking, with window-level drop/dragend listeners as a safety net for edge cases (drag cancel, drop outside form).

Files changed (11)

Rust (backend)

  • src-tauri/src/commands/media_download.rs (NEW) — download_image command + validate_download_url + 10 tests
  • src-tauri/src/commands/media.rsdetect_and_validate_mime made pub(crate)
  • src-tauri/src/commands/export_util.rssave_bytes_with_dialog generalized, save_json_with_dialog delegates
  • src-tauri/src/commands/mod.rs — registered media_download module
  • src-tauri/src/lib.rs — registered download_image in invoke_handler

TypeScript (frontend)

  • src/shared/ui/markdown.tsxImageContextMenu component wrapping images
  • src/app/AppShell.tsx — global file drag prevention useEffect
  • src/features/messages/lib/useMediaUpload.tsisDragOver state, dragDepth ref, drag enter/leave/end handlers
  • src/features/messages/ui/ComposerAttachments.tsx — shared DropZoneOverlay component
  • src/features/messages/ui/MessageComposer.tsx — wired drag handlers + overlay
  • src/features/forum/ui/ForumComposer.tsx — same treatment

Test plan

  • Right-click an image in chat → "Download image" → save dialog opens → file saves correctly
  • Right-click image in lightbox → same behavior
  • Download of non-relay URL is rejected (SSRF protection)
  • Drop a file outside the composer → nothing happens (no fullscreen navigation)
  • Drop a file on the composer → file uploads as attachment
  • Drag a file over the composer → dashed border overlay appears
  • Drag file away from composer → overlay disappears
  • Press Escape during drag → overlay disappears
  • Drag text selection → no overlay appears, text drag-and-drop into inputs still works
  • Forum composer has same drop zone behavior

🤖 Generated with Claude Code

wesbillman and others added 4 commits May 11, 2026 15:40
Replace the broken native webview "Download image" context menu with a
custom implementation. Right-clicking images (thumbnail or lightbox)
shows a "Download image" option that fetches from the relay and presents
a native save-file dialog.

Security: SSRF protection (relay origin + /media/ path validation),
50 MiB size cap with streaming enforcement, 60s timeout, MIME content
validation. Errors surface via toast notifications.

Download logic lives in media_download.rs to keep media.rs under the
file size limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a file is dropped outside the message composer, the webview
navigates to a file:/// URL and displays it fullscreen. Add global
dragover/drop event prevention in AppShell to block this default
browser behavior while preserving the composer's existing drop-to-
upload functionality.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Restrict the global dragover/drop handler to only prevent default when
the drag contains files, preserving text drag-and-drop into inputs.
Fix the accompanying comment to accurately describe why the composer's
drop handler still works.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show a dashed-border overlay with "Drop files to upload" text when a
file is dragged over the message or forum composer. Uses a dragDepth
ref counter for reliable enter/leave tracking across child elements,
scoped to file drags only. Window-level drop/dragend listeners reset
state when drags end outside the form.

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

Copy link
Copy Markdown
Collaborator Author
Screen.Recording.2026-05-11.at.4.07.44.PM.mov

@wesbillman wesbillman enabled auto-merge (squash) May 11, 2026 23:19
@wesbillman wesbillman merged commit 11778f4 into main May 11, 2026
15 checks passed
@wesbillman wesbillman deleted the rick/fix-image-download branch May 11, 2026 23:26
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