fix(add-extension): load real icon in install confirm dialog from URL params

When the install confirm dialog is opened via URL query params (e.g. from a
marketplace deep link), installInfo carried no icon, so the icon fell back to
the /resources/icon endpoint which 404s for extensions whose icon is an
external URL (simpleicons / iconify), showing a Package placeholder.

Fetch the icon from the marketplace detail API (mcp/skill/plugin) after opening
the dialog and inject it into installInfo, and reset the icon-failed state when
the resolved URL changes so the <img> retries instead of sticking on the
placeholder.
This commit is contained in:
RockChinQ
2026-06-06 04:45:46 -04:00
parent 7330732f62
commit 170a6756f4
2 changed files with 70 additions and 0 deletions
@@ -207,6 +207,52 @@ export class CloudServiceClient extends BaseHttpClient {
);
}
public getMCPDetail(
author: string,
name: string,
): Promise<{ mcp: PluginV4 }> {
return this.get<{ mcp: PluginV4 }>(
`/api/v1/marketplace/mcps/${author}/${name}`,
);
}
public getSkillDetail(
author: string,
name: string,
): Promise<{ skill: PluginV4 }> {
return this.get<{ skill: PluginV4 }>(
`/api/v1/marketplace/skills/${author}/${name}`,
);
}
/**
* Resolve the marketplace ``icon`` field for an extension by author/name/type.
* Used when the icon is not already known locally (e.g. an install confirm
* dialog opened from a URL query param carries no icon). Returns the raw
* ``icon`` value from the marketplace record (often an absolute external URL),
* or an empty string if it cannot be fetched.
*/
public async fetchMarketplaceIcon(
type: 'plugin' | 'mcp' | 'skill' | undefined,
author: string,
name: string,
): Promise<string> {
try {
if (type === 'mcp') {
const resp = await this.getMCPDetail(author, name);
return resp?.mcp?.icon || '';
}
if (type === 'skill') {
const resp = await this.getSkillDetail(author, name);
return resp?.skill?.icon || '';
}
const resp = await this.getPluginDetail(author, name);
return resp?.plugin?.icon || '';
} catch {
return '';
}
}
public getPluginREADME(
author: string,
pluginName: string,