11import { useCloudChangedFiles } from "@features/task-detail/hooks/useCloudChangedFiles" ;
2- import {
3- buildCloudEventSummary ,
4- extractCloudFileDiff ,
5- type ParsedToolCall ,
6- } from "@features/task-detail/utils/cloudToolChanges" ;
2+ import type { FileDiffMetadata } from "@pierre/diffs" ;
3+ import { processFile } from "@pierre/diffs" ;
74import { Flex , Spinner , Text } from "@radix-ui/themes" ;
85import type { ChangedFile , Task } from "@shared/types" ;
9- import type { AcpMessage } from "@shared/types/session-events" ;
106import { useMemo } from "react" ;
117import { useReviewComment } from "../hooks/useReviewComment" ;
128import type { DiffOptions , OnCommentCallback } from "../types" ;
@@ -18,30 +14,17 @@ import {
1814 useReviewState ,
1915} from "./ReviewShell" ;
2016
21- const EMPTY_EVENTS : AcpMessage [ ] = [ ] ;
22-
2317interface CloudReviewPageProps {
2418 taskId : string ;
2519 task : Task ;
2620}
2721
2822export function CloudReviewPage ( { taskId, task } : CloudReviewPageProps ) {
29- const {
30- session,
31- effectiveBranch,
32- prUrl,
33- isRunActive,
34- changedFiles,
35- isLoading,
36- } = useCloudChangedFiles ( taskId , task ) ;
23+ const { effectiveBranch, prUrl, isRunActive, remoteFiles, isLoading } =
24+ useCloudChangedFiles ( taskId , task ) ;
3725 const onComment = useReviewComment ( taskId ) ;
38- const events = session ?. events ?? EMPTY_EVENTS ;
39- const summary = useMemo ( ( ) => buildCloudEventSummary ( events ) , [ events ] ) ;
4026
41- const allPaths = useMemo (
42- ( ) => changedFiles . map ( ( f ) => f . path ) ,
43- [ changedFiles ] ,
44- ) ;
27+ const allPaths = useMemo ( ( ) => remoteFiles . map ( ( f ) => f . path ) , [ remoteFiles ] ) ;
4528
4629 const {
4730 diffOptions,
@@ -54,9 +37,9 @@ export function CloudReviewPage({ taskId, task }: CloudReviewPageProps) {
5437 uncollapseFile,
5538 revealFile,
5639 getDeferredReason,
57- } = useReviewState ( changedFiles , allPaths ) ;
40+ } = useReviewState ( remoteFiles , allPaths ) ;
5841
59- if ( ! prUrl && ! effectiveBranch && changedFiles . length === 0 ) {
42+ if ( ! prUrl && ! effectiveBranch && remoteFiles . length === 0 ) {
6043 if ( isRunActive ) {
6144 return (
6245 < Flex align = "center" justify = "center" height = "100%" >
@@ -81,17 +64,17 @@ export function CloudReviewPage({ taskId, task }: CloudReviewPageProps) {
8164 return (
8265 < ReviewShell
8366 taskId = { taskId }
84- fileCount = { changedFiles . length }
67+ fileCount = { remoteFiles . length }
8568 linesAdded = { linesAdded }
8669 linesRemoved = { linesRemoved }
87- isLoading = { isLoading && changedFiles . length === 0 }
88- isEmpty = { changedFiles . length === 0 }
70+ isLoading = { isLoading && remoteFiles . length === 0 }
71+ isEmpty = { remoteFiles . length === 0 }
8972 allExpanded = { collapsedFiles . size === 0 }
9073 onExpandAll = { expandAll }
9174 onCollapseAll = { collapseAll }
9275 onUncollapseFile = { uncollapseFile }
9376 >
94- { changedFiles . map ( ( file ) => {
77+ { remoteFiles . map ( ( file ) => {
9578 const isCollapsed = collapsedFiles . has ( file . path ) ;
9679 const deferredReason = getDeferredReason ( file . path ) ;
9780
@@ -115,7 +98,7 @@ export function CloudReviewPage({ taskId, task }: CloudReviewPageProps) {
11598 < div key = { file . path } data-file-path = { file . path } >
11699 < CloudFileDiff
117100 file = { file }
118- toolCalls = { summary . toolCalls }
101+ prUrl = { prUrl }
119102 options = { diffOptions }
120103 collapsed = { isCollapsed }
121104 onToggle = { ( ) => toggleFile ( file . path ) }
@@ -130,38 +113,46 @@ export function CloudReviewPage({ taskId, task }: CloudReviewPageProps) {
130113
131114function CloudFileDiff ( {
132115 file,
133- toolCalls ,
116+ prUrl ,
134117 options,
135118 collapsed,
136119 onToggle,
137120 onComment,
138121} : {
139122 file : ChangedFile ;
140- toolCalls : Map < string , ParsedToolCall > ;
123+ prUrl : string | null ;
141124 options : DiffOptions ;
142125 collapsed : boolean ;
143126 onToggle : ( ) => void ;
144127 onComment : OnCommentCallback ;
145128} ) {
146- const diff = useMemo (
147- ( ) => extractCloudFileDiff ( toolCalls , file . path ) ,
148- [ toolCalls , file . path ] ,
149- ) ;
129+ const fileDiff = useMemo ( ( ) : FileDiffMetadata | undefined => {
130+ if ( ! file . patch ) return undefined ;
131+ return processFile ( file . patch , { isGitDiff : true } ) ;
132+ } , [ file . patch ] ) ;
150133
151- const fileName = file . path . split ( "/" ) . pop ( ) || file . path ;
152- const oldFile = useMemo (
153- ( ) => ( { name : fileName , contents : diff ?. oldText ?? "" } ) ,
154- [ fileName , diff ] ,
155- ) ;
156- const newFile = useMemo (
157- ( ) => ( { name : fileName , contents : diff ?. newText ?? "" } ) ,
158- [ fileName , diff ] ,
159- ) ;
134+ if ( ! fileDiff ) {
135+ const hasChanges = ( file . linesAdded ?? 0 ) + ( file . linesRemoved ?? 0 ) > 0 ;
136+ const reason = hasChanges ? "large" : "unavailable" ;
137+ const githubFileUrl = prUrl
138+ ? `${ prUrl } /files#diff-${ file . path . replaceAll ( "/" , "-" ) } `
139+ : undefined ;
140+ return (
141+ < DeferredDiffPlaceholder
142+ filePath = { file . path }
143+ linesAdded = { file . linesAdded ?? 0 }
144+ linesRemoved = { file . linesRemoved ?? 0 }
145+ reason = { reason }
146+ collapsed = { collapsed }
147+ onToggle = { onToggle }
148+ externalUrl = { githubFileUrl }
149+ />
150+ ) ;
151+ }
160152
161153 return (
162154 < InteractiveFileDiff
163- oldFile = { oldFile }
164- newFile = { newFile }
155+ fileDiff = { fileDiff }
165156 options = { { ...options , collapsed } }
166157 onComment = { onComment }
167158 renderCustomHeader = { ( fd ) => (
0 commit comments