({
workingDir,
workspaceId,
branchName,
targetBranch,
commitMessage,
canRunGitOperations,
onRefreshCommitMessage,
onConflict,
onResolveConflicts,
})
| 482 | } |
| 483 | |
| 484 | export const ReviewView: React.FC<ReviewViewProps> = ({ |
| 485 | workingDir, |
| 486 | workspaceId, |
| 487 | branchName, |
| 488 | targetBranch, |
| 489 | commitMessage, |
| 490 | canRunGitOperations, |
| 491 | onRefreshCommitMessage, |
| 492 | onConflict, |
| 493 | onResolveConflicts, |
| 494 | }) => { |
| 495 | const { t } = useI18n() |
| 496 | const [viewMode, setViewMode] = useState<ViewMode>({ kind: 'overview' }) |
| 497 | const [filter, setFilter] = useState('') |
| 498 | const [activeKey, setActiveKey] = useState<string | null>(null) |
| 499 | const [flashKey, setFlashKey] = useState<string | null>(null) |
| 500 | |
| 501 | const { data: changesData, isLoading: changesLoading, isError: changesError } = useGitChanges(workingDir) |
| 502 | const commitHash = viewMode.kind === 'commit' ? viewMode.commit.hash : null |
| 503 | const { data: commitFilesData, isLoading: commitFilesLoading } = useGitCommitFiles(workingDir, commitHash) |
| 504 | |
| 505 | const cardNodes = useRef(new Map<string, HTMLElement>()) |
| 506 | const scrollRef = useRef<HTMLDivElement>(null) |
| 507 | const flashTimer = useRef<ReturnType<typeof setTimeout> | null>(null) |
| 508 | |
| 509 | const registerNode = useCallback((key: string, node: HTMLElement | null) => { |
| 510 | if (node) cardNodes.current.set(key, node) |
| 511 | else cardNodes.current.delete(key) |
| 512 | }, []) |
| 513 | |
| 514 | // 数据整理:当前模式下的卡片条目 |
| 515 | const { uncommitted, committed, commitFiles } = useMemo(() => { |
| 516 | const matches = (e: GitChangeEntry) => |
| 517 | !filter.trim() || e.path.toLowerCase().includes(filter.trim().toLowerCase()) |
| 518 | |
| 519 | if (viewMode.kind === 'commit') { |
| 520 | const source: CardSource = { kind: 'commit', hash: viewMode.commit.hash } |
| 521 | const files: TreeEntry[] = (commitFilesData?.files || []) |
| 522 | .filter(matches) |
| 523 | .map((e) => ({ ...e, cardKey: cardKeyOf(source, e.path) })) |
| 524 | return { uncommitted: [] as TreeEntry[], committed: [] as TreeEntry[], commitFiles: files } |
| 525 | } |
| 526 | |
| 527 | const un: TreeEntry[] = (changesData?.uncommitted || []) |
| 528 | .filter(matches) |
| 529 | .map((e) => ({ ...e, cardKey: cardKeyOf({ kind: 'working', diffType: 'uncommitted' }, e.path) })) |
| 530 | const co: TreeEntry[] = (changesData?.committed || []) |
| 531 | .filter(matches) |
| 532 | .map((e) => ({ ...e, cardKey: cardKeyOf({ kind: 'working', diffType: 'committed' }, e.path) })) |
| 533 | return { uncommitted: un, committed: co, commitFiles: [] as TreeEntry[] } |
| 534 | }, [viewMode, changesData, commitFilesData, filter]) |
| 535 | |
| 536 | const allEntries = viewMode.kind === 'commit' ? commitFiles : [...uncommitted, ...committed] |
| 537 | const tree = useMemo(() => buildTree(allEntries), [allEntries]) |
| 538 | |
| 539 | const totals = useMemo(() => { |
| 540 | let additions = 0 |
| 541 | let deletions = 0 |
nothing calls this directly
no test coverage detected