import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; import { Button, Icon, Tabs, getIcon } from '@opensumi/ide-components'; import { Progress } from '@opensumi/ide-core-browser/lib/progress/progress-bar'; import { useInjectable } from '@opensumi/ide-core-browser/lib/react-hooks/injectable-hooks'; import { localize, replaceLocalizePlaceholder } from '@opensumi/ide-core-common'; import { ReactEditorComponent } from '@opensumi/ide-editor/lib/browser'; import { Markdown } from '@opensumi/ide-markdown'; import { IVSXExtensionService, InstallState, VSXExtension, VSXExtensionServiceToken } from '../../common'; import { VSXExtensionRaw } from '../../common/vsx-registry-types'; import styles from './overview.module.less'; enum TabActiveKey { details = 'Details', changelog = 'ChangeLog', deps = 'Dependencies', } const tabMap = [TabActiveKey.details, TabActiveKey.changelog, TabActiveKey.deps]; interface IExtensionMetadata { readme?: string; changelog?: string; icon?: string; downloadCount?: number; installed?: boolean; } const enum ExtensionStatus { CAN_INSTALL, INSTALLING, UNINSTALLING, UNINSTALLED, INSTALLED, ENABLING, } export const ExtensionOverview: ReactEditorComponent< VSXExtensionRaw & VSXExtension & { state: string; extensionId: string; openVSXRegistry: string } > = ({ resource }) => { const vsxExtensionService = useInjectable(VSXExtensionServiceToken); const [loading, setLoading] = useState(true); const [extensionStatus, setExtensionStatus] = useState( resource.metadata?.state === InstallState.INSTALLED ? ExtensionStatus.INSTALLED : ExtensionStatus.CAN_INSTALL, ); const [activateKey, setActivateKey] = useState(TabActiveKey.details); const [metadata, setMetadata] = useState({}); const onDidTabChange = useCallback((index: number) => { const activeKey = tabMap[index]; if (activeKey) { setActivateKey(activeKey); } }, []); const initExtensionMetadata = useCallback(async () => { const extension = await vsxExtensionService.getRemoteRawExtension(resource.metadata?.extensionId); if (extension) { const tasks = ['readme', 'changelog'].map((key) => { const file = extension.files?.[key]; return file ? fetch(file).then((res) => res.text()) : extension[key] ?? ''; }); const [readme, changelog] = await Promise.all(tasks); setMetadata({ readme, changelog, downloadCount: extension.downloadCount }); } setLoading(false); }, [resource]); const install = useCallback(async () => { const extension = await vsxExtensionService.getLocalExtension(resource.metadata?.extensionId); if (extension) { setExtensionStatus(ExtensionStatus.INSTALLING); vsxExtensionService.install(extension).finally(() => { setExtensionStatus(ExtensionStatus.INSTALLED); }); } }, [resource]); const uninstall = useCallback(async () => { const extension = await vsxExtensionService.getLocalExtension(resource.metadata?.extensionId); if (extension) { setExtensionStatus(ExtensionStatus.UNINSTALLING); vsxExtensionService.uninstall(extension).finally(() => { setExtensionStatus(ExtensionStatus.UNINSTALLED); }); } }, [resource]); useEffect(() => { initExtensionMetadata(); }, [resource]); const operatorButtons = useMemo(() => { const buttons: ReactNode[] = []; if (resource.metadata?.state !== InstallState.NOT_INSTALLED) { if (extensionStatus !== ExtensionStatus.UNINSTALLED) { buttons.push( , ); } else { buttons.push( , ); return buttons; } } if (resource.metadata?.state === InstallState.NOT_INSTALLED) { if (extensionStatus === ExtensionStatus.INSTALLED) { buttons.push( , ); } else { buttons.push( , ); } } else if (resource.metadata?.state === InstallState.SHOULD_UPDATE) { if (extensionStatus === ExtensionStatus.INSTALLED) { buttons.push( , ); } else { buttons.push( , ); } } else { buttons.push( , ); } return buttons; }, [resource, extensionStatus]); return (
{resource.metadata?.iconUrl ? ( {replaceLocalizePlaceholder(resource.metadata?.displayName, ) : (
)}

{replaceLocalizePlaceholder(resource.metadata?.displayName, resource.metadata?.extensionId) || resource.metadata?.name}

{resource.metadata?.namespace.toLowerCase() + '.' + resource.metadata?.name.toLowerCase()}
{resource.metadata?.namespace} {resource.metadata?.downloadCount || metadata.downloadCount} {resource.metadata?.averageRating && {resource.metadata?.averageRating}} {resource.metadata?.repository && ( Repository )} {resource.metadata?.license && ( License )} v{resource.metadata?.version}
{replaceLocalizePlaceholder(resource.metadata?.description, resource.metadata?.extensionId)}
{operatorButtons}
{activateKey === TabActiveKey.details && metadata.readme && } {activateKey === TabActiveKey.changelog && metadata.changelog && }
); };