import React from 'react'; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from '@/components/ui/collapsible'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Button } from '@/components/ui/button'; import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay'; import { Icon } from "@/components/icon/Icon"; import { HistoryCommitRow } from './HistoryCommitRow'; import type { GitLogEntry, CommitFileEntry } from '@/lib/api/types'; import { useI18n } from '@/lib/i18n'; import { assignLanes } from './gitGraph'; import type { LanedCommit } from './gitGraph'; const LOG_SIZE_OPTIONS = [ { labelKey: 'gitView.history.logSize25', value: 25 }, { labelKey: 'gitView.history.logSize50', value: 50 }, { labelKey: 'gitView.history.logSize100', value: 100 }, ]; interface HistorySectionProps { mode?: 'history' | 'graph'; log: { all: GitLogEntry[] } | null; isLogLoading: boolean; logMaxCount: number; onLogMaxCountChange: (count: number) => void; expandedCommitHashes: Set; onToggleCommit: (hash: string) => void; commitFilesMap: Map; loadingCommitHashes: Set; onCopyHash: (hash: string) => void; directory: string | undefined; showHeader?: boolean; contentMaxHeightClassName?: string; branchDivider?: { insertBeforeIndex: number; branchName: string; direction: 'up' | 'down'; } | null; onConflict?: (result: { conflict: boolean; conflictFiles?: string[]; operation: 'cherry-pick' | 'revert' | 'merge' | 'rebase' }) => void; onActionSuccess?: () => void; } export const HistorySection: React.FC = ({ mode = 'history', log, isLogLoading, logMaxCount, onLogMaxCountChange, expandedCommitHashes, onToggleCommit, commitFilesMap, loadingCommitHashes, onCopyHash, directory, showHeader = true, contentMaxHeightClassName = 'max-h-[50vh]', branchDivider = null, onConflict, onActionSuccess, }) => { const { t } = useI18n(); const [isOpen, setIsOpen] = React.useState(true); const isGraphMode = mode === 'graph'; const laned: LanedCommit[] = React.useMemo( () => (isGraphMode && log ? assignLanes(log.all) : []), [isGraphMode, log] ); const maxLanes = React.useMemo( () => Math.max(1, ...laned.map((l) => l.lane + 1)), [laned] ); const lanedByHash = React.useMemo( () => new Map(laned.map((l) => [l.commit.hash, l])), [laned] ); // Early return AFTER all hooks if (!log) { return null; } const hasDivider = branchDivider !== null && branchDivider.insertBeforeIndex > 0 && branchDivider.insertBeforeIndex < log.all.length; const hasDividerBelowLoaded = branchDivider !== null && branchDivider.insertBeforeIndex === log.all.length; const hasSplitHistory = hasDivider || hasDividerBelowLoaded; const topEntries = hasDivider ? log.all.slice(0, branchDivider.insertBeforeIndex) : hasDividerBelowLoaded ? log.all : []; const bottomEntries = hasDivider ? log.all.slice(branchDivider.insertBeforeIndex) : []; const dividerIcon = branchDivider?.direction === 'down' ? : ; const renderCommitList = (entries: GitLogEntry[]) => (
    {entries.map((entry) => ( onToggleCommit(entry.hash)} files={commitFilesMap.get(entry.hash) ?? []} isLoadingFiles={loadingCommitHashes.has(entry.hash)} onCopyHash={onCopyHash} directory={directory} onConflict={onConflict} onActionSuccess={onActionSuccess} /> ))}
); const loadMoreButton = log.all.length >= logMaxCount ? (
) : null; const content = ( {log.all.length === 0 ? (

{t('gitView.history.noCommits')}

) : hasSplitHistory && branchDivider ? ( <>
{topEntries.length > 0 ? (
{renderCommitList(topEntries)}
) : null}
{branchDivider.branchName} {dividerIcon}
{bottomEntries.length > 0 ? (
{renderCommitList(bottomEntries)}
) : null}
{loadMoreButton} ) : ( <> {renderCommitList(log.all)} {loadMoreButton} )}
); if (!showHeader) { if (hasSplitHistory) { return
{content}
; } return (
{content}
); } return (

{t('gitView.history.title')}

{isOpen && (
e.stopPropagation()} onPointerDown={(e) => e.stopPropagation()} >
)} {isOpen ? ( ) : ( )}
{content}
); };