feat: update extensions cards (#2174)
This commit is contained in:
@@ -37,7 +37,20 @@ export default function ExtensionsSection({ deepLinkConfig, showEnvVars }: Exten
|
|||||||
const fetchExtensions = useCallback(async () => {
|
const fetchExtensions = useCallback(async () => {
|
||||||
const extensionsList = await getExtensions(true); // Force refresh
|
const extensionsList = await getExtensions(true); // Force refresh
|
||||||
// Sort extensions by name to maintain consistent order
|
// 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);
|
setExtensions(sortedExtensions);
|
||||||
}, [getExtensions]);
|
}, [getExtensions]);
|
||||||
|
|
||||||
|
|||||||
@@ -46,14 +46,15 @@ export default function ExtensionItem({ extension, onToggle, onConfigure }: Exte
|
|||||||
}
|
}
|
||||||
}, [extension.enabled, isToggling]);
|
}, [extension.enabled, isToggling]);
|
||||||
|
|
||||||
const renderFormattedSubtitle = () => {
|
const renderSubtitle = () => {
|
||||||
const subtitle = getSubtitle(extension);
|
const { description, command } = getSubtitle(extension);
|
||||||
return subtitle.split('\n').map((part, index) => (
|
return (
|
||||||
<React.Fragment key={index}>
|
<>
|
||||||
{index === 0 ? part : <span className="font-mono text-xs">{part}</span>}
|
{description && <span>{description}</span>}
|
||||||
{index < subtitle.split('\n').length - 1 && <br />}
|
{description && command && <br />}
|
||||||
</React.Fragment>
|
{command && <span className="font-mono text-xs">{command}</span>}
|
||||||
));
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bundled extensions and builtins are not editable
|
// 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%]">
|
<div className="flex flex-col w-max-[90%]">
|
||||||
<h3 className="text-textStandard">{getFriendlyTitle(extension)}</h3>
|
<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>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export default function ExtensionList({ extensions, onToggle, onConfigure }: Ext
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
// Helper function to get a friendly title from extension name
|
// Helper function to get a friendly title from extension name
|
||||||
export function getFriendlyTitle(extension: FixedExtensionEntry): string {
|
export function getFriendlyTitle(extension: FixedExtensionEntry): string {
|
||||||
@@ -46,23 +47,46 @@ export function getFriendlyTitle(extension: FixedExtensionEntry): string {
|
|||||||
.join(' ');
|
.join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SubtitleParts {
|
||||||
|
description: string | null;
|
||||||
|
command: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function to get a subtitle based on extension type and configuration
|
// 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') {
|
if (config.type === 'builtin') {
|
||||||
// Find matching extension in the data
|
// Find matching extension in the data
|
||||||
const extensionData = builtInExtensionsData.find((ext) => ext.name === config.name);
|
const extensionData = builtInExtensionsData.find(
|
||||||
if (extensionData?.description) {
|
(ext) =>
|
||||||
return extensionData.description;
|
ext.name.toLowerCase().replace(/\s+/g, '') === config.name.toLowerCase().replace(/\s+/g, '')
|
||||||
}
|
);
|
||||||
return 'Built-in extension';
|
return {
|
||||||
|
description: extensionData?.description || 'Built-in extension',
|
||||||
|
command: null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.type === 'stdio') {
|
if (config.type === 'stdio') {
|
||||||
// remove shims for displaying
|
// Only include command if it exists
|
||||||
const full_command = combineCmdAndArgs(removeShims(config.cmd), config.args);
|
const full_command = config.cmd
|
||||||
return `STDIO extension${config.description ? `: ${config.description}` : ''}${full_command ? `\n${full_command}` : ''}`;
|
? combineCmdAndArgs(removeShims(config.cmd), config.args)
|
||||||
|
: null;
|
||||||
|
return {
|
||||||
|
description: config.description || null,
|
||||||
|
command: full_command,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.type === 'sse') {
|
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,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user