import React from 'react'; import type { ToolPart } from '@opencode-ai/sdk/v2'; import { Popover } from '@base-ui/react/popover'; import { useDirectoryStore } from '@/stores/useDirectoryStore'; import { useIsGitRepo } from '@/stores/useGitStore'; import { useUIStore } from '@/stores/useUIStore'; import { type ChangedFile, type ChangedFileEntry, FILE_EDIT_TOOLS, extractChangedFiles, toRelativePath, } from './changedFiles'; import { ChangedFilesList } from './ChangedFilesList'; import { changedFilesPopoverClassName, changedFilesPopoverStyle } from './changedFilesPopover'; import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'; import { Icon } from "@/components/icon/Icon"; import type { TurnActivityRecord } from './lib/turns/types'; interface TurnChangedFilesDropdownProps { activityParts: TurnActivityRecord[] | undefined; } export const TurnChangedFilesDropdown: React.FC = React.memo(({ activityParts }) => { const [isExpanded, setIsExpanded] = React.useState(false); const [portalContainer, setPortalContainer] = React.useState(null); const triggerButtonRef = React.useRef(null); const currentDirectory = useDirectoryStore((s) => s.currentDirectory); const isGitRepo = useIsGitRepo(currentDirectory); const changedFiles = React.useMemo(() => { // Skip work entirely in git repos — the global PendingChangesBar handles those. if (isGitRepo !== false) return []; if (!activityParts || activityParts.length === 0) return []; const toolParts: ToolPart[] = []; for (const activity of activityParts) { const part = activity.part; if (part.type !== 'tool') continue; if (!FILE_EDIT_TOOLS.has(part.tool)) continue; toolParts.push(part); } if (toolParts.length === 0) return []; return extractChangedFiles(toolParts); }, [activityParts, isGitRepo]); if (changedFiles.length === 0) return null; const syncPortalContainer = () => { const container = triggerButtonRef.current?.closest('[data-slot="dialog-content"], [role="dialog"]') as HTMLElement | null; setPortalContainer(container || null); }; const handleOpenFile = (file: ChangedFileEntry) => { if (!currentDirectory) return; const store = useUIStore.getState(); const relativePath = toRelativePath(file.path, currentDirectory); if (!store.isMobile) { store.openContextDiff(currentDirectory, relativePath, false, 'turn'); setIsExpanded(false); return; } store.navigateToDiff(relativePath, false, 'turn'); setIsExpanded(false); }; const fileCount = changedFiles.length; const label = `${fileCount} file${fileCount !== 1 ? 's' : ''}`; return ( {label} {isExpanded ? ( ) : ( )} } /> {label} changed in this turn ); }); TurnChangedFilesDropdown.displayName = 'TurnChangedFilesDropdown';