Enable safe multi-connection cleanup from the sidebar (#816)

The sidebar already supports multi-select, so deletion now resolves the context-clicked selected connection set before confirming. Connection removal gained a batched path to persist once while pruning sidebar layout, pins, active state, connection errors, and stale selection for every removed connection.

Constraint: No new dependencies and existing single-connection delete behavior must remain available.\nRejected: Delete every selected tree item regardless of type | mixed tree selections could unexpectedly remove connections while table/object deletion has separate SQL confirmation behavior.\nConfidence: high\nScope-risk: narrow\nTested: pnpm fmt; pnpm test; pnpm typecheck; pnpm lint; pnpm build\nNot-tested: Manual desktop UI interaction against a running Tauri window

Co-authored-by: caisin <caisin@caisins-Mac-mini.local>
This commit is contained in:
Caisinandcaisin authored and GitHub committed 2026-06-07 16:58:49 +08:00
1 parent 74e19ec6a3
commit 13363b9094
10 files changed
+137 -19

No files matched your search

+27 -8
View File
@@ -584,21 +584,39 @@ export const useConnectionStore = defineStore("connection", () => {
}
}
async function removeConnection(id: string) {
const nextConnections = connections.value.filter((c) => c.id !== id);
async function removeConnections(ids: Iterable<string>) {
const connectionIds = [...new Set(ids)].filter((id) => connections.value.some((c) => c.id === id));
if (!connectionIds.length) return;
const removedIds = new Set(connectionIds);
const nextConnections = connections.value.filter((c) => !removedIds.has(c.id));
await persistConnections(nextConnections);
connections.value = nextConnections;
pinnedTreeNodeIds.value = prunePinnedTreeNodeIdsForConnection(pinnedTreeNodeIds.value, id);
for (const id of removedIds) {
pinnedTreeNodeIds.value = prunePinnedTreeNodeIdsForConnection(pinnedTreeNodeIds.value, id);
}
persistPinnedTreeNodeIds();
clearConnectionError(id);
sidebarLayout.value = removeConnectionFromSidebarLayout(sidebarLayout.value, id);
for (const id of removedIds) {
clearConnectionError(id);
connectedIds.value.delete(id);
sidebarLayout.value = removeConnectionFromSidebarLayout(sidebarLayout.value, id);
}
rebuildTreeNodes();
persistSidebarLayoutDebounced();
if (activeConnectionId.value === id) {
if (activeConnectionId.value && removedIds.has(activeConnectionId.value)) {
activeConnectionId.value = null;
}
invalidateCompletionCache(id);
clearLoadedChildrenCache(id);
selectedTreeNodeIds.value = selectedTreeNodeIds.value.filter((id) => !removedIds.has(id));
if (selectedTreeNodeId.value && removedIds.has(selectedTreeNodeId.value)) selectedTreeNodeId.value = null;
if (treeSelectionAnchorId.value && removedIds.has(treeSelectionAnchorId.value)) treeSelectionAnchorId.value = null;
for (const id of removedIds) {
invalidateCompletionCache(id);
clearLoadedChildrenCache(id);
}
}
async function removeConnection(id: string) {
await removeConnections([id]);
}
async function updateConnection(config: ConnectionConfig) {
@@ -2126,6 +2144,7 @@ export const useConnectionStore = defineStore("connection", () => {
setVisibleDatabases,
clearVisibleDatabases,
removeConnection,
removeConnections,
editingConnectionId,
newConnectionGroupId,
startEditing,