Skip to content

v0.1.9 — actually route external links to OS browser - #2

Merged
AminChirazi merged 1 commit into
mainfrom
fix/external-open-scope
May 5, 2026
Merged

v0.1.9 — actually route external links to OS browser#2
AminChirazi merged 1 commit into
mainfrom
fix/external-open-scope

Conversation

@AminChirazi

Copy link
Copy Markdown
Contributor

Summary

v0.1.8 shipped the host-based split logic for target="_blank" clicks (internal hosts in-window, external hosts via shell:open) — but two bugs prevented shell:open from ever succeeding, so external links (SharePoint, Office.com, OneDrive, customer sites) kept opening inside the desktop window instead of in the system browser. v0.1.9 fixes the actual delivery.

Bugs

1. Capability had no URL scope

shell:allow-open was listed as a bare string in capabilities/default.json. Tauri 2 reads that as "command allowed, scope = empty", so every shell:open invoke was rejected with "url not allowed by scope" at the rust side before reaching the OS browser.

Fix: attach an explicit allow scope to the permission covering the actual destinations:

{
  "identifier": "shell:allow-open",
  "allow": [
    { "url": "https://**" },
    { "url": "http://**" },
    { "url": "mailto:*" }
  ]
}

2. openExternal() lied about success

The wrapper used a synchronous try/catch around invoke():

try {
  window.__TAURI_INTERNALS__.invoke('plugin:shell|open', { path: href });
  return true;
} catch (e) { return false; }

But invoke() returns a Promise. The synchronous catch caught nothing; the function returned true even when the IPC asynchronously rejected. The safety-net fallback in the click handler never fired — leaving either a dead click or (on some WKWebView builds) a fallthrough the WebView resolved as in-window navigation.

Fix: return a real Promise from openExternal, await it in the click handler, fall back to window.location.href only when the Promise resolves to false. Same fix applied to the window.open override.

What's still v0.1.8 behavior

  • Internal-host links (internal.automators.com, auth.automators.com) → in-window navigation.
  • Modifier-clicks (⌘-click, middle-click) → untouched, default WebView handling.
  • Drag region, back/forward shortcuts, sidebar CSS overrides → unchanged.

Test plan

  • Build new release, install on macOS
  • In /sales or /decks: click any SharePoint file card (Excel/Word/PowerPoint) → opens in default browser, NOT inside the app
  • Click "Capacities" in sidebar → opens in default browser
  • Click an internal cross-link (e.g. /sales → customer detail) → still navigates in-window
  • ⌘-click any link → still goes through default WebView handling

Release

Updater is configured in tauri.conf.json to pull from GitHub Releases latest.json. Once the release is cut, existing v0.1.8 installs auto-download v0.1.9 in the background and use it on next quit/relaunch.

🤖 Generated with Claude Code

v0.1.8 shipped the host-based split logic but two bugs prevented
shell:open from succeeding, so external links (SharePoint,
Office.com, OneDrive, customer sites) opened in-window instead of
in the system browser.

Bug 1 — capability had no URL scope
The shell:allow-open permission was listed as a bare string in
capabilities/default.json. Tauri 2 reads that as "command
allowed, scope = empty", so every shell:open invoke rejected with
"url not allowed by scope" before reaching the OS handler.
Attaching an explicit allow array (https://**, http://**,
mailto:*) makes the scope match real-world destinations.

Bug 2 — openExternal lied about success
The wrapper used a synchronous try/catch around invoke(), which
returns a Promise. The catch caught nothing; the function
returned true even when the IPC asynchronously rejected. The
safety-net fallback in the click handler never fired, leaving
either a dead click or (on some WKWebView builds) a fallthrough
that the WebView resolved as in-window navigation. Returning a
real Promise lets the caller await the actual outcome and route
to in-window navigation when shell:open genuinely fails.

window.open() got the same fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 5, 2026 11:27

Copilot AI 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.

Pull request overview

This PR fixes the Tauri desktop shell’s external-link routing so non-internal target="_blank" and window.open(...) navigations are actually handed off to the OS browser instead of remaining in the app window. It fits into the desktop wrapper by correcting the shell permission scope and the injected WebView link-handling logic introduced in v0.1.8.

Changes:

  • Adds an explicit shell:allow-open URL scope for https, http, and mailto destinations in the default Tauri capability.
  • Changes the injected openExternal() helper to return a real Promise and updates click / window.open handling to wait for the actual shell-open result before falling back.
  • Bumps the app version to 0.1.9 across Tauri, Cargo, lockfile, and package metadata.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src-tauri/tauri.conf.json Bumps the Tauri app version to 0.1.9.
src-tauri/src/lib.rs Fixes injected external-link handling to use async shell:open result correctly.
src-tauri/Cargo.toml Bumps the Rust package version to 0.1.9.
src-tauri/Cargo.lock Updates the lockfile’s root package version entry.
src-tauri/capabilities/default.json Adds the URL allow-scope required for shell:open to succeed.
package.json Bumps the JS package version to 0.1.9.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@AminChirazi
AminChirazi merged commit 6b3f69f into main May 5, 2026
5 checks passed
@AminChirazi
AminChirazi deleted the fix/external-open-scope branch May 5, 2026 11:45
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.

2 participants