Add pending extension indicator to extension panel (#5493)
Signed-off-by: Alex Holder <alexeeyre@gmail.com>
This commit is contained in:
@@ -48,11 +48,22 @@ export default function ExtensionsSection({
|
||||
const [showEnvVarsStateVar, setShowEnvVarsStateVar] = useState<boolean | undefined | null>(
|
||||
showEnvVars
|
||||
);
|
||||
const [pendingActivationExtensions, setPendingActivationExtensions] = useState<Set<string>>(
|
||||
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 && (
|
||||
|
||||
@@ -11,6 +11,7 @@ interface ExtensionItemProps {
|
||||
onToggle: (extension: FixedExtensionEntry) => Promise<boolean | void> | 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)}
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle className="">{getFriendlyTitle(extension)}</CardTitle>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
{getFriendlyTitle(extension)}
|
||||
{isPendingActivation && (
|
||||
<span
|
||||
className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-400 border border-amber-300 dark:border-amber-700"
|
||||
title="Extension will be activated when you start a new chat session"
|
||||
>
|
||||
Pending
|
||||
</span>
|
||||
)}
|
||||
</CardTitle>
|
||||
|
||||
<CardAction onClick={(e) => e.stopPropagation()}>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
|
||||
@@ -11,6 +11,7 @@ interface ExtensionListProps {
|
||||
isStatic?: boolean;
|
||||
disableConfiguration?: boolean;
|
||||
searchTerm?: string;
|
||||
pendingActivationExtensions?: Set<string>;
|
||||
}
|
||||
|
||||
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)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user