Skip to content

fix(connections): keep a window navigable when its selected connection goes away - #2558

Merged
datlechin merged 2 commits into
mainfrom
fix/disconnected-workspace-navigation
Aug 27, 2026
Merged

fix(connections): keep a window navigable when its selected connection goes away#2558
datlechin merged 2 commits into
mainfrom
fix/disconnected-workspace-navigation

Conversation

@datlechin

Copy link
Copy Markdown
Member

A window's own navigation was re-derived, in four places, from things that do not belong to the window: the selected connection's phase, a user preference, and the app-wide strip store. Any one of them could leave a window that hosts other live connections with no way to reach them.

Reported from a screen recording: three connections in one window, Disconnect on the selected one, and the window became a full-bleed "Disconnected from Atalanta" pane with no strip, no sidebar, no tab strip and a dead toolbar.

What was already fixed

That exact recording no longer reproduces. It predates #2551, which added SidebarChromeMode.railOnly. Measured against the real ConnectionWindowChromeTests harness on afad18de0: two workspaces, strip visible, selected connection disconnected by the user gives sidebarChromeMode == .railOnly. The strip survives.

What was still broken

The strip could still be absent when it was the only route left. shouldShowWorkspaceRail was settingEnabled && workspaceCount > 1, with no term for "this is currently the only visible route". A pane with no content takes the object browser, the tab strip and every connection-scoped toolbar item with it; with Settings > General > Show connections off there was no strip either, and the window had nothing on screen naming any other connection. railOnly preserves a strip that is already up. Nothing brought one back.

Database > Switch Connection… was disabled exactly when it was needed. Measured false after a disconnect. It validated on context.isConnected and ran through the dying connection's commandActions, both of which go with the session. It is the only route to a connection that is not open yet, and docs/features/workspace-rail.mdx names it as the recovery route. #2551 re-homed Show Previous/Next Connection off the coordinator and left this one behind.

One window held one floating switcher panel per connection. quickSwitcherPanel and switcherPresenter were per coordinator, so a window hosting three connections had three, all anchored on the same window frame and centred on the same point, with none able to see or dismiss the others. ToolbarSwitcherPresenter's own doc comment warns about exactly this.

The fix

ConnectionWindowPaneResolver.showsWorkspaceRail(preferenceEnabled:workspaceCount:pane:isClosing:) is the one rule for the strip. It stands whenever the pane hides the window's chrome and the app has more than one workspace, whatever the preference says, and goes back to obeying the preference once there is content to navigate by. Closing is an explicit input rather than read off the pane, because a closing window and a workspace whose connection never resolved both land on .empty.

applyPaneChrome settles the strip before anything standing on it, so a phase change can bring a hidden strip back, and so the sidebar clamp reads a width the strip's constraints actually report.

Switch Connection is presented by MainSplitViewController. The Database menu item validates on hasSelectedWorkspace, the toolbar's control stays rendered with no connection behind it, and both it and the overflow entry answer through ToolbarSubject.windowController rather than the coordinator. Open Quickly stays connection-scoped and correctly disabled, because it searches that connection's own objects. The window owns the single ToolbarSwitcherPresenter and its panel, and dismisses it on close, which the toolbar could no longer do once a released connection left it with no coordinator to reach it through.

The strip is a cross-window switcher by design (WorkspaceRailViewController: "Every rail lists every workspace", and activating a row raises the window hosting it), so its app-wide count stays app-wide. An earlier draft scoped it to the window; three independent reviewers rejected that with the same evidence.

Deliberately unchanged

ConnectionUnavailableView stays a ContentUnavailableView in the detail pane. It is the Apple-sanctioned empty-state API and the pane genuinely has no content; the "whole window" impression was the chrome collapsing around it. The window does not auto-select a live sibling on disconnect: that is unrequested navigation, it loses the tab the user was on, and Apple Mail keeps an offline account listed and badged rather than replacing the window.

Verification

Step Result
build PASS
test (6 suites, 71 cases) PASS
lint TablePro TableProTests TableProUITests 0 violations
docs PASS
uitest INCONCLUSIVE, twice

SwitchConnectionAfterDisconnectUITests could not run on this machine: Failed to initialize for UI testing: Timed out while enabling automation mode, on both attempts, before any case started. That is an unanswered macOS authorization prompt, not the test, and it blocks every UI test here equally. CI runs it.

Reviewed by Codex (review and adversarial-review). Four findings, all acted on: the toolbar route still going through the coordinator, the window-owned panel outliving its window, .empty still obeying the preference outside a close, and the toolbar control disappearing rather than staying reachable.

@mintlify

mintlify Bot commented Aug 27, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
TablePro 🟢 Ready View Preview Aug 27, 2026, 9:14 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Signed-off-by: Ngô Quốc Đạt <datlechin@gmail.com>
@datlechin
datlechin merged commit d925650 into main Aug 27, 2026
5 checks passed
@datlechin
datlechin deleted the fix/disconnected-workspace-navigation branch August 27, 2026 09:15
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