@@ -12,7 +12,6 @@ import { AssistantParts, Message, MessageDivider, PART_MAPPING, type UserActions
1212import { Card } from "./card"
1313import { Accordion } from "./accordion"
1414import { StickyAccordionHeader } from "./sticky-accordion-header"
15- import { Collapsible } from "./collapsible"
1615import { DiffChanges } from "./diff-changes"
1716import { Icon } from "./icon"
1817import { TextShimmer } from "./text-shimmer"
@@ -241,23 +240,20 @@ export function SessionTurn(
241240 } , [ ] )
242241 . reverse ( )
243242 } )
243+ const MAX_FILES = 10
244244 const edited = createMemo ( ( ) => diffs ( ) . length )
245245 const [ state , setState ] = createStore ( {
246- open : false ,
246+ showAll : false ,
247247 expanded : [ ] as string [ ] ,
248248 } )
249- const open = ( ) => state . open
249+ const showAll = ( ) => state . showAll
250250 const expanded = ( ) => state . expanded
251-
252- createEffect (
253- on (
254- open ,
255- ( value , prev ) => {
256- if ( ! value && prev ) setState ( "expanded" , [ ] )
257- } ,
258- { defer : true } ,
259- ) ,
260- )
251+ const overflow = createMemo ( ( ) => Math . max ( 0 , edited ( ) - MAX_FILES ) )
252+ const visible = createMemo ( ( ) => ( showAll ( ) ? diffs ( ) : diffs ( ) . slice ( 0 , MAX_FILES ) ) )
253+ const toggleAll = ( ) => {
254+ autoScroll . pause ( )
255+ setState ( "showAll" , ! showAll ( ) )
256+ }
261257
262258 const assistantMessages = createMemo (
263259 ( ) => {
@@ -425,101 +421,100 @@ export function SessionTurn(
425421 </ Show >
426422 < SessionRetry status = { status ( ) } show = { active ( ) } />
427423 < Show when = { edited ( ) > 0 && ! working ( ) } >
428- < div data-slot = "session-turn-diffs" >
429- < Collapsible open = { open ( ) } onOpenChange = { ( value ) => setState ( "open" , value ) } variant = "ghost" >
430- < Collapsible . Trigger >
431- < div data-component = "session-turn-diffs-trigger" >
432- < div data-slot = "session-turn-diffs-title" >
433- < span data-slot = "session-turn-diffs-label" > { i18n . t ( "ui.sessionReview.change.modified" ) } </ span >
434- < span data-slot = "session-turn-diffs-count" >
435- { edited ( ) } { i18n . t ( edited ( ) === 1 ? "ui.common.file.one" : "ui.common.file.other" ) }
436- </ span >
437- < div data-slot = "session-turn-diffs-meta" >
438- < DiffChanges changes = { diffs ( ) } variant = "bars" />
439- < Collapsible . Arrow />
440- </ div >
441- </ div >
442- </ div >
443- </ Collapsible . Trigger >
444- < Collapsible . Content >
445- < Show when = { open ( ) } >
446- < div data-component = "session-turn-diffs-content" >
447- < Accordion
448- multiple
449- style = { { "--sticky-accordion-offset" : "40px" } }
450- value = { expanded ( ) }
451- onChange = { ( value ) =>
452- setState ( "expanded" , Array . isArray ( value ) ? value : value ? [ value ] : [ ] )
453- }
454- >
455- < For each = { diffs ( ) } >
456- { ( diff ) => {
457- const active = createMemo ( ( ) => expanded ( ) . includes ( diff . file ) )
458- const [ visible , setVisible ] = createSignal ( false )
459-
460- createEffect (
461- on (
462- active ,
463- ( value ) => {
464- if ( ! value ) {
465- setVisible ( false )
466- return
467- }
468-
469- requestAnimationFrame ( ( ) => {
470- if ( ! active ( ) ) return
471- setVisible ( true )
472- } )
473- } ,
474- { defer : true } ,
475- ) ,
476- )
477-
478- return (
479- < Accordion . Item value = { diff . file } >
480- < StickyAccordionHeader >
481- < Accordion . Trigger >
482- < div data-slot = "session-turn-diff-trigger" >
483- < span data-slot = "session-turn-diff-path" >
484- < Show when = { diff . file . includes ( "/" ) } >
485- < span data-slot = "session-turn-diff-directory" >
486- { `\u202A${ getDirectory ( diff . file ) } \u202C` }
487- </ span >
488- </ Show >
489- < span data-slot = "session-turn-diff-filename" > { getFilename ( diff . file ) } </ span >
490- </ span >
491- < div data-slot = "session-turn-diff-meta" >
492- < span data-slot = "session-turn-diff-changes" >
493- < DiffChanges changes = { diff } />
494- </ span >
495- < span data-slot = "session-turn-diff-chevron" >
496- < Icon name = "chevron-down" size = "small" />
497- </ span >
498- </ div >
499- </ div >
500- </ Accordion . Trigger >
501- </ StickyAccordionHeader >
502- < Accordion . Content >
503- < Show when = { visible ( ) } >
504- < div data-slot = "session-turn-diff-view" data-scrollable >
505- < Dynamic
506- component = { fileComponent }
507- mode = "diff"
508- before = { { name : diff . file , contents : diff . before } }
509- after = { { name : diff . file , contents : diff . after } }
510- />
511- </ div >
424+ < div
425+ data-slot = "session-turn-diffs"
426+ data-component = "session-turn-diffs-group"
427+ data-show-all = { showAll ( ) || undefined }
428+ >
429+ < div data-slot = "session-turn-diffs-header" >
430+ < span data-slot = "session-turn-diffs-label" >
431+ { edited ( ) } { i18n . t ( "ui.sessionTurn.diffs.changed" ) } { " " }
432+ { i18n . t ( edited ( ) === 1 ? "ui.common.file.one" : "ui.common.file.other" ) }
433+ </ span >
434+ < DiffChanges changes = { diffs ( ) } />
435+ < Show when = { overflow ( ) > 0 } >
436+ < span data-slot = "session-turn-diffs-toggle" onClick = { toggleAll } >
437+ { showAll ( ) ? i18n . t ( "ui.sessionTurn.diffs.showLess" ) : i18n . t ( "ui.sessionTurn.diffs.showAll" ) }
438+ </ span >
439+ </ Show >
440+ </ div >
441+ < div data-component = "session-turn-diffs-content" >
442+ < Accordion
443+ multiple
444+ style = { { "--sticky-accordion-offset" : "40px" } }
445+ value = { expanded ( ) }
446+ onChange = { ( value ) => setState ( "expanded" , Array . isArray ( value ) ? value : value ? [ value ] : [ ] ) }
447+ >
448+ < For each = { visible ( ) } >
449+ { ( diff ) => {
450+ const active = createMemo ( ( ) => expanded ( ) . includes ( diff . file ) )
451+ const [ shown , setShown ] = createSignal ( false )
452+
453+ createEffect (
454+ on (
455+ active ,
456+ ( value ) => {
457+ if ( ! value ) {
458+ setShown ( false )
459+ return
460+ }
461+
462+ requestAnimationFrame ( ( ) => {
463+ if ( ! active ( ) ) return
464+ setShown ( true )
465+ } )
466+ } ,
467+ { defer : true } ,
468+ ) ,
469+ )
470+
471+ return (
472+ < Accordion . Item value = { diff . file } >
473+ < StickyAccordionHeader >
474+ < Accordion . Trigger >
475+ < div data-slot = "session-turn-diff-trigger" >
476+ < span data-slot = "session-turn-diff-path" >
477+ < Show when = { diff . file . includes ( "/" ) } >
478+ < span data-slot = "session-turn-diff-directory" >
479+ { `\u202A${ getDirectory ( diff . file ) } \u202C` }
480+ </ span >
512481 </ Show >
513- </ Accordion . Content >
514- </ Accordion . Item >
515- )
516- } }
517- </ For >
518- </ Accordion >
519- </ div >
520- </ Show >
521- </ Collapsible . Content >
522- </ Collapsible >
482+ < span data-slot = "session-turn-diff-filename" > { getFilename ( diff . file ) } </ span >
483+ </ span >
484+ < div data-slot = "session-turn-diff-meta" >
485+ < span data-slot = "session-turn-diff-changes" >
486+ < DiffChanges changes = { diff } />
487+ </ span >
488+ < span data-slot = "session-turn-diff-chevron" >
489+ < Icon name = "chevron-down" size = "small" />
490+ </ span >
491+ </ div >
492+ </ div >
493+ </ Accordion . Trigger >
494+ </ StickyAccordionHeader >
495+ < Accordion . Content >
496+ < Show when = { shown ( ) } >
497+ < div data-slot = "session-turn-diff-view" data-scrollable >
498+ < Dynamic
499+ component = { fileComponent }
500+ mode = "diff"
501+ before = { { name : diff . file , contents : diff . before } }
502+ after = { { name : diff . file , contents : diff . after } }
503+ />
504+ </ div >
505+ </ Show >
506+ </ Accordion . Content >
507+ </ Accordion . Item >
508+ )
509+ } }
510+ </ For >
511+ </ Accordion >
512+ < Show when = { ! showAll ( ) && overflow ( ) > 0 } >
513+ < div data-slot = "session-turn-diffs-more" onClick = { toggleAll } >
514+ { i18n . t ( "ui.sessionTurn.diffs.more" , { count : String ( overflow ( ) ) } ) }
515+ </ div >
516+ </ Show >
517+ </ div >
523518 </ div >
524519 </ Show >
525520 < Show when = { error ( ) } >
0 commit comments