diff --git a/ui/desktop/src/components/settings/extensions/ExtensionsSection.tsx b/ui/desktop/src/components/settings/extensions/ExtensionsSection.tsx index d1a72be95873..172f0794928f 100644 --- a/ui/desktop/src/components/settings/extensions/ExtensionsSection.tsx +++ b/ui/desktop/src/components/settings/extensions/ExtensionsSection.tsx @@ -48,11 +48,22 @@ export default function ExtensionsSection({ const [showEnvVarsStateVar, setShowEnvVarsStateVar] = useState( showEnvVars ); + const [pendingActivationExtensions, setPendingActivationExtensions] = useState>( + new Set() + ); // Update deep link state when props change useEffect(() => { setDeepLinkConfigStateVar(deepLinkConfig); setShowEnvVarsStateVar(showEnvVars); + + if (deepLinkConfig && !showEnvVars) { + setPendingActivationExtensions((prev) => { + const updated = new Set(prev); + updated.add(deepLinkConfig.name); + return updated; + }); + } }, [deepLinkConfig, showEnvVars]); // Process extensions from context - this automatically updates when extensionsList changes @@ -102,6 +113,12 @@ export default function ExtensionsSection({ sessionId: sessionId, }); + setPendingActivationExtensions((prev) => { + const updated = new Set(prev); + updated.delete(extensionConfig.name); + return updated; + }); + await fetchExtensions(); return true; }; @@ -122,8 +139,21 @@ export default function ExtensionsSection({ extensionConfig: extensionConfig, sessionId: sessionId, }); + setPendingActivationExtensions((prev) => { + const updated = new Set(prev); + updated.delete(extensionConfig.name); + return updated; + }); } catch (error) { console.error('Failed to activate extension:', error); + // If activation fails, mark as pending if it's enabled in config + if (formData.enabled) { + setPendingActivationExtensions((prev) => { + const updated = new Set(prev); + updated.add(extensionConfig.name); + return updated; + }); + } } finally { await fetchExtensions(); if (onModalClose) { @@ -202,6 +232,7 @@ export default function ExtensionsSection({ onConfigure={handleConfigureClick} disableConfiguration={disableConfiguration} searchTerm={searchTerm} + pendingActivationExtensions={pendingActivationExtensions} /> {!hideButtons && ( diff --git a/ui/desktop/src/components/settings/extensions/subcomponents/ExtensionItem.tsx b/ui/desktop/src/components/settings/extensions/subcomponents/ExtensionItem.tsx index 872142dfbce9..f677260332eb 100644 --- a/ui/desktop/src/components/settings/extensions/subcomponents/ExtensionItem.tsx +++ b/ui/desktop/src/components/settings/extensions/subcomponents/ExtensionItem.tsx @@ -11,6 +11,7 @@ interface ExtensionItemProps { onToggle: (extension: FixedExtensionEntry) => Promise | void; onConfigure?: (extension: FixedExtensionEntry) => void; isStatic?: boolean; // to not allow users to edit configuration + isPendingActivation?: boolean; } export default function ExtensionItem({ @@ -18,6 +19,7 @@ export default function ExtensionItem({ onToggle, onConfigure, isStatic, + isPendingActivation = false, }: ExtensionItemProps) { // Add local state to track the visual toggle state const [visuallyEnabled, setVisuallyEnabled] = useState(extension.enabled); @@ -79,7 +81,17 @@ export default function ExtensionItem({ onClick={() => handleToggle(extension)} > - {getFriendlyTitle(extension)} + + {getFriendlyTitle(extension)} + {isPendingActivation && ( + + Pending + + )} + e.stopPropagation()}>
diff --git a/ui/desktop/src/components/settings/extensions/subcomponents/ExtensionList.tsx b/ui/desktop/src/components/settings/extensions/subcomponents/ExtensionList.tsx index a39137076e2f..a2ab0b121fbf 100644 --- a/ui/desktop/src/components/settings/extensions/subcomponents/ExtensionList.tsx +++ b/ui/desktop/src/components/settings/extensions/subcomponents/ExtensionList.tsx @@ -11,6 +11,7 @@ interface ExtensionListProps { isStatic?: boolean; disableConfiguration?: boolean; searchTerm?: string; + pendingActivationExtensions?: Set; } export default function ExtensionList({ @@ -20,6 +21,7 @@ export default function ExtensionList({ isStatic, disableConfiguration: _disableConfiguration, searchTerm = '', + pendingActivationExtensions = new Set(), }: ExtensionListProps) { const matchesSearch = (extension: FixedExtensionEntry): boolean => { if (!searchTerm) return true; @@ -63,6 +65,7 @@ export default function ExtensionList({ onToggle={onToggle} onConfigure={onConfigure} isStatic={isStatic} + isPendingActivation={pendingActivationExtensions.has(extension.name)} /> ))}