feat: update extensions cards (#2174)

This commit is contained in:
Bradley Axen
2025-04-11 17:27:17 -07:00
committed by GitHub
parent 255c8dc0f6
commit c52a95d565
3 changed files with 59 additions and 21 deletions

View File

@@ -37,7 +37,20 @@ export default function ExtensionsSection({ deepLinkConfig, showEnvVars }: Exten
const fetchExtensions = useCallback(async () => {
const extensionsList = await getExtensions(true); // Force refresh
// Sort extensions by name to maintain consistent order
const sortedExtensions = [...extensionsList].sort((a, b) => a.name.localeCompare(b.name));
const sortedExtensions = [...extensionsList].sort((a, b) => {
// First sort by builtin
if (a.type === 'builtin' && b.type !== 'builtin') return -1;
if (a.type !== 'builtin' && b.type === 'builtin') return 1;
// Then sort by bundled (handle null/undefined cases)
const aBundled = a.bundled === true;
const bBundled = b.bundled === true;
if (aBundled && !bBundled) return -1;
if (!aBundled && bBundled) return 1;
// Finally sort alphabetically within each group
return a.name.localeCompare(b.name);
});
setExtensions(sortedExtensions);
}, [getExtensions]);

View File

@@ -46,14 +46,15 @@ export default function ExtensionItem({ extension, onToggle, onConfigure }: Exte
}
}, [extension.enabled, isToggling]);
const renderFormattedSubtitle = () => {
const subtitle = getSubtitle(extension);
return subtitle.split('\n').map((part, index) => (
<React.Fragment key={index}>
{index === 0 ? part : <span className="font-mono text-xs">{part}</span>}
{index < subtitle.split('\n').length - 1 && <br />}
</React.Fragment>
));
const renderSubtitle = () => {
const { description, command } = getSubtitle(extension);
return (
<>
{description && <span>{description}</span>}
{description && command && <br />}
{command && <span className="font-mono text-xs">{command}</span>}
</>
);
};
// Bundled extensions and builtins are not editable
@@ -67,7 +68,7 @@ export default function ExtensionItem({ extension, onToggle, onConfigure }: Exte
>
<div className="flex flex-col w-max-[90%]">
<h3 className="text-textStandard">{getFriendlyTitle(extension)}</h3>
<p className="text-xs text-textSubtle">{renderFormattedSubtitle()}</p>
<p className="text-xs text-textSubtle">{renderSubtitle()}</p>
</div>
<div

View File

@@ -25,6 +25,7 @@ export default function ExtensionList({ extensions, onToggle, onConfigure }: Ext
</div>
);
}
// Helper functions
// Helper function to get a friendly title from extension name
export function getFriendlyTitle(extension: FixedExtensionEntry): string {
@@ -46,23 +47,46 @@ export function getFriendlyTitle(extension: FixedExtensionEntry): string {
.join(' ');
}
export interface SubtitleParts {
description: string | null;
command: string | null;
}
// Helper function to get a subtitle based on extension type and configuration
export function getSubtitle(config: ExtensionConfig): string {
export function getSubtitle(config: ExtensionConfig): SubtitleParts {
if (config.type === 'builtin') {
// Find matching extension in the data
const extensionData = builtInExtensionsData.find((ext) => ext.name === config.name);
if (extensionData?.description) {
return extensionData.description;
}
return 'Built-in extension';
const extensionData = builtInExtensionsData.find(
(ext) =>
ext.name.toLowerCase().replace(/\s+/g, '') === config.name.toLowerCase().replace(/\s+/g, '')
);
return {
description: extensionData?.description || 'Built-in extension',
command: null,
};
}
if (config.type === 'stdio') {
// remove shims for displaying
const full_command = combineCmdAndArgs(removeShims(config.cmd), config.args);
return `STDIO extension${config.description ? `: ${config.description}` : ''}${full_command ? `\n${full_command}` : ''}`;
// Only include command if it exists
const full_command = config.cmd
? combineCmdAndArgs(removeShims(config.cmd), config.args)
: null;
return {
description: config.description || null,
command: full_command,
};
}
if (config.type === 'sse') {
return `SSE extension${config.description ? `: ${config.description}` : ''}${config.uri ? ` (${config.uri})` : ''}`;
const description = config.description
? `SSE extension: ${config.description}`
: 'SSE extension';
const command = config.uri || null;
return { description, command };
}
return `Unknown type of extension`;
return {
description: 'Unknown type of extension',
command: null,
};
}