feat: ask where to save downloads
Facebook Messenger on your desktop, without the Facebook clutter
Brought to you by:
kristoffer-r
Originally created by: kristofferR
Carrier currently saves Messenger media directly to the system Downloads folder, with no way to choose a destination per file.
This adds a General setting that keeps the existing automatic behavior by default or opens a native save dialog for every download. Picker paths stay in Rust, downloads without a matching reservation are rejected in ask mode, and selected filenames are revalidated against the existing media safety policy.
Validation:
bun run checkcargo fmt && cargo clippy --all-targets -- -D warnings && cargo test --libcrq preflight --type uncommittedRef [#219]
Originally posted by: kristofferR
@coderabbitai review
Originally posted by: kristofferR
@codex review
Originally posted by: coderabbitai[bot]
✅ Action performed
Review finished. > Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.Originally posted by: chatgpt-codex-connector[bot]
Codex Review: Didn't find any major issues. Chef's kiss.
Reviewed commit:
ccbd6f926cℹ️ About Codex in GitHub
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Originally posted by: coderabbitai[bot]
📝 Walkthrough
## Walkthrough The change adds a persisted download behavior setting with automatic and prompted modes. Native save dialogs validate and reserve paths. Download flows use the selected path, enforce safe destinations, and suppress cancellation toasts. ### Changes **Download behavior configuration** |Layer / File(s)|Summary| |---|---| |**Settings and bridge contract**`dist/settings.html`, `inject/src/types.d.ts`, `src-tauri/src/settings.rs`, `inject/src/messenger/lib/injected-assets.test.ts`|The General tab exposes `downloads` and `ask` options. Settings validation and defaults support both values. The injected bridge declares the chooser call.| |**Native picker protocol**
`src-tauri/Cargo.toml`, `src-tauri/src/download.rs`, `src-tauri/src/lib.rs`, `src-tauri/src/window.rs`|The dialog plugin presents save dialogs. Signed results cover presentation and completion phases. Selected paths receive validation, bounded reservations, and one-time consumption.| |**Download path enforcement**
`src-tauri/src/window.rs`|Prompted downloads use approved paths. Unprompted downloads fail in `ask` mode. Automatic downloads use unique paths in the Downloads directory.| |**Injected download flows and feedback**
`inject/src/messenger/...`, `src-tauri/inject/messenger.js`|Download and share failures use centralized handling. Cancellation errors produce no toast. Success messages reflect the selected behavior. Untrusted anchor clicks are ignored.| **Estimated code review effort:** 4 (Complex) | ~60 minutes **Merge Risk:** _🔵 Low_ · up to `ccbd6` The change adds an optional save dialog while preserving automatic downloads by default. A bounded risk remains because some rejected downloads may appear as silent cancellations, leaving users without feedback and making diagnosis harder; this should be addressed or explicitly accepted by the owner. ### Sequence Diagram(s) :::mermaid sequenceDiagram participant Page participant InjectedBridge participant TauriChooser participant SaveDialog participant DownloadWindow Page->>InjectedBridge: Start download in ask mode InjectedBridge->>TauriChooser: Request URL and filename TauriChooser->>SaveDialog: Show native save dialog SaveDialog-->>TauriChooser: Return selected path or cancellation TauriChooser-->>InjectedBridge: Return signed chooser result InjectedBridge->>DownloadWindow: Start download DownloadWindow->>TauriChooser: Consume reserved path DownloadWindow-->>InjectedBridge: Return download result InjectedBridge-->>Page: Show success or failure toast
🚥 Pre-merge checks | ✅ 4 | ❌ 1
### ❌ Failed checks (1 warning) | Check name | Status | Explanation | Resolution | | :----------------: | :--------- | :------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------------- | | Docstring Coverage | ⚠️ Warning | Docstring coverage is 63.64% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |✅ Passed checks (4 passed)
| Check name | Status | Explanation | | :------------------------: | :------- | :---------------------------------------------------------------------------------------------------------- | | Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. | | Title check | ✅ Passed | The title clearly and concisely describes the main change: adding an option to ask where to save downloads. | | Linked Issues check | ✅ Passed | Check skipped because no linked issues were found for this pull request. | | Out of Scope Changes check | ✅ Passed | Check skipped because no linked issues were found for this pull request. |✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
- [ ] Create stacked PR - [ ] Commit on current branch🧪 Generate unit tests (beta)
- [ ] Create PR with unit tests - [ ] Commit unit tests in branch `t3code/implement-issue-219`Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
❤️ Share
- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)Comment
@coderabbitai helpto get the list of available commands.Originally posted by: kristofferR
@codex review
Ticket changed by: kristofferR
Originally posted by: chatgpt-codex-connector[bot]
Codex Review: Didn't find any major issues. 👍
Reviewed commit:
d43d04e447ℹ️ About Codex in GitHub
[Your team has set up Codex to review pull requests in this repo](https://chatgpt.com/codex/cloud/settings/general). Reviews are triggered when you - Open a pull request for review - Mark a draft as ready - Comment "@codex review". If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".