fix(updates): sync entry-point states after component updates

This commit is contained in:
zipg authored and GitHub committed 2026-09-20 11:03:31 +08:00
1 parent db5e6f106b
commit 6babd1bf9b
7 files changed
+86 -7

No files matched your search

@@ -19,6 +19,7 @@ import { physicalDropPositionInsideRect } from "@/lib/ai/aiAttachments";
import { createFrontendPluginRegistry, pluginConnectionProviderIcon } from "@/lib/plugins/frontendPlugin";
import { beaconPluginInstall, buildMarketplacePluginListings, filterMarketplacePluginListings, listingRepositoryCanVerify, marketplaceHomepageUrl, type MarketplacePluginListing } from "@/lib/plugins/pluginMarketplace";
import { isBatchSelectableListing, runBatch } from "@/lib/plugins/pluginBatch";
import { COMPONENT_PLUGINS_UPDATED_EVENT } from "@/lib/updates/componentUpdateEvents";
import { formatBytes } from "@/lib/database/serverMetrics";
import type { PluginCenterFocus } from "@/lib/plugins/pluginCenterNavigation";
import { useConnectionStore } from "@/stores/connectionStore";
@@ -245,6 +246,19 @@ async function refreshAfterBatch() {
}
}
async function refreshAfterExternalPluginUpdate() {
clearPluginIconCache();
try {
installedPlugins.value = await api.listPlugins();
} catch (cause) {
error.value = cause instanceof Error ? cause.message : String(cause);
}
}
function handleComponentPluginsUpdated() {
void refreshAfterExternalPluginUpdate();
}
function toggleBatchMode() {
if (batchRunning.value) return;
batchMode.value = !batchMode.value;
@@ -737,10 +751,12 @@ watch(allowUnsigned, (value) => {
});
onMounted(() => {
void refresh();
window.addEventListener(COMPONENT_PLUGINS_UPDATED_EVENT, handleComponentPluginsUpdated);
if (isTauriRuntime()) document.addEventListener("dbx:tauri-file-drop", onTauriPluginDrop);
});
watch(marketplaceViewMode, (mode) => safeLocalStorageSet(MARKETPLACE_VIEW_MODE_STORAGE_KEY, mode));
onBeforeUnmount(() => {
window.removeEventListener(COMPONENT_PLUGINS_UPDATED_EVENT, handleComponentPluginsUpdated);
if (isTauriRuntime()) document.removeEventListener("dbx:tauri-file-drop", onTauriPluginDrop);
});
</script>
@@ -5,6 +5,7 @@ import { readFileSync } from "node:fs";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { InstalledPlugin, PluginRepositoryCatalogResult } from "@/types/database";
import type { MarketplacePluginListing } from "@/lib/plugins/pluginMarketplace";
import { COMPONENT_PLUGINS_UPDATED_EVENT } from "@/lib/updates/componentUpdateEvents";
const mocks = vi.hoisted(() => ({
listPlugins: vi.fn(),
@@ -299,6 +300,19 @@ describe("PluginContributionsPanel installed plugin pin controls", () => {
});
});
describe("PluginContributionsPanel external component updates", () => {
it("refreshes installed plugins when the update center updates plugins", async () => {
expect(state.marketplaceListings.every((listing) => listing.status === "update")).toBe(true);
mocks.listPlugins.mockResolvedValueOnce([installed("a", "3.0.0"), installed("b", "3.0.0"), installed("c", "3.0.0")]);
window.dispatchEvent(new Event(COMPONENT_PLUGINS_UPDATED_EVENT));
await flushUi();
expect(mocks.listPlugins).toHaveBeenCalledOnce();
expect(state.marketplaceListings.every((listing) => listing.status === "installed")).toBe(true);
});
});
const batches = ["install", "uninstall"] as const;
type Batch = (typeof batches)[number];
const singles = ["marketplace", "uninstall", "rollback", "package", "url"] as const;