fix: native arbitrary-file download + image context-menu flash#830
Merged
Conversation
Two regressions in message media handling: 1. Arbitrary file downloads (FileCard, added in #810) used a bare `<a href download>`. In the Tauri webview that navigates to the blob URL, escaping to the OS browser and landing on the Block CDN "browser not supported" interstitial. Add a native `download_file` Tauri command mirroring `download_image`'s SSRF `/media/`-origin validation, 50 MiB streaming cap, and MIME blocklist, but with a generic save dialog and a sanitized imeta filename. FileCard is now a `<button>` that invokes it, keeping the fetch inside the app's HTTP tunnel. 2. The image right-click "Download Image" menu flashed and vanished: the opening contextmenu/click also drove the Radix Dialog trigger and the menu's own global dismiss listeners, tearing it down immediately. Defer attaching the dismiss listeners by one tick, stop the contextmenu during capture with stopImmediatePropagation, and preventDefault non-left pointerdown on the dialog trigger so the menu survives the interaction that opened it. Refactor `download_image` to share a `fetch_blob_bytes` helper with the new command. Update the e2e mock bridge and file-attachment specs to assert clicking a file card invokes `download_file`. Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@sprout-oss.stage.blox.sqprod.co> Signed-off-by: Wes <wesbillman@users.noreply.github.com>
ForumPostCard rendered <Markdown imetaByUrl={parseImetaTags(post.tags)} />,
building a fresh imeta object on every render. The Markdown component's
React.memo compares imetaByUrl by reference, so the memo never held for
forum posts: react-markdown re-parsed and rebuilt the FileCard <button>
on every parent render, swapping the live DOM node.
A click landing across one of those swaps split mousedown/mouseup onto
different nodes (mousedown hit the markdown <div>, pointer/up hit the
button). The browser only synthesizes a `click` when mousedown and mouseup
share a target, so no click fired, the button's onClick never ran, and the
file download was silently dropped. This is why forum file downloads failed
while chat (which does not re-render the card the same way) worked.
Memoize the imeta map on post.tags so the Markdown memo holds, the FileCard
node identity stays stable, and the click lands. Also avoids re-parsing
every forum post's markdown on each render.
Verified: full desktop smoke e2e suite (127 passed); the previously failing
forum file-attachment download test green 6/6 on repeated runs.
Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@sprout-oss.stage.blox.sqprod.co>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
bdcbf30 to
94e8a14
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Two regressions in message media handling, reported by @wesbillman:
FileCard(added in feat(media): support arbitrary file types with download cards #810) used a bare<a href download>; in the Tauri webview that navigates to the blob URL, escaping to the OS browser → WARP/CDN proxy.Fix
File download — new native
download_fileTauri command besidedownload_image:/media/-origin validation, 50 MiB streaming cap, and MIME blocklist (HTML/SVG/executables only — PDFs, zips, text, docs pass).download_imagerefactored to share afetch_blob_byteshelper.FileCardis now a<button>invokingdownload_file(with toast on error) — fetch stays inside the app's HTTP tunnel, no browser escape.Context-menu flash — three complementary guards on
markdown.tsx:setTimeout(0)), so the opening right-click can never be the event that closes the menu.onContextMenuCapture+stopImmediatePropagationto stop the contextmenu during capture.preventDefaulton non-leftpointerdownon the Radix dialog trigger so the trigger stack can't tear the menu down.Testing
pnpm typecheck✅cargo test media_download(10 URL-validation tests) ✅download_fileis invoked on card click ✅Co-authored-by: Brain