| ... | ... | @@ -11,6 +11,8 @@ import { |
| 11 | 11 | CheckIcon, |
| 12 | 12 | ChevronDownIcon, |
| 13 | 13 | ChevronRightIcon, |
| 14 | ChevronsDownUpIcon, |
| 15 | ChevronsUpDownIcon, |
| 14 | 16 | Columns2Icon, |
| 15 | 17 | PilcrowIcon, |
| 16 | 18 | Rows3Icon, |
| ... | ... | @@ -32,6 +34,7 @@ import { |
| 32 | 34 | resolveDiffThemeName, |
| 33 | 35 | resolveFileDiffPath, |
| 34 | 36 | } from "../lib/diffRendering"; |
| 37 | import { areAllDiffFilesCollapsed, toggleAllDiffFiles } from "../lib/diffCollapse"; |
| 35 | 38 | import { useTurnDiffSummaries } from "../hooks/useTurnDiffSummaries"; |
| 36 | 39 | import { useProject, useThread } from "../state/entities"; |
| 37 | 40 | import { resolveThreadRouteRef } from "../threadRoutes"; |
| ... | ... | @@ -39,6 +42,7 @@ import { useClientSettings } from "../hooks/useSettings"; |
| 39 | 42 | import { formatShortTimestamp } from "../timestampFormat"; |
| 40 | 43 | import { DiffPanelLoadingState, DiffPanelShell, type DiffPanelMode } from "./DiffPanelShell"; |
| 41 | 44 | import { AnnotatableCodeView, type AnnotatableCodeViewHandle } from "./diffs/AnnotatableCodeView"; |
| 45 | import { Button } from "./ui/button"; |
| 42 | 46 | import { ToggleGroup, Toggle } from "./ui/toggle-group"; |
| 43 | 47 | import { Switch } from "./ui/switch"; |
| 44 | 48 | import { |
| ... | ... | @@ -446,6 +450,8 @@ export default function DiffPanel({ |
| 446 | 450 | }), |
| 447 | 451 | [collapsedDiffFileKeys, renderableFiles], |
| 448 | 452 | ); |
| 453 | const diffFileKeys = useMemo(() => codeViewFiles.map((file) => file.fileKey), [codeViewFiles]); |
| 454 | const allDiffFilesCollapsed = areAllDiffFilesCollapsed(diffFileKeys, collapsedDiffFileKeys); |
| 449 | 455 | |
| 450 | 456 | useEffect(() => { |
| 451 | 457 | if (!selectedFilePath) return; |
| ... | ... | @@ -496,6 +502,18 @@ export default function DiffPanel({ |
| 496 | 502 | [collapseScopeKey], |
| 497 | 503 | ); |
| 498 | 504 | |
| 505 | const toggleDiffFileCollapse = useCallback(() => { |
| 506 | setCollapsedDiffFiles((current) => { |
| 507 | const currentKeys = |
| 508 | current.scopeKey === collapseScopeKey ? current.fileKeys : EMPTY_COLLAPSED_DIFF_FILE_KEYS; |
| 509 | |
| 510 | return { |
| 511 | scopeKey: collapseScopeKey, |
| 512 | fileKeys: toggleAllDiffFiles(diffFileKeys, currentKeys), |
| 513 | }; |
| 514 | }); |
| 515 | }, [collapseScopeKey, diffFileKeys]); |
| 516 | |
| 499 | 517 | const selectTurn = (turnId: TurnId) => { |
| 500 | 518 | if (!routeThreadRef) return; |
| 501 | 519 | useDiffPanelStore.getState().selectTurn(routeThreadRef, turnId); |
| ... | ... | @@ -695,6 +713,30 @@ export default function DiffPanel({ |
| 695 | 713 | )} |
| 696 | 714 | </div> |
| 697 | 715 | <div className="flex shrink-0 items-center gap-1 [-webkit-app-region:no-drag]"> |
| 716 | {codeViewFiles.length > 0 && ( |
| 717 | <Tooltip> |
| 718 | <TooltipTrigger |
| 719 | render={ |
| 720 | <Button |
| 721 | type="button" |
| 722 | size="icon-xs" |
| 723 | variant="outline" |
| 724 | aria-label={allDiffFilesCollapsed ? "Expand all files" : "Collapse all files"} |
| 725 | onClick={toggleDiffFileCollapse} |
| 726 | /> |
| 727 | } |
| 728 | > |
| 729 | {allDiffFilesCollapsed ? ( |
| 730 | <ChevronsUpDownIcon className="size-3" /> |
| 731 | ) : ( |
| 732 | <ChevronsDownUpIcon className="size-3" /> |
| 733 | )} |
| 734 | </TooltipTrigger> |
| 735 | <TooltipPopup side="top"> |
| 736 | {allDiffFilesCollapsed ? "Expand all files" : "Collapse all files"} |
| 737 | </TooltipPopup> |
| 738 | </Tooltip> |
| 739 | )} |
| 698 | 740 | <ToggleGroup |
| 699 | 741 | className="shrink-0" |
| 700 | 742 | variant="outline" |
| ... | ... | @@ -824,7 +866,7 @@ export default function DiffPanel({ |
| 824 | 866 | <AnnotatableCodeView |
| 825 | 867 | viewerRef={codeViewRef} |
| 826 | 868 | key={collapseScopeKey ?? reviewSectionId} |
| 827 | | className="diff-render-surface h-full min-h-0 overflow-auto" |
| 869 | className="diff-render-surface h-full min-h-0 overflow-auto [&>div>div:last-child]:top-0! [&>div>div:last-child]:bottom-auto!" |
| 828 | 870 | files={codeViewFiles} |
| 829 | 871 | sectionId={reviewSectionId} |
| 830 | 872 | sectionTitle={reviewSectionTitle} |