fix(plugins): refresh reused result-view workbench context

This commit is contained in:
jearhe authored and GitHub committed 2026-09-21 12:28:17 +08:00
1 parent 334b6a574a
commit 282ea32b7b
3 files changed
+48 -5

No files matched your search

@@ -1080,6 +1080,7 @@ function openPluginResultView(pluginId: string, contributionId: string, label: s
sql: resultSqlForGrid(props.activeTab),
result: { columns: result.columns, rows: cappedRows, truncated: result.rows.length > cappedRows.length },
},
refreshContextOnReuse: true,
});
}
@@ -40,6 +40,40 @@ describe("queryStore openPluginWorkbench reuse", () => {
expect(tab?.pluginWorkbench?.context).toEqual({ connectionId: "conn-1", workbenchId: "wb-original" });
});
it("refreshes a reused result-view context when explicitly requested", () => {
const queryStore = useQueryStore();
const firstId = queryStore.openPluginWorkbench("io.dbx.plan-detective", "result-view", {
connectionId: "conn-1",
context: { connectionId: "conn-1", sql: "SELECT 1" },
});
const secondId = queryStore.openPluginWorkbench("io.dbx.plan-detective", "result-view", {
connectionId: "conn-1",
context: { connectionId: "conn-1", sql: "SELECT 2" },
refreshContextOnReuse: true,
});
expect(secondId).toBe(firstId);
expect(queryStore.tabs.find((tab) => tab.id === firstId)?.pluginWorkbench?.context).toEqual({ connectionId: "conn-1", sql: "SELECT 2" });
});
it("refreshes a reused result-view result snapshot when explicitly requested", () => {
const queryStore = useQueryStore();
const firstId = queryStore.openPluginWorkbench("io.dbx.plan-detective", "result-view", {
connectionId: "conn-1",
context: { connectionId: "conn-1", result: { columns: ["id"], rows: [[1]], truncated: false } },
});
const secondId = queryStore.openPluginWorkbench("io.dbx.plan-detective", "result-view", {
connectionId: "conn-1",
context: { connectionId: "conn-1", result: { columns: ["id"], rows: [[2]], truncated: false } },
refreshContextOnReuse: true,
});
expect(secondId).toBe(firstId);
expect(queryStore.tabs.find((tab) => tab.id === firstId)?.pluginWorkbench?.context?.result).toEqual({ columns: ["id"], rows: [[2]], truncated: false });
});
it("a different connection still opens its own workbench tab", () => {
const queryStore = useQueryStore();
+13 -5
View File
@@ -3500,16 +3500,24 @@ export const useQueryStore = defineStore("query", () => {
return undefined;
}
function openPluginWorkbench(pluginId: string, contributionId: string, options: { title?: string; connectionId?: string; database?: string; context?: Record<string, unknown>; forceNew?: boolean } = {}) {
function openPluginWorkbench(pluginId: string, contributionId: string, options: { title?: string; connectionId?: string; database?: string; context?: Record<string, unknown>; forceNew?: boolean; refreshContextOnReuse?: boolean } = {}) {
const contextConnectionId = typeof options.context?.connectionId === "string" ? options.context.connectionId : "";
const connectionId = options.connectionId || contextConnectionId;
if (!options.forceNew) {
const existing = tabs.value.find((tab) => tab.mode === "plugin-workbench" && tab.pluginWorkbench?.pluginId === pluginId && tab.pluginWorkbench?.contributionId === contributionId && pluginTabConnectionId(tab) === connectionId);
if (existing) {
// Reopening surfaces the existing tab as-is. Replacing the context
// here (openPluginConnection mints a fresh workbenchId per click)
// would deep-reload the plugin webview — a full flash plus losing
// the sidecar session binding on the old workbench id.
if (options.refreshContextOnReuse && options.context) {
existing.pluginWorkbench = {
...existing.pluginWorkbench!,
context: snapshotPluginWorkbenchContext(options.context),
};
}
// Reopening normally surfaces the existing tab as-is. Replacing the
// context here by default (openPluginConnection mints a fresh
// workbenchId per click) would deep-reload the plugin webview — a full
// flash plus losing the sidecar session binding on the old workbench
// id. Stateless surfaces such as result-view can explicitly opt into
// a context refresh without changing the tab identity.
// A tab created by an older build (or otherwise unregistered) may
// still be ownerless; land it in the workspace or the group-rendered
// tab strips can never show it.