/** * PluginDetailDialog — full detail view for a single plugin with install controls. */ import { useEffect, useState } from 'react'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from '@renderer/components/ui/dialog'; import { Badge } from '@renderer/components/ui/badge'; import { Button } from '@renderer/components/ui/button'; import { Label } from '@renderer/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@renderer/components/ui/select'; import { useStore } from '@renderer/store'; import { api } from '@renderer/api'; import { getCapabilityLabel, inferCapabilities, normalizeCategory, } from '@shared/utils/extensionNormalizers'; import { ExternalLink, Loader2 } from 'lucide-react'; import { InstallButton } from '../common/InstallButton'; import { InstallCountBadge } from '../common/InstallCountBadge'; import { MarkdownViewer } from '@renderer/components/chat/viewers/MarkdownViewer'; import type { EnrichedPlugin, InstallScope } from '@shared/types/extensions'; interface PluginDetailDialogProps { plugin: EnrichedPlugin | null; open: boolean; onClose: () => void; } const SCOPE_OPTIONS: { value: InstallScope; label: string }[] = [ { value: 'user', label: 'User (global)' }, { value: 'project', label: 'Project' }, ]; export const PluginDetailDialog = ({ plugin, open, onClose, }: PluginDetailDialogProps): React.JSX.Element => { const fetchPluginReadme = useStore((s) => s.fetchPluginReadme); const readmes = useStore((s) => s.pluginReadmes); const readmeLoading = useStore((s) => s.pluginReadmeLoading); const installProgress = useStore( (s) => (plugin ? s.pluginInstallProgress[plugin.pluginId] : undefined) ?? 'idle' ); const installPlugin = useStore((s) => s.installPlugin); const uninstallPlugin = useStore((s) => s.uninstallPlugin); const [scope, setScope] = useState('user'); useEffect(() => { if (plugin && open) { fetchPluginReadme(plugin.pluginId); } }, [plugin, open, fetchPluginReadme]); if (!plugin) return <>; const capabilities = inferCapabilities(plugin); const category = normalizeCategory(plugin.category); const readme = readmes[plugin.pluginId]; const isReadmeLoading = readmeLoading[plugin.pluginId] ?? false; return ( !o && onClose()}>
{plugin.name} {plugin.description}
{plugin.isInstalled && ( Installed )}
{/* Metadata grid */}
Author

{plugin.author?.name ?? 'Unknown'}

Category

{category}

Capabilities
{capabilities.map((cap) => ( {getCapabilityLabel(cap)} ))}
Installs
{/* Install controls */}
installPlugin({ pluginId: plugin.pluginId, scope })} onUninstall={() => uninstallPlugin(plugin.pluginId, scope)} size="default" />
{/* Homepage link */} {plugin.homepage && ( )} {/* README */}
{isReadmeLoading && (
Loading README...
)} {!isReadmeLoading && readme && ( )} {!isReadmeLoading && !readme && (

No README available.

)}
); };