@@ -80,10 +80,12 @@ interface TimelineActionContext {
8080
8181class TimelineAggregate {
8282 readonly items : TimelineItem [ ] ;
83+ readonly source : string ;
8384
8485 lastRenderedIndex : number ;
8586
8687 constructor ( timeline : Timeline ) {
88+ this . source = timeline . source ;
8789 this . items = timeline . items ;
8890 this . _cursor = timeline . paging ?. cursor ;
8991 this . _more = timeline . paging ?. more ?? false ;
@@ -162,6 +164,21 @@ class TimelineAggregate {
162164
163165 return updated ;
164166 }
167+
168+ private _stale = false ;
169+ get stale ( ) {
170+ return this . _stale ;
171+ }
172+
173+ private _requiresReset = false ;
174+ get requiresReset ( ) : boolean {
175+ return this . _requiresReset ;
176+ }
177+
178+ invalidate ( requiresReset : boolean ) {
179+ this . _stale = true ;
180+ this . _requiresReset = requiresReset ;
181+ }
165182}
166183
167184export const TimelineFollowActiveEditorContext = new RawContextKey < boolean > ( 'timelineFollowActiveEditor' , true ) ;
@@ -283,15 +300,32 @@ export class TimelinePane extends ViewPane {
283300 if ( ( uri ?. toString ( true ) === this . uri ?. toString ( true ) && uri !== undefined ) ||
284301 // Fallback to match on fsPath if we are dealing with files or git schemes
285302 ( uri ?. fsPath === this . uri ?. fsPath && ( uri ?. scheme === 'file' || uri ?. scheme === 'git' ) && ( this . uri ?. scheme === 'file' || this . uri ?. scheme === 'git' ) ) ) {
303+
304+ // If the uri hasn't changed, make sure we have valid caches
305+ for ( const source of this . timelineService . getSources ( ) ) {
306+ if ( this . excludedSources . has ( source . id ) ) {
307+ continue ;
308+ }
309+
310+ const timeline = this . timelinesBySource . get ( source . id ) ;
311+ if ( timeline !== undefined && ! timeline . stale ) {
312+ continue ;
313+ }
314+
315+ if ( timeline !== undefined ) {
316+ this . updateTimeline ( timeline , timeline . requiresReset ) ;
317+ } else {
318+ this . loadTimelineForSource ( source . id , uri , true ) ;
319+ }
320+ }
321+
286322 return ;
287323 }
288324
289325 this . setUriCore ( uri , false ) ;
290326 }
291327
292328 private onProvidersChanged ( e : TimelineProvidersChangeEvent ) {
293- // TODO@eamodio only do work if we are visible
294-
295329 if ( e . removed ) {
296330 for ( const source of e . removed ) {
297331 this . timelinesBySource . delete ( source ) ;
@@ -306,23 +340,16 @@ export class TimelinePane extends ViewPane {
306340 }
307341
308342 private onTimelineChanged ( e : TimelineChangeEvent ) {
309- // TODO@eamodio only do work if we are visible
310-
311343 if ( e ?. uri === undefined || e . uri . toString ( true ) !== this . uri ?. toString ( true ) ) {
312344 const timeline = this . timelinesBySource . get ( e . id ) ;
313345 if ( timeline === undefined ) {
314346 return ;
315347 }
316348
317- if ( e . reset ) {
318- this . timelinesBySource . delete ( e . id ) ;
319- // Override the limit, to re-query for all our existing cached (possibly visible) items to keep visual continuity
320- const { oldest } = timeline ;
321- this . loadTimelineForSource ( e . id , this . uri ! , true , oldest !== undefined ? { limit : { timestamp : oldest . timestamp , id : oldest . id } } : undefined ) ;
349+ if ( this . isBodyVisible ( ) ) {
350+ this . updateTimeline ( timeline , e . reset ?? false ) ;
322351 } else {
323- // Override the limit, to query for any newer items
324- const { newest } = timeline ;
325- this . loadTimelineForSource ( e . id , this . uri ! , false , newest !== undefined ? { limit : { timestamp : newest . timestamp , id : newest . id } } : { limit : PageSize } ) ;
352+ timeline . invalidate ( e . reset ?? false ) ;
326353 }
327354 }
328355 }
@@ -379,29 +406,37 @@ export class TimelinePane extends ViewPane {
379406 return this . _visibleItemCount > 0 ;
380407 }
381408
409+ private clear ( cancelPending : boolean ) {
410+ this . _visibleItemCount = 0 ;
411+ this . _maxItemCount = PageSize ;
412+ this . timelinesBySource . clear ( ) ;
413+
414+ if ( cancelPending ) {
415+ for ( const { tokenSource } of this . pendingRequests . values ( ) ) {
416+ tokenSource . dispose ( true ) ;
417+ }
418+
419+ this . pendingRequests . clear ( ) ;
420+
421+ if ( ! this . isBodyVisible ( ) ) {
422+ this . tree . setChildren ( null , undefined ) ;
423+ this . _isEmpty = true ;
424+ }
425+ }
426+ }
427+
382428 private async loadTimeline ( reset : boolean , sources ?: string [ ] ) {
383429 // If we have no source, we are reseting all sources, so cancel everything in flight and reset caches
384430 if ( sources === undefined ) {
385431 if ( reset ) {
386- this . _visibleItemCount = 0 ;
387- this . _maxItemCount = PageSize ;
388- this . timelinesBySource . clear ( ) ;
389-
390- for ( const { tokenSource } of this . pendingRequests . values ( ) ) {
391- tokenSource . dispose ( true ) ;
392- }
393-
394- this . pendingRequests . clear ( ) ;
432+ this . clear ( true ) ;
395433 }
396434
397435 // TODO@eamodio : Are these the right the list of schemes to exclude? Is there a better way?
398436 if ( this . uri ?. scheme === 'vscode-settings' || this . uri ?. scheme === 'webview-panel' || this . uri ?. scheme === 'walkThrough' ) {
399437 this . uri = undefined ;
400438
401- this . _visibleItemCount = 0 ;
402- this . _maxItemCount = PageSize ;
403- this . timelinesBySource . clear ( ) ;
404-
439+ this . clear ( false ) ;
405440 this . refresh ( ) ;
406441
407442 return ;
@@ -413,15 +448,16 @@ export class TimelinePane extends ViewPane {
413448 }
414449
415450 if ( this . uri === undefined ) {
416- this . _visibleItemCount = 0 ;
417- this . _maxItemCount = PageSize ;
418- this . timelinesBySource . clear ( ) ;
419-
451+ this . clear ( false ) ;
420452 this . refresh ( ) ;
421453
422454 return ;
423455 }
424456
457+ if ( ! this . isBodyVisible ( ) ) {
458+ return ;
459+ }
460+
425461 let hasPendingRequests = false ;
426462
427463 for ( const source of sources ?? this . timelineService . getSources ( ) . map ( s => s . id ) ) {
@@ -490,6 +526,19 @@ export class TimelinePane extends ViewPane {
490526 return true ;
491527 }
492528
529+ private updateTimeline ( timeline : TimelineAggregate , reset : boolean ) {
530+ if ( reset ) {
531+ this . timelinesBySource . delete ( timeline . source ) ;
532+ // Override the limit, to re-query for all our existing cached (possibly visible) items to keep visual continuity
533+ const { oldest } = timeline ;
534+ this . loadTimelineForSource ( timeline . source , this . uri ! , true , oldest !== undefined ? { limit : { timestamp : oldest . timestamp , id : oldest . id } } : undefined ) ;
535+ } else {
536+ // Override the limit, to query for any newer items
537+ const { newest } = timeline ;
538+ this . loadTimelineForSource ( timeline . source , this . uri ! , false , newest !== undefined ? { limit : { timestamp : newest . timestamp , id : newest . id } } : { limit : PageSize } ) ;
539+ }
540+ }
541+
493542 private _pendingRefresh = false ;
494543
495544 private async handleRequest ( request : TimelineRequest ) {
@@ -590,7 +639,7 @@ export class TimelinePane extends ViewPane {
590639 for ( const [ source , timeline ] of this . timelinesBySource ) {
591640 timeline . lastRenderedIndex = - 1 ;
592641
593- if ( this . excludedSources . has ( source ) ) {
642+ if ( this . excludedSources . has ( source ) || timeline . stale ) {
594643 continue ;
595644 }
596645
@@ -651,6 +700,10 @@ export class TimelinePane extends ViewPane {
651700 }
652701
653702 private refresh ( ) {
703+ if ( ! this . isBodyVisible ( ) ) {
704+ return ;
705+ }
706+
654707 this . tree . setChildren ( null , this . getItems ( ) as any ) ;
655708 this . _isEmpty = ! this . hasVisibleItems ;
656709
@@ -682,6 +735,16 @@ export class TimelinePane extends ViewPane {
682735 this . tree . domFocus ( ) ;
683736 }
684737
738+ setExpanded ( expanded : boolean ) : boolean {
739+ const changed = super . setExpanded ( expanded ) ;
740+
741+ if ( changed && this . isBodyVisible ( ) ) {
742+ this . onActiveEditorChanged ( ) ;
743+ }
744+
745+ return changed ;
746+ }
747+
685748 setVisible ( visible : boolean ) : void {
686749 if ( visible ) {
687750 this . visibilityDisposables = new DisposableStore ( ) ;
0 commit comments