import Collapse, { Panel } from 'rc-collapse'; import React, { memo, useCallback, useEffect, useState } from 'react'; import 'rc-collapse/assets/index.css'; import { Icon } from '@opensumi/ide-components/lib/icon/icon'; import { Popover, getIcon } from '@opensumi/ide-core-browser/lib/components'; import { EnhanceIcon } from '@opensumi/ide-core-browser/lib/components/ai-native'; import { useInjectable } from '@opensumi/ide-core-browser/lib/react-hooks/injectable-hooks'; import { AppConfig } from '@opensumi/ide-core-browser/lib/react-providers/config-provider'; import { LabelService } from '@opensumi/ide-core-browser/lib/services/label-service'; import { localize } from '@opensumi/ide-core-common/lib/localize'; import { Event, URI } from '@opensumi/ide-core-common/lib/utils'; import { WorkbenchEditorService } from '@opensumi/ide-editor/lib/browser/types'; import { FileContext, LLMContextService, LLMContextServiceToken } from '../../../common/llm-context'; import { ContextSelector } from './context-selector'; import styles from './style.module.less'; const getCollapsedHeight = () => ({ height: 0, opacity: 0 }); const getRealHeight = (node) => ({ height: node.scrollHeight, opacity: 1 }); const getCurrentHeight = (node) => ({ height: node.offsetHeight }); const skipOpacityTransition = (_, event) => (event as TransitionEvent).propertyName === 'height'; export const ChatContext = memo(() => { const [addedFiles, updateAddedFiles] = useState([]); const [contextOverlay, toggleContextOverlay] = useState(false); const labelService = useInjectable(LabelService); const appConfig = useInjectable(AppConfig); const workbenchEditorService = useInjectable(WorkbenchEditorService); const contextService = useInjectable(LLMContextServiceToken); useEffect(() => { const disposable = Event.debounce( contextService.onDidContextFilesChangeEvent, (_, e) => e!, 50, )((files) => { if (files) { updateAddedFiles([...files.attached]); } }, contextService); return () => { disposable.dispose(); }; }, []); const openContextOverlay = useCallback(() => { toggleContextOverlay(true); }, [addedFiles]); const onDidSelect = useCallback((uri: URI) => { contextService.addFileToContext(uri, undefined, true); }, []); const onDidDeselect = useCallback((uri: URI) => { contextService.removeFileFromContext(uri, true); }, []); const onDidClickFile = useCallback((uri: URI) => { workbenchEditorService.open(uri); }, []); const onDidCleanFiles = useCallback((e) => { e.stopPropagation(); e.preventDefault(); contextService.cleanFileContext(); }, []); const onDidRemoveFile = useCallback((e, uri: URI) => { e.stopPropagation(); e.preventDefault(); onDidDeselect(uri); }, []); return (
(isActive ? : )} openMotion={{ motionName: 'rc-collapse-motion', onEnterStart: getCollapsedHeight, onEnterActive: getRealHeight, onLeaveStart: getCurrentHeight, onLeaveActive: getCollapsedHeight, onEnterEnd: skipOpacityTransition, onLeaveEnd: skipOpacityTransition, motionDeadline: 100, leavedClassName: styles.collapse_hide, }} >

Context {addedFiles.length > 0 ? ` (${addedFiles.length} files)` : ''}

} key='context-panel' >
{addedFiles.map((file) => (
onDidClickFile(file.uri)}> {file.uri.path.base} {file.selection ? ` (${file.selection[0]}-${file.selection[1]})` : ''} {URI.file(appConfig.workspaceDir).relative(file.uri.parent)?.toString()} onDidRemoveFile(e, file.uri)} />
))}
Add Files
{contextOverlay && ( toggleContextOverlay(false)} onDidDeselect={onDidDeselect} onDidSelect={onDidSelect} addedFiles={addedFiles} /> )} ); });