Skip to content

fix: route Desktop loopback links and modifier-clicks to system browser - #187

Merged
cnjack merged 1 commit into
mainfrom
desktop-loopback-links
Aug 12, 2026
Merged

fix: route Desktop loopback links and modifier-clicks to system browser#187
cnjack merged 1 commit into
mainfrom
desktop-loopback-links

Conversation

@cnjack

@cnjack cnjack commented Aug 12, 2026

Copy link
Copy Markdown
Owner

What

  • initExternalLinks now returns a cleanup function that removes the delegated click listener.
  • On Tauri Desktop, loopback (localhost preview) links and Command/Ctrl-clicks are routed through the system browser — the webview cannot open new tabs, so these gestures were previously dead.
  • Browser Web keeps its native behavior: Command/Ctrl-click new-tab and loopback navigation are untouched.
  • Adds unit tests covering Desktop (ordinary click / Command-click / Ctrl-click on localhost) and Browser Web modifier-click behavior.

Why

In the Desktop app, localhost preview links and modifier-clicks did nothing because Tauri's webview denies new-window creation, and the old listener skipped both modifier-clicks and loopback URLs entirely. API traffic uses fetch/WebSocket rather than anchor navigation, so routing loopback anchors externally is safe.

Testing

  • npx vitest run src/lib/useDesktop.test.ts — 5/5 passed

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved external-link handling in the desktop app.
    • Command-click and Ctrl-click now open loopback links in the system browser as expected.
    • Preserved native modifier-click behavior for HTTPS links in browser mode.
    • Improved link navigation reliability while maintaining existing URL validation and filtering.

initExternalLinks now returns a cleanup function. On Tauri Desktop,
loopback (localhost preview) links and Command/Ctrl-clicks are routed
through the system browser since the webview cannot open new tabs;
Browser Web keeps native modifier-click and loopback navigation
behavior. Add unit tests covering both environments.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

initExternalLinks now returns cleanup logic and routes desktop loopback and modifier-click links through Tauri. Browser mode preserves native modifier-click behavior. Tests cover routing, browser behavior, and per-test isolation.

Changes

External link handling

Layer / File(s) Summary
Link routing and cleanup
web/src/lib/useDesktop.ts
initExternalLinks uses a named delegated click handler, returns an unsubscribe function, routes eligible desktop links through Tauri, and preserves browser navigation behavior.
Link routing validation
web/src/lib/useDesktop.test.ts
Tests mock Tauri and reset test state. Tests cover localhost links with click modifiers and native browser HTTPS modifier-click behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant initExternalLinks
  participant TauriOpenUrl
  participant SystemBrowser
  User->>initExternalLinks: Click external or loopback link
  initExternalLinks->>TauriOpenUrl: Open eligible desktop link
  TauriOpenUrl->>SystemBrowser: Open URL
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 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 Desktop link-routing changes in the pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch desktop-loopback-links

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.

@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)
web/src/lib/useDesktop.test.ts (1)

39-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test listener removal after cleanup().

Line 53 calls cleanup(), but the test does not verify that the delegated listener was removed. The test can pass if a stale listener remains registered. Add a second click after cleanup. Assert that the router does not prevent the event or call mocks.openUrl.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/lib/useDesktop.test.ts` around lines 39 - 53, Extend the
initExternalLinks test to dispatch a second click on the anchor after cleanup().
Assert that this post-cleanup event is not prevented and that mocks.openUrl is
not called again, verifying the delegated listener was removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@web/src/lib/useDesktop.test.ts`:
- Around line 39-53: Extend the initExternalLinks test to dispatch a second
click on the anchor after cleanup(). Assert that this post-cleanup event is not
prevented and that mocks.openUrl is not called again, verifying the delegated
listener was removed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 48e33739-19c1-4e36-8887-7fd2a39aab51

📥 Commits

Reviewing files that changed from the base of the PR and between 675c353 and 6ee95b3.

📒 Files selected for processing (2)
  • web/src/lib/useDesktop.test.ts
  • web/src/lib/useDesktop.ts

@jcode-cloud-app jcode-cloud-app 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.

Note

No high-confidence findings

No findings met the configured confidence threshold.

Summary

Clean. initExternalLinks now returns a cleanup fn and routes Desktop loopback links + Cmd/Ctrl-clicks to the system browser. Browser Web behavior is provably unchanged (modifier/shift/alt still early-return; loopback still early-returns; external still calls openUrl). In Desktop the page origin is tauri://localhost while the sidecar API is http://127.0.0.1:<port>, so no http link is same-origin and in-app routing uses relative links (skipped by the http/https guard) — API traffic uses fetch/WebSocket, never anchor nav, so routing loopback clicks outward fixes the prior dead webview navigation without regressions. The sole caller (main.tsx) ignores the new return value, which is valid TS. No defect meets the 80% confidence bar.

🔍 Checks performed · 9
  • Read web/src/lib/useDesktop.ts (initExternalLinks, isLoopback, isTauri, openUrl)
  • Read web/src/lib/useDesktop.test.ts (Desktop + Browser Web cases)
  • Read web/src/main.tsx: sole caller ignores the new cleanup return (valid)
  • Read web/src/lib/apiBase.ts: Desktop sidecar = http://127.0.0.1:<port>
  • Read web/src/App.tsx:303: Desktop page served from tauri://localhost (cross-origin to API)
  • Grepped web/src for href={ and loopback references (SettingsView external URLs, ArtifactsPanel share URL)
  • Inspected ArtifactsPanel.tsx: result.url is a backend/cloud share URL, not loopback
  • Traced before/after logic per environment: Browser Web identical; Desktop adds loopback + modifier routing
  • node_modules absent and pnpm unavailable in env; vitest not executed, relied on static analysis

jcode posts a non-blocking COMMENT review. Merge decisions remain with your team.

@cnjack
cnjack merged commit 368ca39 into main Aug 12, 2026
4 checks passed
@cnjack
cnjack deleted the desktop-loopback-links branch August 12, 2026 02:52
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.

1 participant