fix(connections): keep a window navigable when its selected connection goes away - #2558
Merged
Merged
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
|
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 realConnectionWindowChromeTestsharness onafad18de0: two workspaces, strip visible, selected connection disconnected by the user givessidebarChromeMode == .railOnly. The strip survives.What was still broken
The strip could still be absent when it was the only route left.
shouldShowWorkspaceRailwassettingEnabled && 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.railOnlypreserves a strip that is already up. Nothing brought one back.Database > Switch Connection…was disabled exactly when it was needed. Measuredfalseafter a disconnect. It validated oncontext.isConnectedand ran through the dying connection'scommandActions, both of which go with the session. It is the only route to a connection that is not open yet, anddocs/features/workspace-rail.mdxnames 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.
quickSwitcherPanelandswitcherPresenterwere 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.applyPaneChromesettles 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 onhasSelectedWorkspace, the toolbar's control stays rendered with no connection behind it, and both it and the overflow entry answer throughToolbarSubject.windowControllerrather than the coordinator.Open Quicklystays connection-scoped and correctly disabled, because it searches that connection's own objects. The window owns the singleToolbarSwitcherPresenterand 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
ConnectionUnavailableViewstays aContentUnavailableViewin 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
buildtest(6 suites, 71 cases)lint TablePro TableProTests TableProUITestsdocsuitestSwitchConnectionAfterDisconnectUITestscould 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 (
reviewandadversarial-review). Four findings, all acted on: the toolbar route still going through the coordinator, the window-owned panel outliving its window,.emptystill obeying the preference outside a close, and the toolbar control disappearing rather than staying reachable.