Skip to content

Fix: Open Original File button not working in Image Details panel #688.#689

Open
NikhilPatil2005 wants to merge 3 commits intoAOSSIE-Org:mainfrom
NikhilPatil2005:open-image-issue
Open

Fix: Open Original File button not working in Image Details panel #688.#689
NikhilPatil2005 wants to merge 3 commits intoAOSSIE-Org:mainfrom
NikhilPatil2005:open-image-issue

Conversation

@NikhilPatil2005
Copy link

@NikhilPatil2005 NikhilPatil2005 commented Dec 6, 2025

fixes issue #688

Summary by CodeRabbit

  • New Features

    • Added sharing options modal with OneDrive integration and clipboard copy functionality
    • Enhanced media information panel with location-based Google Maps link support
    • Added ability to open original media files directly
  • Dependencies

    • Updated framework API package to latest stable version

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 6, 2025

Walkthrough

This pull request migrates the Tauri application from shell-based file operations to the tauri-opener plugin, adds a new ShareOptionsModal component with OneDrive integration for file sharing, updates Tauri dependencies, creates a new opener capability manifest, and includes development workflow documentation.

Changes

Cohort / File(s) Summary
Tauri Plugin & Resource Handling
frontend/src-tauri/src/main.rs
Refactored resource path resolution to single-line call; reformatted invoke_handler macro with multi-line list style; clarified tauri_plugin_opener::init() requirement.
File/URL Open Migration
frontend/src/components/Media/MediaInfoPanel.tsx
Replaced tauri-shell open with tauri-opener openPath/openUrl; enhanced location handling with Google Maps integration; added handleOpenOriginal with logging and error handling; reorganized UI sections with improved null-safety checks.
File Sharing Modal
frontend/src/components/Media/ShareOptionsModal.tsx
New React component providing file sharing UI with OneDrive integration; includes copy-to-clipboard, tile-based actions, and Tauri invoke calls to onedrive_share and share_file backend endpoints.
Opener Plugin Configuration
frontend/src-tauri/capabilities/opener.json
New capability manifest defining opener plugin permissions with allowed open-path directories (home, desktop, downloads, documents, pictures) and mounted volumes.
Dependency Management
frontend/package.json
Updated @tauri-apps/api from >=2.0.0-beta.0 to ^2.9.1.
Formatting & Configuration
frontend/tsconfig.json, frontend/src/components/Media/ImageCard.tsx, .gitignore, run.txt
Minor whitespace adjustment in tsconfig.json; removed trailing newline from ImageCard.tsx; added .venv/ to gitignore; added environment setup and Git workflow documentation.

Sequence Diagram

sequenceDiagram
    participant User
    participant ShareModal as ShareOptionsModal
    participant Tauri as Tauri Runtime
    participant Backend

    User->>ShareModal: Click "Using OneDrive" or "More options"
    ShareModal->>Tauri: invoke('onedrive_share', {filePath})
    Tauri->>Backend: onedrive_share handler
    Backend-->>Tauri: share URL
    Tauri-->>ShareModal: receive share URL
    
    rect rgb(200, 220, 255)
        Note over ShareModal,Backend: OneDrive Share Flow
        ShareModal->>Tauri: invoke('share_file', {shareUrl})
        Tauri->>Backend: share_file handler
        Backend-->>Tauri: open native share dialog
        Tauri-->>ShareModal: dialog result
    end
    
    ShareModal-->>User: Share dialog displayed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • ShareOptionsModal.tsx: New component with Tauri invoke integration; requires verification of onedrive_share and share_file backend endpoint contracts, error handling patterns, and disabled state logic
  • MediaInfoPanel.tsx: Multiple API migration points from shell to opener; verify Google Maps URL construction and openPath/openUrl usage across different scenarios (local files vs. URLs)
  • opener.json: New capability manifest; ensure allowed paths are correctly scoped and match intended security model
  • Tauri main.rs: While mostly formatting, verify that plugin initialization order and resource resolution behavior remain unchanged

Possibly related PRs

Suggested reviewers

  • rahulharpal1603

Poem

🐰 A rabbit hops with glee so bright,
The opener plugin shines with light!
With ShareOptions and OneDrive's embrace,
Files flow freely through cyberspace,
No shell to open—just tauri's might! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main fix: replacing the broken Open Original File button functionality with tauri-opener plugin integration across multiple files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2273a0a and bdfd988.

⛔ Files ignored due to path filters (1)
  • frontend/src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (1)
  • frontend/src/components/Media/ShareOptionsModal.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/Media/ShareOptionsModal.tsx

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

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/src/components/Media/MediaInfoPanel.tsx (1)

49-57: Frontend invoke usage is fine; consider typing and trimming debug logs

Both call sites for invoke('open_original_file', …) are correctly shaped for a command that takes a single path: String argument and returns Result<(), String> once the Rust side is fixed to accept an AppHandle and use app.opener().open_path. (v2.tauri.app)

Two small optional tweaks:

  • For better type-safety and editor help, you can make the return type explicit since you ignore it anyway:
    await invoke<void>('open_original_file', { path: url });
    // ...
    await invoke<void>('open_original_file', { path: currentImage.path });
  • The console.log('Sending path to Tauri:', currentImage.path); line will print full local file paths (often including the username) to the dev console. Once you’re done debugging the issue, it’s safer to remove or gate this behind a debug flag so you’re not routinely logging potentially sensitive paths.

If, in the future, you want to distinguish between opening URLs (map links) and filesystem paths at the Rust layer, the opener plugin also provides an open_url API that you could expose via a separate command.

Also applies to: 170-178

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c37d8df and 194e71c.

📒 Files selected for processing (2)
  • frontend/src-tauri/src/main.rs (2 hunks)
  • frontend/src/components/Media/MediaInfoPanel.tsx (8 hunks)
🔇 Additional comments (4)
frontend/src-tauri/src/main.rs (2)

43-46: Command registration looks correct; ensure capabilities allow it

Registering open_original_file alongside services::get_server_path via tauri::generate_handler! is the right way to expose it to invoke('open_original_file', …) on the frontend; no code changes needed here. (v2.tauri.app)

Just make sure your Tauri 2 capabilities configuration allows this command and the opener plugin usage in production, otherwise the frontend may see “command not allowed” or permission errors at runtime.


10-24: Fix open_original_file to use AppHandle + OpenerExt::open_path

This command requires corrections to use the tauri-plugin-opener v2.x API correctly. The open_path method must be called on app.opener() after bringing the OpenerExt trait into scope. The command should accept an AppHandle parameter to access the plugin instance.

+use tauri::AppHandle;
+use tauri_plugin_opener::OpenerExt;
+
 #[tauri::command]
-async fn open_original_file(path: String) -> Result<(), String> {
-    println!("Tauri received path: {}", path);
-
-    match tauri_plugin_opener::open_path(&path, None::<String>) {
+async fn open_original_file(app: AppHandle, path: String) -> Result<(), String> {
+    println!("Tauri received path: {}", path);
+
+    match app.opener().open_path(path, None::<&str>) {
         Ok(_) => {
             println!("File opened successfully");
             Ok(())
         }
         Err(e) => {
             eprintln!("Failed to open file: {}", e);
             Err(e.to_string())
         }
     }
 }

(If you never await anything here, you can also make the command non-async.)

frontend/src/components/Media/MediaInfoPanel.tsx (2)

2-2: Tauri v2 invoke import is correct

Importing invoke from @tauri-apps/api/core is the right pattern for Tauri 2 and matches the current docs. No changes needed here. (v2.tauri.app)


76-152: Sectioned “Image Details” layout changes look good

The added inline section labels (Name, Date, Location, Tags, Position) and their associated markup are purely presentational, don’t affect behavior, and integrate cleanly with the existing props (currentImage, currentIndex, totalImages). No functional issues spotted here.

@NikhilPatil2005
Copy link
Author

Hi @rahulharpal1603,
I have created the PR for fixing Issue #688. The implementation is tested locally and working as expected.
Please review the PR and kindly approve the workflow so checks can run.
Let me know if any changes are required.
Thank you!

Copy link
Contributor

@rahulharpal1603 rahulharpal1603 left a comment

Choose a reason for hiding this comment

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

Can't we just use this plugin: https://v2.tauri.app/plugin/opener/

It is much easier to use this than write Rust code.

@rahulharpal1603 rahulharpal1603 changed the title Fix: Open Original File button not working in Image Details panel #688 Fix: Open Original File button not working in Image Details panel #688. Dec 7, 2025
@github-actions github-actions bot added bug Something isn't working frontend labels Dec 7, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
frontend/src/components/Media/MediaInfoPanel.tsx (1)

41-55: LGTM! Improved null safety and correct API usage.

The stricter null checks for coordinates and migration to openUrl are correct. Minor note: the comment on line 47 about "Fixed URL format" is unclear—consider removing it if no specific fix was needed, or clarifying what was changed.

If the comment refers to a specific issue, clarify it:

-      // Fixed URL format (removed the '0' typo before latitude if it was unintentional, or kept standard)
+      // Standard Google Maps URL format
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 194e71c and 0088342.

📒 Files selected for processing (3)
  • frontend/src-tauri/capabilities/opener.json (1 hunks)
  • frontend/src-tauri/src/main.rs (1 hunks)
  • frontend/src/components/Media/MediaInfoPanel.tsx (8 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src-tauri/src/main.rs (1)
frontend/src-tauri/src/services/mod.rs (1)
  • get_server_path (5-11)
🔇 Additional comments (8)
frontend/src-tauri/src/main.rs (3)

10-10: LGTM! Clear documentation added.

The comment clarifies the purpose and necessity of the opener plugin, improving code maintainability.


18-18: LGTM! Cleaner path resolution.

The single-line path resolution is more concise and aligns with the pattern used in services/mod.rs (lines 4-10).


22-24: LGTM! Improved formatting.

The multi-line format with trailing comma follows Rust conventions and makes it easier to add future handlers.

frontend/src/components/Media/MediaInfoPanel.tsx (4)

1-12: LGTM! Correct migration to opener plugin.

The import change from tauri-plugin-shell to @tauri-apps/plugin-opener aligns with the capability configuration and is the correct fix for the issue.


29-39: LGTM! Clean refactoring.

Both helper functions are more concise and use modern JavaScript features (optional chaining, nullish coalescing) appropriately.


122-132: LGTM! Proper null guards for coordinate formatting.

The null checks ensure toFixed() is only called on valid numbers, preventing runtime errors.


178-186: LGTM! This is the core fix for issue #688.

The button now correctly calls handleOpenOriginal, which uses the opener plugin with proper error handling. This should resolve the "Open Original File button not working" issue.

frontend/src-tauri/capabilities/opener.json (1)

1-21: Verify that allowed paths align with intended use cases for opening images.

The capability restricts file opening to standard home directory locations ($HOME/**), which excludes external drives, network locations, and system directories. If the application needs to support opening images from external storage, those paths must be explicitly added to the allow list. For example:

  • macOS external drives: "/Volumes/**"
  • Linux removable media: "/media/**" or "/mnt/**"
  • Windows external drives: "E:\\**", "F:\\**", etc.
  • Network shares: "\\\\server\\share\\**" (Windows) or mounted network paths

Clarify whether the current scope is intentional (restrict to home directory for security) or whether external/network storage support is required.

Comment on lines 57 to 73
const handleOpenOriginal = async () => {
if (!currentImage?.path) {
console.warn("No path available for currentImage");
return;
}
const path = currentImage.path;
console.log("Attempting to open file:", path);

try {
// This will now succeed because the path is in the allowed scope
await openPath(path);
console.log("openPath succeeded");
} catch (err) {
console.error("openPath failed:", err);
alert(`Could not open file: ${err}`); // Optional user feedback
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Function works but has UX and assumption concerns.

The implementation correctly uses openPath and includes error handling, but:

  1. Path scope assumption (line 66): The comment assumes the path is always in the allowed scope defined in opener.json. If images can be stored outside $HOME/** (e.g., external drives, network shares), openPath will fail.

  2. User feedback (line 71): Using alert() for error feedback is not ideal UX—it blocks the UI and looks dated. Consider using a toast notification or inline error message instead.

Consider replacing the alert with better error feedback:

-      alert(`Could not open file: ${err}`); // Optional user feedback
+      // TODO: Replace with toast notification system
+      console.error("User-facing error: Could not open file. Ensure the file exists and is accessible.");

Additionally, verify that all image paths will be within the allowed directories defined in opener.json. If not, you may need to extend the capability permissions.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleOpenOriginal = async () => {
if (!currentImage?.path) {
console.warn("No path available for currentImage");
return;
}
const path = currentImage.path;
console.log("Attempting to open file:", path);
try {
// This will now succeed because the path is in the allowed scope
await openPath(path);
console.log("openPath succeeded");
} catch (err) {
console.error("openPath failed:", err);
alert(`Could not open file: ${err}`); // Optional user feedback
}
};
const handleOpenOriginal = async () => {
if (!currentImage?.path) {
console.warn("No path available for currentImage");
return;
}
const path = currentImage.path;
console.log("Attempting to open file:", path);
try {
// This will now succeed because the path is in the allowed scope
await openPath(path);
console.log("openPath succeeded");
} catch (err) {
console.error("openPath failed:", err);
// TODO: Replace with toast notification system
console.error("User-facing error: Could not open file. Ensure the file exists and is accessible.");
}
};
🤖 Prompt for AI Agents
In frontend/src/components/Media/MediaInfoPanel.tsx around lines 57 to 73,
remove the assumption comment about path always being in the allowed opener.json
scope and replace the blocking alert() with non-blocking UX; handle failures by
(1) using the app's toast/notification system (or render an inline error state)
to show a friendly message with the error, (2) log the full error to console for
debugging, and (3) detect permission/scope errors specifically and present
actionable guidance (e.g., "file may be outside allowed directories; move file
or update opener.json") or fallback behavior. Also add a lightweight pre-check
for allowed paths (use an existing isPathAllowed helper or compare against known
allowed prefixes like $HOME) before calling openPath and fall back to the
toast/instruction if the path is out of scope.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (5)
frontend/src-tauri/Cargo.toml (1)

26-26: Confirm dotenvy is actually needed

dotenvy = "0.15" looks fine for env loading, but from this diff alone it's not clear it's used. If no code ends up depending on it, consider dropping it to keep the Tauri binary leaner.

run.txt (1)

1-75: Tighten and de‑duplicate run instructions; remove stray lines

The overall flow is helpful, but a few tweaks would reduce confusion:

  • There are two nearly identical PR workflows (Lines 14–56 vs 59–72). Consider consolidating into one generic “create branch + PR” section with placeholders instead of hard‑coding open-image-issue and then repeating my-branch.
  • Commands like .\.venv\Scripts\activate are Windows‑specific; if contributors use macOS/Linux, a short note with the corresponding source .venv/bin/activate variant would help.
  • The trailing lines palisaders, sugarlabs, oppis at the end look accidental and should probably be removed.

None of this blocks the PR, but cleaning it up will make the doc easier for others to follow.

frontend/src/components/Media/ShareOptionsModal.tsx (3)

44-62: Align share flow behavior and disable “More options” when no path

A couple of small points around the share actions:

  • The onShare flow looks reasonable, and you correctly guard on missing filePath. However, the “More options” button is styled as disabled when there’s no filePath but not actually disabled, so it’s still focusable/clickable (and just logs a warning). For better accessibility and consistency with the OneDrive button, also set disabled={!filePath}.
         <button
-          onClick={onShare}
-          className={`inline-flex items-center gap-2 rounded border border-white/10 px-3 py-2 text-sm font-medium ${filePath ? 'hover:bg-white/5' : 'cursor-not-allowed opacity-50'}`}
+          onClick={onShare}
+          disabled={!filePath}
+          className={`inline-flex items-center gap-2 rounded border border-white/10 px-3 py-2 text-sm font-medium ${
+            filePath ? 'hover:bg-white/5' : 'cursor-not-allowed opacity-50'
+          }`}
           aria-label="Using more options"
         >
  • shareUrl from invoke<string>('onedrive_share', …) is only logged. If the native side doesn’t use that URL, consider either wiring it into the sharing logic or dropping the call/log to avoid an extra round‑trip.

Also applies to: 116-137


68-89: Optional: improve dialog accessibility labelling

You already set role="dialog" and aria-modal="true", which is good. For better screen‑reader support, consider tying the dialog to its title via aria-labelledby:

-    <div
-      className="absolute top-20 left-5 z-50 w-[360px] max-w-full rounded-lg bg-black/80 p-3 text-white backdrop-blur-md shadow-lg"
-      role="dialog"
-      aria-modal="true"
-    >
+    <div
+      className="absolute top-20 left-5 z-50 w-[360px] max-w-full rounded-lg bg-black/80 p-3 text-white backdrop-blur-md shadow-lg"
+      role="dialog"
+      aria-modal="true"
+      aria-labelledby="share-options-title"
+    >
       {/* Header */}
       <div className="flex items-start justify-between gap-2">
         <div>
-          <h3 className="text-lg font-semibold">More share options</h3>
+          <h3 id="share-options-title" className="text-lg font-semibold">
+            More share options
+          </h3>

Not mandatory, but it makes the modal more accessible.


103-113: Clarify “Copy file” vs “Copy file path” behavior

Both the header button and the “Copy file” tile call copyPath, which copies the path, not the file content. That’s fine functionally, but the naming could be confusing:

  • Consider renaming the tile label to “Copy path” (or similar), or
  • Implement a real “copy/move file” behavior via the Tauri FS plugin for that tile and keep the existing “Copy file path” semantics for the header button.

This is mostly UX polish; the current implementation is safe.

Also applies to: 142-153

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0088342 and 2273a0a.

⛔ Files ignored due to path filters (2)
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • frontend/src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • .gitignore (1 hunks)
  • frontend/package.json (1 hunks)
  • frontend/src-tauri/Cargo.toml (1 hunks)
  • frontend/src-tauri/capabilities/opener.json (1 hunks)
  • frontend/src/components/Media/ImageCard.tsx (1 hunks)
  • frontend/src/components/Media/MediaInfoPanel.tsx (8 hunks)
  • frontend/src/components/Media/ShareOptionsModal.tsx (1 hunks)
  • frontend/tsconfig.json (1 hunks)
  • run.txt (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • frontend/tsconfig.json
  • .gitignore
  • frontend/src/components/Media/ImageCard.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/components/Media/MediaInfoPanel.tsx
  • frontend/src-tauri/capabilities/opener.json
🔇 Additional comments (1)
frontend/package.json (1)

42-42: and

@NikhilPatil2005
Copy link
Author

Please review again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working frontend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments