import { useState } from 'react'; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible'; import { ChevronDown, ChevronUp, Loader2 } from 'lucide-react'; import { Button } from './ui/button'; import { startNewSession } from '../sessions'; import { useNavigation } from '../hooks/useNavigation'; import { formatExtensionErrorMessage } from '../utils/extensionErrorUtils'; import { getInitialWorkingDir } from '../utils/workingDir'; import { formatExtensionName } from './settings/extensions/subcomponents/ExtensionList'; import { defineMessages, useIntl } from '../i18n'; const i18n = defineMessages({ loadingExtensions: { id: 'groupedExtensionLoadingToast.loadingExtensions', defaultMessage: 'Loading {count, plural, one {# extension} other {# extensions}}...', }, successfullyLoaded: { id: 'groupedExtensionLoadingToast.successfullyLoaded', defaultMessage: 'Successfully loaded {count, plural, one {# extension} other {# extensions}}', }, partiallyLoaded: { id: 'groupedExtensionLoadingToast.partiallyLoaded', defaultMessage: 'Loaded {successCount}/{totalCount, plural, one {# extension} other {# extensions}}', }, failedToLoad: { id: 'groupedExtensionLoadingToast.failedToLoad', defaultMessage: '{count, plural, one {# extension} other {# extensions}} failed to load', }, failedToAddExtension: { id: 'groupedExtensionLoadingToast.failedToAddExtension', defaultMessage: 'Failed to add extension', }, askGoose: { id: 'groupedExtensionLoadingToast.askGoose', defaultMessage: 'Ask goose', }, copied: { id: 'groupedExtensionLoadingToast.copied', defaultMessage: 'Copied!', }, copyError: { id: 'groupedExtensionLoadingToast.copyError', defaultMessage: 'Copy error', }, showLess: { id: 'groupedExtensionLoadingToast.showLess', defaultMessage: 'Show less', }, showDetails: { id: 'groupedExtensionLoadingToast.showDetails', defaultMessage: 'Show details', }, collapseDetails: { id: 'groupedExtensionLoadingToast.collapseDetails', defaultMessage: 'Collapse details', }, expandDetails: { id: 'groupedExtensionLoadingToast.expandDetails', defaultMessage: 'Expand details', }, }); export interface ExtensionLoadingStatus { name: string; status: 'loading' | 'success' | 'error'; error?: string; recoverHints?: string; } interface ExtensionLoadingToastProps { extensions: ExtensionLoadingStatus[]; totalCount: number; isComplete: boolean; } export function GroupedExtensionLoadingToast({ extensions, totalCount, isComplete, }: ExtensionLoadingToastProps) { const [isOpen, setIsOpen] = useState(false); const [copiedExtension, setCopiedExtension] = useState(null); const setView = useNavigation(); const intl = useIntl(); const successCount = extensions.filter((ext) => ext.status === 'success').length; const errorCount = extensions.filter((ext) => ext.status === 'error').length; const getStatusIcon = (status: 'loading' | 'success' | 'error') => { switch (status) { case 'loading': return ; case 'success': return
; case 'error': return
; } }; const getSummaryText = () => { if (!isComplete) { return intl.formatMessage(i18n.loadingExtensions, { count: totalCount }); } if (errorCount === 0) { return intl.formatMessage(i18n.successfullyLoaded, { count: successCount }); } return intl.formatMessage(i18n.partiallyLoaded, { successCount, totalCount }); }; const getSummaryIcon = () => { if (!isComplete) { return ; } if (errorCount === 0) { return
; } return
; }; return (
{/* Main summary section - clickable */}
{getSummaryIcon()}
{getSummaryText()}
{errorCount > 0 && (
{intl.formatMessage(i18n.failedToLoad, { count: errorCount })}
)}
{/* Expanded details section */}
{extensions.map((ext) => { const friendlyName = formatExtensionName(ext.name); return (
{getStatusIcon(ext.status)}
{friendlyName}
{ext.status === 'error' && ext.error && (
{formatExtensionErrorMessage(ext.error, intl.formatMessage(i18n.failedToAddExtension))}
{ext.recoverHints && setView && ( )}
)}
); })}
{/* Toggle button */} {totalCount > 0 && ( )}
); }