Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
131f1e9
feat(connections): let a connection be tried before it has to be save…
deveshk0 Sep 8, 2026
8bc5168
fix(connections): close the three ways the save offer could mislead (…
deveshk0 Sep 8, 2026
64b48e4
fix(connections): give back a connection nobody is waiting for (#369 …
deveshk0 Sep 8, 2026
4030f18
test(indexes): wait for the schema fields, not just for the call (#36…
deveshk0 Sep 8, 2026
9f1edcc
fix(connections): stop an unsaved connection leaking into places it c…
deveshk0 Sep 8, 2026
da23591
fix(connections): keep an unsaved tab out of the mirrored split, and …
deveshk0 Sep 8, 2026
204169b
Revert "split_pane" half of da23591 — it needs a product decision, no…
deveshk0 Sep 8, 2026
41887aa
fix(connections): let the offer describe the connection that was made…
deveshk0 Sep 8, 2026
9f31a2f
fix(sidebar): refuse a shortcut that could not survive a restart (#36…
deveshk0 Sep 8, 2026
7c49485
fix(connections): show the URI that was connected, and decide shortcu…
deveshk0 Sep 8, 2026
c866ab2
fix(connections): stop an unsaved session answering to a saved profil…
deveshk0 Sep 8, 2026
c5bc1fb
fix(connections): keep an unsaved session out of a saved profile's qu…
deveshk0 Sep 8, 2026
a377e30
fix(connections): take Math.random out of an id that now keys storage…
deveshk0 Sep 8, 2026
b6d91fd
fix(connections): finish isolating an unsaved session's query, chat a…
deveshk0 Sep 8, 2026
6b48634
fix(connections): let only the current attempt release the Connect bu…
deveshk0 Sep 8, 2026
7385899
fix(connections): isolate history writes and the shell assistant, and…
deveshk0 Sep 8, 2026
1a08ba1
fix(connections): read ephemeral from the profile, and release a sess…
deveshk0 Sep 8, 2026
6d29038
fix(connections): make the post-await ownership checks actually able …
deveshk0 Sep 8, 2026
aa66bd5
fix(connections): retarget a trial connection's chats under its own i…
deveshk0 Sep 8, 2026
c942548
fix(connections): stop the name suggestion renaming a profile called …
deveshk0 Sep 9, 2026
29c33ff
fix(connections): advance the attempt generation when the editor clos…
deveshk0 Sep 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
477 changes: 446 additions & 31 deletions src/components/ConnectionManager.tsx

Large diffs are not rendered by default.

52 changes: 44 additions & 8 deletions src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
favoriteItemSubtitle,
favoriteItemKey,
} from '../lib/favoriteItems';
import { isEphemeralProfileId } from '../workspace/persistence';
import {
listAllSavedQueries,
QUERIES_CHANGED_EVENT,
Expand Down Expand Up @@ -724,9 +725,40 @@ export const Sidebar: React.FC<SidebarProps> = ({
return { kind: 'connection', connectionName: conn.name };
};

const handleTogglePin = (entry: PinnedItem) => {
/**
* Whether a shortcut to this connection could survive a restart.
*
* Pins and favourites are stored by connection NAME and resolved on the way
* back by `ensureConnection`, which looks that name up among *saved
* profiles*. A connection the user chose not to save has no profile to
* resolve to, so a shortcut to it — or to any database or collection inside
* it — could only ever come back as "no saved connection" (#369 review).
*
* Guarded here rather than at the six menu items that build these entries:
* one choke point cannot be half-applied, and connection, database and
* collection shortcuts all fail for the same reason.
*/
// Takes the id of the connection the shortcut is being made FROM, never its
// name. Duplicate profile names are supported and a trial connection's name
// is editable, so a name can match a different, saved connection — and a
// name-based check would then clear the shortcut for the wrong server
// (#369 review).
const canOutliveTheSession = (connId: string): boolean => {
const conn = activeConnections.find((c) => c.id === connId);
// Unknown means gone, not ephemeral — never block removing an existing
// shortcut for a connection that is no longer open.
return !conn || !isEphemeralProfileId(conn.profileId);
};

const handleTogglePin = (entry: PinnedItem, connId: string) => {
try {
const wasPinned = isItemPinned(pinnedItems, entry);
// Only adding is refused. Removing has to keep working whatever the
// entry points at, or a shortcut could become impossible to clear.
if (!wasPinned && !canOutliveTheSession(connId)) {
Comment thread
deveshk0 marked this conversation as resolved.
Outdated
toast(t('toasts.shortcutNeedsSavedConnection', { name: entry.connectionName }), 'error');
return;
}
const next = togglePinItem(pinnedItems, entry);
setPinnedItems(next);
if (!wasPinned) {
Expand All @@ -738,9 +770,13 @@ export const Sidebar: React.FC<SidebarProps> = ({
}
};

const handleToggleFavorite = (entry: FavoriteItem) => {
const handleToggleFavorite = (entry: FavoriteItem, connId: string) => {
try {
const wasFav = isItemFavorited(favoriteItems, entry);
if (!wasFav && !canOutliveTheSession(connId)) {
toast(t('toasts.shortcutNeedsSavedConnection', { name: entry.connectionName }), 'error');
return;
}
const next = toggleFavoriteItem(favoriteItems, entry);
setFavoriteItems(next);
if (!wasFav) {
Expand Down Expand Up @@ -1479,7 +1515,7 @@ export const Sidebar: React.FC<SidebarProps> = ({
connectionName: conn.name,
db: dbName,
collection: collName,
});
}, connId);
}
}}
>
Expand Down Expand Up @@ -1508,7 +1544,7 @@ export const Sidebar: React.FC<SidebarProps> = ({
connectionName: conn.name,
db: dbName,
collection: collName,
});
}, connId);
}
}}
>
Expand Down Expand Up @@ -1848,7 +1884,7 @@ export const Sidebar: React.FC<SidebarProps> = ({
data-testid={`ctx-pin-conn-${conn.id}`}
onSelect={() => {
const entry = pinEntryForConnection(conn.id);
if (entry) handleTogglePin(entry);
if (entry) handleTogglePin(entry, conn.id);
}}
>
<Pin />
Expand All @@ -1863,7 +1899,7 @@ export const Sidebar: React.FC<SidebarProps> = ({
className={ctxItemClass}
onSelect={() => {
const entry = favoriteEntryForConnection(conn.id);
if (entry) handleToggleFavorite(entry);
if (entry) handleToggleFavorite(entry, conn.id);
}}
>
<Heart />
Expand Down Expand Up @@ -2005,7 +2041,7 @@ export const Sidebar: React.FC<SidebarProps> = ({
kind: 'database',
connectionName: conn.name,
db: dbName,
})
}, conn.id)
}
>
<Pin />
Expand All @@ -2024,7 +2060,7 @@ export const Sidebar: React.FC<SidebarProps> = ({
kind: 'database',
connectionName: conn.name,
db: dbName,
})
}, conn.id)
}
>
<Heart />
Expand Down
Loading