Skip to content

feat(connections): open a connection in a dedicated window#409

Open
debba wants to merge 1 commit into
mainfrom
feat/open-connection-in-new-window
Open

feat(connections): open a connection in a dedicated window#409
debba wants to merge 1 commit into
mainfrom
feat/open-connection-in-new-window

Conversation

@debba

@debba debba commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Overview

Adds an "Open in New Window" action to the connection context menus (the open-connections sidebar rail and the Connections page) that opens a connection in its own standalone window, together with the cross-window plumbing needed to keep connection state consistent across every window.

Behaviour

Opening

  • Validate before spawning. The connection is test_connection'd first; the window is created only if the connection succeeds. A failing connection now surfaces the error in the originating window (with a spinner on the card while validating) instead of opening an empty window that then errors.
  • If the connection is already open somewhere, validation is skipped — the window is opened (or an existing one is focused) directly.

Ownership & sidebar

  • A connection opened in a new window is "owned" by that window and is detached from the originating window's sidebar rail. The process-global pool stays warm and is reused by the new window (no reconnect round-trip).

Cross-window state sync

  • Connection open-state is now shared across all windows: a connection open in any window shows as open in every window's Connections page (badge, card styling, connect/disconnect action).
  • Implemented on top of the existing health-check active-connection registry, broadcast via a new connections:active-changed event and seeded on window start via get_active_connections.

Lifecycle

  • Disconnecting a connection closes its dedicated window — from anywhere. The main window is never auto-closed.
  • Closing a dedicated window also tears down its bound connection, so nothing leaks.

Guards

  • "Open in New Window" is disabled when the current window has no open connection.

Implementation

Backend (src-tauri/)

  • connection_window.rs (new): open_connection_window command — creates/focuses a connection-window-<id> window loading /?connect=<id>; a CloseRequested handler disconnects the bound connection on close.
  • capabilities/default.json: whitelist connection-window-*.
  • health_check.rs: broadcast the active-connection set on register / disconnect / health-failure; add active_connections() + emit_active_changed().
  • commands.rs: register_active_connection and disconnect_connection now emit the broadcast; new get_active_connections command.

Frontend (src/)

  • New hooks: useOpenConnectionInNewWindow (validate → open → detach), useAutoConnectFromUrl (auto-connect the dedicated window on startup), useConnectionWindowLifecycle (close the dedicated window when its connection goes away).
  • DatabaseProvider: globallyOpenConnectionIds + isConnectionOpenAnywhere, plus a detachConnection helper (removes from a window's UI without closing the pool).
  • Connections page / cards: reflect global open-state; "Open in New Window" menu entry + disabled guard.
  • i18n: sidebar.openInNewWindow added to all 8 locales.

Tests / cleanup

  • Unit tests for useOpenConnectionInNewWindow, useAutoConnectFromUrl, useConnectionWindowLifecycle, and the Rust window-label sanitizer.
  • Removed the now-unused hasConnectionMenuItems helper and its tests.

Verification

  • npm run build (tsc -b + vite) — ✅
  • npm run lint — ✅ 0 errors
  • npx vitest run — ✅ 2706 passed
  • cargo test — ✅ 770 passed
  • cargo clippy --all-targets — ✅ 0 errors

Notes

  • GitNexus MCP was not connected during development, so gitnexus_detect_changes / impact analysis could not be run; changes are largely additive.

Add an "Open in New Window" action to both connection context menus (the
open-connections sidebar rail and the Connections page) that opens a
connection in its own standalone window, plus the cross-window plumbing to
keep everything consistent.

Behaviour:
- Validate connectivity BEFORE spawning the window: the connection is
  test_connection'd first and the window is only created on success, so a
  failing connection surfaces the error in the originating window instead of
  in a freshly-opened empty one.
- A connection opened in a new window is "owned" by that window: it is
  detached from the originating window's sidebar rail (its process-global
  pool stays warm and is reused by the new window).
- Connection open-state is shared across all windows: a connection open in
  any window shows as open in every window's Connections page. Backed by the
  health-check active-connection registry, broadcast via a new
  `connections:active-changed` event and seeded through get_active_connections.
- Disconnecting a connection closes its dedicated window (the main window is
  never auto-closed). Closing a dedicated window also tears down its
  connection so nothing leaks.
- "Open in New Window" is disabled when the current window has no open
  connection.

Backend:
- New connection_window module (open_connection_window command) with a
  CloseRequested handler that disconnects the bound connection; window label
  connection-window-* added to capabilities.
- health_check: broadcast the active-connection set on register/disconnect/
  health-failure; add active_connections() + get_active_connections command.

Frontend:
- New hooks: useOpenConnectionInNewWindow, useAutoConnectFromUrl,
  useConnectionWindowLifecycle.
- DatabaseProvider: globallyOpenConnectionIds + isConnectionOpenAnywhere and
  a detachConnection helper; Connections page / cards reflect global state.
- i18n key sidebar.openInNewWindow added to all 8 locales.

Tests: unit tests for the new hooks and the window-label sanitizer; removed
the now-unused hasConnectionMenuItems helper and its tests.
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