Skip to content

feat(download): Open file/folder actions for completed downloads (task 08) - #101

Merged
mpiton merged 2 commits into
mainfrom
feat/task-08-open-file-folder
Apr 24, 2026
Merged

feat(download): Open file/folder actions for completed downloads (task 08)#101
mpiton merged 2 commits into
mainfrom
feat/task-08-open-file-folder

Conversation

@mpiton

@mpiton mpiton commented Apr 24, 2026

Copy link
Copy Markdown
Owner

Summary

Feature: Add Open file and Open folder actions for completed downloads in UI and Details panel
Port: Introduce FileOpener domain port for OS-level file operations (open_file, reveal_file)
Adapter: Implement SystemFileOpener with platform-specific launchers (xdg-open/open/explorer)
Application: Add command handlers open_download_file and open_download_folder with state validation
IPC: Register Tauri commands delegating to application layer with error mapping
Frontend: Wire UI buttons and mutations with i18n support and graceful error handling
Tests: 10 Rust tests (domain ports, adapters, handlers), 9 TypeScript tests (components, mutations)

Changes

  • Domain: Port FileOpener (open_file, reveal_file) with mock implementation for testing
  • Adapter: SystemFileOpener dispatches per-OS (Linux xdg-open, macOS open -R, Windows explorer /select)
  • Handlers: Validate download exists, state is Completed, file exists; error handling with NotFound distinction
  • IPC: download_open_file(id) and download_open_folder(id) with Result<(), String> signature
  • UI: Menu items and detail buttons conditional on Completed state
  • i18n: English + French keys for actions and error toasts
  • Error handling: File not found → user-friendly toast, other errors → technical message

Type

feat


Summary by cubic

Add “Open file” and “Open folder” actions for completed downloads so users can launch the file or reveal it in their OS file manager from both the table and the details panel. Implements PRD‑v2 P0.8 (task 08).

  • New Features

    • IPC: Added download_open_file(id) and download_open_folder(id) Tauri commands.
    • Backend: Introduced FileOpener port with SystemFileOpener using xdg-open (Linux), open/open -R (macOS), and explorer//select (Windows); wired via CommandBus::with_file_opener.
    • Validation: Only for Completed downloads; missing files surface as NotFound and map to a localized “File not found” toast (en/fr).
    • Frontend: Added actions in the row menu (Completed only) and buttons in the File Info section; wired with useTauriMutation and error toasts.
  • Bug Fixes

    • Run launcher calls on a blocking thread with tokio::task::spawn_blocking to avoid stalling the async runtime.
    • Windows: pass /select, and the path as separate args to explorer to handle spaces.
    • Linux/macOS: in reveal_file, normalize empty Path::parent() to “.” to support relative filenames and avoid empty args to xdg-open.

Written for commit b6bd963. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Added "Open file" and "Open folder" actions for completed downloads (table and details), invoking native OS behavior with cross‑platform support.
    • Added localized toasts for missing files and operation failures (English, French).
  • Documentation

    • Documented native folder/file picker usage in General settings and added reusable UI hooks.
  • Tests

    • Added interaction and unit tests covering open-file/folder actions and error-to-toast behavior.

…nloads (task 08)

Expose two Tauri IPC commands (`download_open_file`, `download_open_folder`)
that launch a completed download with the OS default app or reveal it in
the host file manager. A new `FileOpener` domain port, implemented by
`SystemFileOpener`, dispatches to `xdg-open` on Linux, `open`/`open -R` on
macOS and `explorer`/`explorer /select,<path>` on Windows. Application
handlers validate the download is in `Completed` state and surface
`DomainError::NotFound` when the file is missing — the frontend mutation
maps that to a localized "File not found" toast. UI adds the actions in
the downloads row dropdown (Completed rows only) and as buttons in the
detail panel's File info section.
@github-actions github-actions Bot added documentation Improvements or additions to documentation rust frontend labels Apr 24, 2026
@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds cross-platform "open file" and "open folder" functionality: new FileOpener domain port, SystemFileOpener adapter, command handlers, Tauri IPC commands, wiring into CommandBus, frontend buttons/menu items, i18n strings, and tests.

Changes

Cohort / File(s) Summary
Domain Port
src-tauri/src/domain/ports/driven/file_opener.rs, src-tauri/src/domain/ports/driven/mod.rs
New FileOpener trait with open_file and reveal_file returning DomainError.
Filesystem Adapter
src-tauri/src/adapters/driven/filesystem/file_opener.rs, src-tauri/src/adapters/driven/filesystem/mod.rs
New SystemFileOpener implementing FileOpener with platform-specific commands (xdg-open/open/start/explorer), path validation, error mapping, and unit tests.
Application Layer
src-tauri/src/application/command_bus.rs, src-tauri/src/application/commands/...
CommandBus gains optional file_opener injection and accessors; new CQRS types OpenDownloadFileCommand / OpenDownloadFolderCommand and handlers (handle_open_download_file, handle_open_download_folder) that validate state, call the port via spawn_blocking, and map errors to AppError.
Tauri IPC & Wiring
src-tauri/src/adapters/driving/tauri_ipc.rs, src-tauri/src/lib.rs
Two new Tauri commands (download_open_file, download_open_folder) wired to handlers; SystemFileOpener exported and injected into CommandBus at startup.
Frontend UI & Tests
src/views/DownloadDetailsPanel/FileInfoSection.tsx, src/views/DownloadDetailsPanel/__tests__/FileInfoSection.test.tsx, src/views/DownloadsView/DownloadsTable.tsx, src/views/DownloadsView/__tests__/DownloadsTable.test.tsx
Conditional "Open file"/"Open folder" buttons and menu items for completed downloads, Tauri mutations with differentiated error-to-toast mapping, and tests verifying rendering, invocation, and toast behavior.
i18n
src/i18n/locales/en.json, src/i18n/locales/fr.json
Added translation keys for downloads.table.actions.openFile and openFolder and downloads.table.toast messages for errors (file missing/generic folder error).
Tests / Ports Compile-time
src-tauri/src/domain/ports/driven/tests.rs
Added in-test RecordingFileOpener and assertions ensuring Send + Sync conformance and call recording.

Sequence Diagram

sequenceDiagram
    participant FE as Frontend (React)
    participant IPC as Tauri IPC
    participant CB as CommandBus / Handler
    participant Repo as Download Repository
    participant Port as FileOpener Port
    participant OS as Operating System

    FE->>IPC: download_open_file(id)
    IPC->>CB: handle_open_download_file(cmd)
    CB->>Repo: find_by_id(id)
    Repo-->>CB: download or NotFound
    CB->>CB: validate download.state == Completed
    CB->>Port: open_file(destination_path) (spawn_blocking)
    Port->>OS: spawn native opener (xdg-open/open/start)
    OS-->>Port: result / exit code
    Port-->>CB: Ok or DomainError
    CB-->>IPC: Ok or AppError (mapped to String)
    IPC-->>FE: Ok or error string
    FE->>FE: show toast if error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

ui

Poem

🐰 A rabbit hops with keys and logs in tow,
I open folders where the downloads go,
Tauri whispers, the system answers true,
Click, reveal, and the user smiles anew—
Huzzah for files that leap right into view! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.87% 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
Title check ✅ Passed The title clearly and specifically describes the main change: implementing 'Open file/folder actions for completed downloads', which aligns with the comprehensive feature added across domain, adapter, application, IPC, and frontend layers.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/task-08-open-file-folder

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Apr 24, 2026

Copy link
Copy Markdown

Greptile Summary

This PR implements "Open file" and "Open folder" actions for completed downloads across the full stack: a new FileOpener domain port, a SystemFileOpener adapter with per-OS launchers (xdg-open / open -R / explorer), two Tauri IPC commands, frontend mutations, and i18n keys in English and French. The two P1 issues raised in the previous review (blocking Command::status() in an async handler, and Windows /select, path-with-spaces) are both addressed — spawn_blocking wraps the sync calls and the path is now passed as a separate OsString argument.

Confidence Score: 5/5

Safe to merge — previous P1 issues are resolved and all remaining findings are P2 or informational.

The two blocking issues from the previous review (spawn_blocking missing, Windows path quoting) are both fixed in this revision. No new P0 or P1 bugs were found. The openFileMissing key reuse for folder not-found errors and the test scaffold duplication are pre-existing P2 concerns already captured in prior review threads.

No files require special attention for merge readiness.

Important Files Changed

Filename Overview
src-tauri/src/adapters/driven/filesystem/file_opener.rs New SystemFileOpener adapter with per-OS launchers; blocking calls correctly wrapped via spawn_blocking in handlers; Windows /select, two-arg approach addresses previous path-with-spaces concern
src-tauri/src/application/commands/open_download_file.rs Handler validates Completed state, wraps blocking open_file in spawn_blocking, maps NotFound; ~200-line test scaffold duplicated from open_download_folder.rs (noted in previous review)
src-tauri/src/application/commands/open_download_folder.rs Symmetric to open_download_file handler; uses reveal_file with graceful fallback when file is gone; same duplicated test scaffold issue
src-tauri/src/application/command_bus.rs Adds optional file_opener field via builder pattern matching checksum_computer; no breaking changes to existing fixtures
src-tauri/src/adapters/driving/tauri_ipc.rs Two new Tauri commands download_open_file and download_open_folder wired correctly to handlers; Result<(), String> signatures consistent with other IPC commands
src/views/DownloadsView/DownloadsTable.tsx Adds openFile/openFolder to RowActions context; Completed-only menu items with mutations; openFileMissing key reused for folder not-found case (flagged in prior review)
src/views/DownloadDetailsPanel/FileInfoSection.tsx Adds Open file and Open folder buttons conditionally on Completed state; same openFileMissing/openFolderError inconsistency as DownloadsTable (noted in prior review)
src/i18n/locales/en.json Adds openFile/openFolder action labels and toast keys; missing openFolderMissing key (covered by prior review comment)
src/i18n/locales/fr.json French translations added symmetrically with en.json

Sequence Diagram

sequenceDiagram
    participant UI as Frontend (React)
    participant IPC as Tauri IPC
    participant Bus as CommandBus
    participant Repo as DownloadRepository
    participant BTP as spawn_blocking
    participant OS as SystemFileOpener

    UI->>IPC: download_open_file(id) / download_open_folder(id)
    IPC->>Bus: handle_open_download_file / handle_open_download_folder
    Bus->>Repo: find_by_id(id)
    Repo-->>Bus: Download (or NotFound)
    Bus->>Bus: validate state == Completed
    Bus->>BTP: spawn_blocking(opener.open_file / reveal_file)
    BTP->>OS: open_file(path) / reveal_file(path)
    OS->>OS: check path.exists()
    OS-->>BTP: Ok(()) or DomainError::NotFound
    BTP-->>Bus: Result
    Bus-->>IPC: AppError mapped
    IPC-->>UI: Result<(), String>
    UI->>UI: toast on error (openFileMissing / openFileError)
Loading

Reviews (2): Last reviewed commit: "fix(download): address PR #101 review co..." | Re-trigger Greptile

Comment thread src-tauri/src/adapters/driven/filesystem/file_opener.rs
Comment on lines +151 to +162
.map_err(|e| DomainError::StorageError(format!("failed to launch {program}: {e}")))?;
// Launchers on Windows (cmd/start/explorer) can return non-zero even on
// successful hand-off, so we trust the spawn-did-not-error signal only.
Ok(())
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn open_file_errors_when_path_missing() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Blocking Command::status() call inside an async Tauri handler

run_launcher calls std::process::Command::status(), which is a synchronous blocking call. It is invoked from handle_open_download_file/handle_open_download_folder, which are awaited inside async Tauri IPC handlers. The module doc acknowledges the issue but the fix is not applied at the call site — blocking a Tokio worker thread starves other tasks on that thread while the child process runs. Wrapping the call in tokio::task::spawn_blocking would keep the async runtime healthy on slow launchers or network-mounted destinations.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src-tauri/src/adapters/driven/filesystem/file_opener.rs
Line: 151-162

Comment:
**Blocking `Command::status()` call inside an async Tauri handler**

`run_launcher` calls `std::process::Command::status()`, which is a synchronous blocking call. It is invoked from `handle_open_download_file`/`handle_open_download_folder`, which are awaited inside async Tauri IPC handlers. The module doc acknowledges the issue but the fix is not applied at the call site — blocking a Tokio worker thread starves other tasks on that thread while the child process runs. Wrapping the call in `tokio::task::spawn_blocking` would keep the async runtime healthy on slow launchers or network-mounted destinations.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/views/DownloadsView/__tests__/DownloadsTable.test.tsx (1)

124-135: ⚠️ Potential issue | 🟠 Major

Reset locale in shared setup to prevent order-dependent test failures.

A previous test sets i18nextLng to fr, but this setup does not restore a default locale. Later tests asserting English labels can fail depending on execution order.

Proposed fix
 beforeEach(() => {
+  window.localStorage.setItem('i18nextLng', 'en');
   useUiStore.setState({
     selectedDownloadId: null,
     selectedDownloadIds: [],
     detailsPanelOpen: false,
     filterBarExpanded: false,
   });
   useDownloadStore.setState({ progressMap: {} });
   invokeMock.mockClear();
   invokeMock.mockResolvedValue(undefined);
   toastErrorMock.mockClear();
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/DownloadsView/__tests__/DownloadsTable.test.tsx` around lines 124 -
135, In the shared beforeEach setup, reset the i18next locale so tests aren't
order-dependent: update the beforeEach block (the one calling
useUiStore.setState and useDownloadStore.setState) to also clear or set the
i18next storage key (e.g., localStorage.removeItem('i18nextLng') or
localStorage.setItem('i18nextLng','en')) so tests that assert English labels
always run with a known locale.
🧹 Nitpick comments (1)
src/views/DownloadsView/DownloadsTable.tsx (1)

371-382: Prefer structured error codes over string matching for failure classification.

Using "not found" substring checks ties UI behavior to backend message text. A small wording change can silently break the missing-file toast path. Consider returning a typed error code from IPC (e.g., NOT_FOUND) and branching on that instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/views/DownloadsView/DownloadsTable.tsx` around lines 371 - 382, The
current error handlers in openFileMut and openFolderMut rely on fragile string
matching of err.message to detect missing-file cases; update both
useTauriMutation errorMessage callbacks to branch on a structured error code
(e.g., check err.code === 'NOT_FOUND' or err?.details?.code) instead of
searching for "not found", and coordinate with the IPC handlers
('download_open_file' and 'download_open_folder') to return that typed error
code on missing files so the toast selection
(downloads.table.toast.openFileMissing vs openFileError/openFolderError) is
resilient to message text changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src-tauri/src/adapters/driven/filesystem/file_opener.rs`:
- Around line 68-82: The NotFound guard and Linux fallback mishandle
single-component relative paths because path.parent() can be an empty path;
update the parent handling so empty parents are treated as the current directory
("."), i.e. compute parent from path.parent() but normalize any empty Path to
Path::new(".") before calling is_dir()/using it, then use that normalized parent
when deciding the NotFound error and when computing target for run_launcher
(refer to the parent, path, target and run_launcher usages and ensure the
unwrap_or/unwrap_or_else branches return Path::new(".") instead of an empty
path).

In `@src-tauri/src/application/commands/open_download_file.rs`:
- Around line 34-36: The call to
opener.open_file(Path::new(download.destination_path())) currently maps all
errors to AppError::Domain which loses file-not-found semantics; update the
error mapping in open_download_file.rs so that when opener.open_file returns an
IO error with ErrorKind::NotFound you return AppError::NotFound (preserving the
download.destination_path() context if needed), and for all other errors
continue to map to AppError::Domain; target the expression around
opener.open_file(...) and replace the single map_err(AppError::Domain) with
logic that matches the underlying error kind and returns AppError::NotFound for
NotFound, otherwise AppError::Domain.

---

Outside diff comments:
In `@src/views/DownloadsView/__tests__/DownloadsTable.test.tsx`:
- Around line 124-135: In the shared beforeEach setup, reset the i18next locale
so tests aren't order-dependent: update the beforeEach block (the one calling
useUiStore.setState and useDownloadStore.setState) to also clear or set the
i18next storage key (e.g., localStorage.removeItem('i18nextLng') or
localStorage.setItem('i18nextLng','en')) so tests that assert English labels
always run with a known locale.

---

Nitpick comments:
In `@src/views/DownloadsView/DownloadsTable.tsx`:
- Around line 371-382: The current error handlers in openFileMut and
openFolderMut rely on fragile string matching of err.message to detect
missing-file cases; update both useTauriMutation errorMessage callbacks to
branch on a structured error code (e.g., check err.code === 'NOT_FOUND' or
err?.details?.code) instead of searching for "not found", and coordinate with
the IPC handlers ('download_open_file' and 'download_open_folder') to return
that typed error code on missing files so the toast selection
(downloads.table.toast.openFileMissing vs openFileError/openFolderError) is
resilient to message text changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 81272ca2-2392-4af0-937e-6cdf1b823988

📥 Commits

Reviewing files that changed from the base of the PR and between de8e0a0 and f008b86.

📒 Files selected for processing (18)
  • CHANGELOG.md
  • src-tauri/src/adapters/driven/filesystem/file_opener.rs
  • src-tauri/src/adapters/driven/filesystem/mod.rs
  • src-tauri/src/adapters/driving/tauri_ipc.rs
  • src-tauri/src/application/command_bus.rs
  • src-tauri/src/application/commands/mod.rs
  • src-tauri/src/application/commands/open_download_file.rs
  • src-tauri/src/application/commands/open_download_folder.rs
  • src-tauri/src/domain/ports/driven/file_opener.rs
  • src-tauri/src/domain/ports/driven/mod.rs
  • src-tauri/src/domain/ports/driven/tests.rs
  • src-tauri/src/lib.rs
  • src/i18n/locales/en.json
  • src/i18n/locales/fr.json
  • src/views/DownloadDetailsPanel/FileInfoSection.tsx
  • src/views/DownloadDetailsPanel/__tests__/FileInfoSection.test.tsx
  • src/views/DownloadsView/DownloadsTable.tsx
  • src/views/DownloadsView/__tests__/DownloadsTable.test.tsx

Comment thread src-tauri/src/adapters/driven/filesystem/file_opener.rs Outdated
Comment thread src-tauri/src/application/commands/open_download_file.rs Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 18 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src-tauri/src/adapters/driven/filesystem/file_opener.rs">

<violation number="1" location="src-tauri/src/adapters/driven/filesystem/file_opener.rs:56">
P1: Using `cmd /C start` with an unescaped path lets `cmd` interpret metacharacters in filenames, which can execute unintended commands on Windows.</violation>

<violation number="2" location="src-tauri/src/adapters/driven/filesystem/file_opener.rs:113">
P2: Build the Windows `explorer /select` arguments without embedding the raw path into a formatted switch string; paths with spaces can fail to select the intended file.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

std::ffi::OsString::from("/C"),
std::ffi::OsString::from("start"),
std::ffi::OsString::from(""),
path.as_os_str().to_os_string(),

@cubic-dev-ai cubic-dev-ai Bot Apr 24, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: Using cmd /C start with an unescaped path lets cmd interpret metacharacters in filenames, which can execute unintended commands on Windows.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src-tauri/src/adapters/driven/filesystem/file_opener.rs, line 56:

<comment>Using `cmd /C start` with an unescaped path lets `cmd` interpret metacharacters in filenames, which can execute unintended commands on Windows.</comment>

<file context>
@@ -0,0 +1,186 @@
+                std::ffi::OsString::from("/C"),
+                std::ffi::OsString::from("start"),
+                std::ffi::OsString::from(""),
+                path.as_os_str().to_os_string(),
+            ],
+        );
</file context>
Fix with Cubic

Comment thread src-tauri/src/adapters/driven/filesystem/file_opener.rs Outdated
- Wrap Command::status() calls in tokio::task::spawn_blocking so the
  async Tauri IPC handlers stop starving the tokio runtime on slow
  launchers (CodeRabbit + greptile).
- Preserve DomainError::NotFound as AppError::NotFound in both command
  handlers so the UI can still surface the localized "file not found"
  toast instead of the generic failure path.
- Normalize empty Path::parent() to "." in reveal_file so single-
  component relative paths like "file.bin" no longer spuriously error
  with NotFound and no longer hand an empty arg to xdg-open.
- On Windows, pass "/select," and the target path as two separate
  OsString arguments so explorer can reveal files whose path contains
  spaces (e.g. "C:\\My Downloads\\file.mp4").
- Reset i18nextLng to "en" in DownloadsTable test setup so specs that
  assert English labels don't depend on test execution order.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src-tauri/src/application/commands/open_download_file.rs (1)

70-251: Consider extracting shared test mocks to reduce duplication.

The mock implementations (Repo, Engine, Bus, FS, Http, Loader, Cfg, Creds, Clip, Arch, RecordingOpener, build_bus, make_completed) are largely duplicated between this file and open_download_folder.rs. Consolidating these into a shared test support module (e.g., application::test_support) would reduce maintenance burden and ensure consistency.

Also applies to: 252-307

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src-tauri/src/application/commands/open_download_file.rs` around lines 70 -
251, Extract the duplicated test mocks and helpers into a shared test support
module (e.g., application::test_support): move the structs and impls Repo,
Engine, Bus, FS, Http, Loader, Cfg, Creds, Clip, Arch, RecordingOpener and the
helper functions build_bus and make_completed into that module, make them public
(pub) so tests can reuse them, then replace the local definitions in
open_download_file.rs and open_download_folder.rs with use
application::test_support::{Repo, Engine, Bus, FS, Http, Loader, Cfg, Creds,
Clip, Arch, RecordingOpener, build_bus, make_completed}; ensure any referenced
types (DownloadRepository, DownloadEngine, EventBus, FileStorage, HttpClient,
PluginLoader, ConfigStore, CredentialStore, ClipboardObserver, ArchiveExtractor)
are still in scope via existing imports.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src-tauri/src/application/commands/open_download_file.rs`:
- Around line 70-251: Extract the duplicated test mocks and helpers into a
shared test support module (e.g., application::test_support): move the structs
and impls Repo, Engine, Bus, FS, Http, Loader, Cfg, Creds, Clip, Arch,
RecordingOpener and the helper functions build_bus and make_completed into that
module, make them public (pub) so tests can reuse them, then replace the local
definitions in open_download_file.rs and open_download_folder.rs with use
application::test_support::{Repo, Engine, Bus, FS, Http, Loader, Cfg, Creds,
Clip, Arch, RecordingOpener, build_bus, make_completed}; ensure any referenced
types (DownloadRepository, DownloadEngine, EventBus, FileStorage, HttpClient,
PluginLoader, ConfigStore, CredentialStore, ClipboardObserver, ArchiveExtractor)
are still in scope via existing imports.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 122f32f2-780f-4a50-85f2-4307ca793904

📥 Commits

Reviewing files that changed from the base of the PR and between f008b86 and b6bd963.

📒 Files selected for processing (5)
  • src-tauri/src/adapters/driven/filesystem/file_opener.rs
  • src-tauri/src/application/command_bus.rs
  • src-tauri/src/application/commands/open_download_file.rs
  • src-tauri/src/application/commands/open_download_folder.rs
  • src/views/DownloadsView/__tests__/DownloadsTable.test.tsx

@mpiton
mpiton merged commit d6d5281 into main Apr 24, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation frontend rust

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant