feat(sidebar): select several databases or schemas and act on them at once - #2094
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. |
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 user asked whether they could select several databases and act on them together, for example to delete them. They could not: database and schema rows were not selectable at all, and Drop Database was single-name from one menu.
What changed
Sidebar tree. Database and schema rows are selectable.
outlineView(_:shouldSelectItem:)gated ontableRef != nil, so containers could never be selected, let alone multi-selected. Shift-click and Cmd-click extend the selection. The context menu acts on the selection and names its count: Refresh, Copy N Names, Export..., and a destructive Drop N Databases.... Use as Active stays single-target and disables while more than one row is selected.Database switcher. Selection moves from
String?toSet<String>. ItscontextMenu(forSelectionType:)already receives the correctly resolved set from SwiftUI, so the fix was to stop calling.first. Same four actions.Targeting.
SidebarMenuTargetis one pure resolver implementing AppKit'sclickedRowconvention: clicked row inside the selection means the whole selection, outside means the clicked row alone. Mixed selections filter to the clicked row's kind.Schema drop.
dropSchemaandsupportsDropSchemaadded to PluginKit with defaults, bridged throughPluginDriverAdapter. Implemented for PostgreSQL (DROP SCHEMA ... CASCADE), SQL Server (T-SQL has no cascade, so a non-empty schema is refused by the server) and SurrealDB (REMOVE DATABASE, since its schema level is a Surreal database). A schema in a non-active database drops through a scoped metadata driver, so the statement runs against the right database instead of the connected one.Export.
ExportPreselectionreplaces the bareSet<String>and matches by qualified container instead of bare table name.ExportDialog.loadDatabaseItems()already built a multi-database tree, so this is preselection plumbing rather than a new export path. Export is hidden for a schema outside the connected database, because the dialog only enumerates that database's schemas and would preselect nothing.Confirmation. One dialog for the whole set: the title counts the targets, the message lists every name (capped at 10 plus an overflow count), and the destructive button names the count. Drops run sequentially, a failure never stops the rest, and the failures are reported together at the end.
Bugs fixed on the way
Color.accentColor, so they rendered accent-on-accent against the selection fill. They now go through\.backgroundProminence, the documented signal for content on a prominent selection background, which is what the sidebar rows already used. The helper moved out ofViews/Sidebarsince it is no longer sidebar-only. Multi-select made this obvious, but it affected single selection too.refreshDatabasesandrefreshSchemascleared the cache before refetching, which is the "a refresh never clears the cache it is refreshing" invariant (Multiple UI Flicker #1916): the tree rendered.loadingwith no content as a spinner. Both now fetch first and commit over the old value, and a failed refresh keeps what is on screen.PluginKit ABI
Additive, so no
currentPluginKitVersionbump.scripts/check-pluginkit-abi.sh mainreports a diff with zero removed symbols; the only additions are the two new requirements, each with its default implementation. That is the case CLAUDE.md documents as binary-compatible. Labelledabi-additiveper the gate's instructions.Testing
swiftlint lint --strictclean.TableProscheme builds; theAllPluginsaggregate compiles all 30, which is what covers MSSQL and SurrealDB since neither is bundled.No UI automation was added.
TableProUITestsdrives the sample database, which is SQLite, andsupportsDatabaseTreerequires a network connection mode, so neither the tree nor the switcher is reachable without a live server. The behaviour that could be made deterministic went into pure types instead.Follow-up: plugin release (after merge)
MSSQL and SurrealDB are registry-only, so their schema drop reaches users only through a plugin release. PostgreSQL ships with the app and needs nothing.
There is nothing to change in the repo for it: the plugin version comes from the tag name, and
TableProPluginKitVersionstays at 19 in both Info.plists because the ABI change is additive. One dispatch onmainafter this merges:Versions follow the latest existing tags (
plugin-mssql-v1.0.34,plugin-surrealdb-v1.0.2). PluginKit defaults to 19 fromPluginManager.swift, which is correct here. Dispatch onmainrather than this branch so the published binaries match what was reviewed; the workflow refuses to overwrite a release carrying a different PluginKit label, so a build from the wrong ref costs a version number.A new plugin on an older app is inert rather than harmful: the old app has no drop-schema UI to read the capability with.