@@ -18,7 +18,7 @@ import { fromNow } from 'vs/base/common/date';
18
18
import { createMatches , FuzzyScore , IMatch } from 'vs/base/common/filters' ;
19
19
import { MarkdownString } from 'vs/base/common/htmlContent' ;
20
20
import { combinedDisposable , Disposable , DisposableMap , DisposableStore , IDisposable } from 'vs/base/common/lifecycle' ;
21
- import { autorun , autorunWithStore } from 'vs/base/common/observable' ;
21
+ import { autorun , autorunWithStore , IObservable , observableValue } from 'vs/base/common/observable' ;
22
22
import { ThemeIcon } from 'vs/base/common/themables' ;
23
23
import { localize } from 'vs/nls' ;
24
24
import { IConfigurationService } from 'vs/platform/configuration/common/configuration' ;
@@ -35,7 +35,7 @@ import { ColorIdentifier, registerColor } from 'vs/platform/theme/common/colorRe
35
35
import { IThemeService } from 'vs/platform/theme/common/themeService' ;
36
36
import { IViewPaneOptions , ViewAction , ViewPane } from 'vs/workbench/browser/parts/views/viewPane' ;
37
37
import { IViewDescriptorService , ViewContainerLocation } from 'vs/workbench/common/views' ;
38
- import { renderSCMHistoryItemGraph , historyItemGroupLocal , historyItemGroupRemote , historyItemGroupBase , historyItemGroupHoverLabelForeground , toISCMHistoryItemViewModelArray } from 'vs/workbench/contrib/scm/browser/scmHistory' ;
38
+ import { renderSCMHistoryItemGraph , historyItemGroupLocal , historyItemGroupRemote , historyItemGroupBase , historyItemGroupHoverLabelForeground , toISCMHistoryItemViewModelArray , SWIMLANE_WIDTH , renderSCMHistoryGraphPlaceholder } from 'vs/workbench/contrib/scm/browser/scmHistory' ;
39
39
import { RepositoryActionRunner } from 'vs/workbench/contrib/scm/browser/scmRepositoryRenderer' ;
40
40
import { collectContextMenuActions , connectPrimaryMenu , getActionViewItemProvider , isSCMHistoryItemLoadMoreTreeElement , isSCMHistoryItemViewModelTreeElement , isSCMRepository , isSCMViewService } from 'vs/workbench/contrib/scm/browser/util' ;
41
41
import { ISCMHistoryItem , ISCMHistoryItemViewModel , SCMHistoryItemLoadMoreTreeElement , SCMHistoryItemViewModelTreeElement } from 'vs/workbench/contrib/scm/common/history' ;
@@ -338,7 +338,9 @@ class HistoryItemRenderer implements ITreeRenderer<SCMHistoryItemViewModelTreeEl
338
338
interface LoadMoreTemplate {
339
339
readonly element : HTMLElement ;
340
340
readonly graphPlaceholder : HTMLElement ;
341
- readonly historyItemPlaceholder : HTMLElement ;
341
+ readonly historyItemPlaceholderContainer : HTMLElement ;
342
+ readonly historyItemPlaceholderLabel : IconLabel ;
343
+ readonly elementDisposables : DisposableStore ;
342
344
readonly disposables : IDisposable ;
343
345
}
344
346
@@ -347,22 +349,45 @@ class HistoryItemLoadMoreRenderer implements ITreeRenderer<SCMHistoryItemLoadMor
347
349
static readonly TEMPLATE_ID = 'historyItemLoadMore' ;
348
350
get templateId ( ) : string { return HistoryItemLoadMoreRenderer . TEMPLATE_ID ; }
349
351
350
- constructor ( private readonly _loadMoreCallback : ( repository : ISCMRepository , cursor : string ) => void ) { }
352
+ constructor (
353
+ private readonly _loadingMore : IObservable < boolean > ,
354
+ private readonly _loadMoreCallback : ( repository : ISCMRepository ) => void ,
355
+ @IConfigurationService private readonly _configurationService : IConfigurationService ,
356
+ @ISCMViewService private readonly _scmViewService : ISCMViewService ) { }
351
357
352
358
renderTemplate ( container : HTMLElement ) : LoadMoreTemplate {
353
359
// hack
354
360
( container . parentElement ! . parentElement ! . querySelector ( '.monaco-tl-twistie' ) ! as HTMLElement ) . classList . add ( 'force-no-twistie' ) ;
355
361
356
362
const element = append ( container , $ ( '.history-item-load-more' ) ) ;
357
363
const graphPlaceholder = append ( element , $ ( '.graph-placeholder' ) ) ;
358
- const historyItemPlaceholder = append ( element , $ ( '.history-item-placeholder' ) ) ;
364
+ const historyItemPlaceholderContainer = append ( element , $ ( '.history-item-placeholder' ) ) ;
365
+ const historyItemPlaceholderLabel = new IconLabel ( historyItemPlaceholderContainer , { supportIcons : true } ) ;
359
366
360
- return { element, graphPlaceholder, historyItemPlaceholder , disposables : new DisposableStore ( ) } ;
367
+ return { element, graphPlaceholder, historyItemPlaceholderContainer , historyItemPlaceholderLabel , elementDisposables : new DisposableStore ( ) , disposables : new DisposableStore ( ) } ;
361
368
}
362
369
363
370
renderElement ( element : ITreeNode < SCMHistoryItemLoadMoreTreeElement , void > , index : number , templateData : LoadMoreTemplate , height : number | undefined ) : void {
364
- templateData . graphPlaceholder . style . width = `${ 11 * ( element . element . graphColumnCount + 1 ) - 4 } px` ;
365
- this . _loadMoreCallback ( element . element . repository , element . element . cursor ) ;
371
+ const repositoryCount = this . _scmViewService . visibleRepositories . length ;
372
+ const alwaysShowRepositories = this . _configurationService . getValue < boolean > ( 'scm.alwaysShowRepositories' ) === true ;
373
+
374
+ templateData . graphPlaceholder . textContent = '' ;
375
+ templateData . graphPlaceholder . style . width = `${ SWIMLANE_WIDTH * ( element . element . graphColumns . length + 1 ) } px` ;
376
+ templateData . graphPlaceholder . appendChild ( renderSCMHistoryGraphPlaceholder ( element . element . graphColumns ) ) ;
377
+
378
+ templateData . historyItemPlaceholderContainer . classList . toggle ( 'shimmer' , repositoryCount === 1 && ! alwaysShowRepositories ) ;
379
+
380
+ if ( repositoryCount > 1 || alwaysShowRepositories ) {
381
+ templateData . elementDisposables . add ( autorun ( reader => {
382
+ const loadingMore = this . _loadingMore . read ( reader ) ;
383
+ const icon = `$(${ loadingMore ? 'loading~spin' : 'fold-down' } )` ;
384
+
385
+ templateData . historyItemPlaceholderLabel . setLabel ( localize ( 'loadMore' , "{0} Load More..." , icon ) ) ;
386
+ } ) ) ;
387
+ } else {
388
+ templateData . historyItemPlaceholderLabel . setLabel ( '' ) ;
389
+ this . _loadMoreCallback ( element . element . repository ) ;
390
+ }
366
391
}
367
392
368
393
disposeTemplate ( templateData : LoadMoreTemplate ) : void {
@@ -500,21 +525,21 @@ class SCMHistoryTreeDataSource extends Disposable implements IAsyncDataSource<IS
500
525
private readonly _historyItems = new Map < ISCMRepository , HistoryItemCacheEntry > ( ) ;
501
526
502
527
constructor (
503
- @IConfigurationService private readonly configurationService : IConfigurationService ,
504
- @ISCMViewService private readonly scmViewService : ISCMViewService
528
+ @IConfigurationService private readonly _configurationService : IConfigurationService ,
529
+ @ISCMViewService private readonly _scmViewService : ISCMViewService
505
530
) {
506
531
super ( ) ;
507
532
}
508
533
509
534
async getChildren ( inputOrElement : ISCMViewService | TreeElement ) : Promise < Iterable < TreeElement > > {
510
- const repositoryCount = this . scmViewService . visibleRepositories . length ;
511
- const alwaysShowRepositories = this . configurationService . getValue < boolean > ( 'scm.alwaysShowRepositories' ) === true ;
535
+ const repositoryCount = this . _scmViewService . visibleRepositories . length ;
536
+ const alwaysShowRepositories = this . _configurationService . getValue < boolean > ( 'scm.alwaysShowRepositories' ) === true ;
512
537
513
538
if ( isSCMViewService ( inputOrElement ) && ( repositoryCount > 1 || alwaysShowRepositories ) ) {
514
- return this . scmViewService . visibleRepositories ;
539
+ return this . _scmViewService . visibleRepositories ;
515
540
} else if ( ( isSCMViewService ( inputOrElement ) && repositoryCount === 1 && ! alwaysShowRepositories ) || isSCMRepository ( inputOrElement ) ) {
516
541
const children : TreeElement [ ] = [ ] ;
517
- inputOrElement = isSCMRepository ( inputOrElement ) ? inputOrElement : this . scmViewService . visibleRepositories [ 0 ] ;
542
+ inputOrElement = isSCMRepository ( inputOrElement ) ? inputOrElement : this . _scmViewService . visibleRepositories [ 0 ] ;
518
543
519
544
const historyItems = await this . _getHistoryItems ( inputOrElement ) ;
520
545
children . push ( ...historyItems ) ;
@@ -523,8 +548,7 @@ class SCMHistoryTreeDataSource extends Disposable implements IAsyncDataSource<IS
523
548
if ( lastHistoryItem && lastHistoryItem . historyItemViewModel . historyItem . parentIds . length !== 0 ) {
524
549
children . push ( {
525
550
repository : inputOrElement ,
526
- cursor : lastHistoryItem . historyItemViewModel . historyItem . parentIds [ 0 ] ,
527
- graphColumnCount : lastHistoryItem . historyItemViewModel . outputSwimlanes . length ,
551
+ graphColumns : lastHistoryItem . historyItemViewModel . outputSwimlanes ,
528
552
type : 'historyItemLoadMore'
529
553
} satisfies SCMHistoryItemLoadMoreTreeElement ) ;
530
554
}
@@ -536,7 +560,7 @@ class SCMHistoryTreeDataSource extends Disposable implements IAsyncDataSource<IS
536
560
537
561
hasChildren ( inputOrElement : ISCMViewService | TreeElement ) : boolean {
538
562
if ( isSCMViewService ( inputOrElement ) ) {
539
- return this . scmViewService . visibleRepositories . length !== 0 ;
563
+ return this . _scmViewService . visibleRepositories . length !== 0 ;
540
564
} else if ( isSCMRepository ( inputOrElement ) ) {
541
565
return true ;
542
566
} else if ( isSCMHistoryItemViewModelTreeElement ( inputOrElement ) ) {
@@ -622,7 +646,7 @@ export class SCMHistoryViewPane extends ViewPane {
622
646
private _tree ! : WorkbenchAsyncDataTree < ISCMViewService , TreeElement , FuzzyScore > ;
623
647
private _treeDataSource ! : SCMHistoryTreeDataSource ;
624
648
private _treeIdentityProvider ! : SCMHistoryTreeIdentityProvider ;
625
- private _isLoadMoreInProgress = false ;
649
+ private _isLoadMore = observableValue ( this , false ) ;
626
650
627
651
private readonly _repositories = new DisposableMap < ISCMRepository > ( ) ;
628
652
private readonly _visibilityDisposables = new DisposableStore ( ) ;
@@ -636,8 +660,8 @@ export class SCMHistoryViewPane extends ViewPane {
636
660
637
661
constructor (
638
662
options : IViewPaneOptions ,
639
- @ICommandService private readonly commandService : ICommandService ,
640
- @ISCMViewService private readonly scmViewService : ISCMViewService ,
663
+ @ICommandService private readonly _commandService : ICommandService ,
664
+ @ISCMViewService private readonly _scmViewService : ISCMViewService ,
641
665
@IConfigurationService configurationService : IConfigurationService ,
642
666
@IContextMenuService contextMenuService : IContextMenuService ,
643
667
@IKeybindingService keybindingService : IKeybindingService ,
@@ -679,7 +703,7 @@ export class SCMHistoryViewPane extends ViewPane {
679
703
this . onDidChangeBodyVisibility ( visible => {
680
704
if ( visible ) {
681
705
this . _treeOperationSequencer . queue ( async ( ) => {
682
- await this . _tree . setInput ( this . scmViewService ) ;
706
+ await this . _tree . setInput ( this . _scmViewService ) ;
683
707
684
708
Event . filter ( this . configurationService . onDidChangeConfiguration ,
685
709
e =>
@@ -691,8 +715,8 @@ export class SCMHistoryViewPane extends ViewPane {
691
715
} , this , this . _visibilityDisposables ) ;
692
716
693
717
// Add visible repositories
694
- this . scmViewService . onDidChangeVisibleRepositories ( this . _onDidChangeVisibleRepositories , this , this . _visibilityDisposables ) ;
695
- this . _onDidChangeVisibleRepositories ( { added : this . scmViewService . visibleRepositories , removed : Iterable . empty ( ) } ) ;
718
+ this . _scmViewService . onDidChangeVisibleRepositories ( this . _onDidChangeVisibleRepositories , this , this . _visibilityDisposables ) ;
719
+ this . _onDidChangeVisibleRepositories ( { added : this . _scmViewService . visibleRepositories , removed : Iterable . empty ( ) } ) ;
696
720
697
721
this . _tree . scrollTop = 0 ;
698
722
} ) ;
@@ -728,7 +752,7 @@ export class SCMHistoryViewPane extends ViewPane {
728
752
[
729
753
this . instantiationService . createInstance ( RepositoryRenderer , getActionViewItemProvider ( this . instantiationService ) ) ,
730
754
this . instantiationService . createInstance ( HistoryItemRenderer , historyItemHoverDelegate ) ,
731
- this . instantiationService . createInstance ( HistoryItemLoadMoreRenderer , ( repository , cursor ) => this . _loadMoreCallback ( repository , cursor ) ) ,
755
+ this . instantiationService . createInstance ( HistoryItemLoadMoreRenderer , this . _isLoadMore , repository => this . _loadMoreCallback ( repository ) ) ,
732
756
] ,
733
757
this . _treeDataSource ,
734
758
{
@@ -750,8 +774,7 @@ export class SCMHistoryViewPane extends ViewPane {
750
774
if ( ! e . element ) {
751
775
return ;
752
776
} else if ( isSCMRepository ( e . element ) ) {
753
- this . scmViewService . focus ( e . element ) ;
754
- return ;
777
+ this . _scmViewService . focus ( e . element ) ;
755
778
} else if ( isSCMHistoryItemViewModelTreeElement ( e . element ) ) {
756
779
const historyItem = e . element . historyItemViewModel . historyItem ;
757
780
const historyItemParentId = historyItem . parentIds . length > 0 ? historyItem . parentIds [ 0 ] : undefined ;
@@ -765,11 +788,17 @@ export class SCMHistoryViewPane extends ViewPane {
765
788
const path = rootUri ? rootUri . path : e . element . repository . provider . label ;
766
789
const multiDiffSourceUri = URI . from ( { scheme : 'scm-history-item' , path : `${ path } /${ historyItemParentId } ..${ historyItem . id } ` } , true ) ;
767
790
768
- await this . commandService . executeCommand ( '_workbench.openMultiDiffEditor' , { title, multiDiffSourceUri, resources : historyItemChanges } ) ;
791
+ await this . _commandService . executeCommand ( '_workbench.openMultiDiffEditor' , { title, multiDiffSourceUri, resources : historyItemChanges } ) ;
769
792
}
770
793
771
- this . scmViewService . focus ( e . element . repository ) ;
772
- return ;
794
+ this . _scmViewService . focus ( e . element . repository ) ;
795
+ } else if ( isSCMHistoryItemLoadMoreTreeElement ( e . element ) ) {
796
+ const repositoryCount = this . _scmViewService . visibleRepositories . length ;
797
+ const alwaysShowRepositories = this . configurationService . getValue < boolean > ( 'scm.alwaysShowRepositories' ) === true ;
798
+
799
+ if ( repositoryCount > 1 || alwaysShowRepositories ) {
800
+ this . _loadMoreCallback ( e . element . repository ) ;
801
+ }
773
802
}
774
803
}
775
804
@@ -785,14 +814,14 @@ export class SCMHistoryViewPane extends ViewPane {
785
814
let actionRunner : IActionRunner = new HistoryItemActionRunner ( ( ) => this . _getSelectedHistoryItems ( ) ) ;
786
815
787
816
if ( isSCMRepository ( element ) ) {
788
- const menus = this . scmViewService . menus . getRepositoryMenus ( element . provider ) ;
817
+ const menus = this . _scmViewService . menus . getRepositoryMenus ( element . provider ) ;
789
818
const menu = menus . repositoryContextMenu ;
790
819
791
820
actions = collectContextMenuActions ( menu ) ;
792
821
actionRunner = new RepositoryActionRunner ( ( ) => this . _getSelectedRepositories ( ) ) ;
793
822
context = element . provider ;
794
823
} else if ( isSCMHistoryItemViewModelTreeElement ( element ) ) {
795
- const menus = this . scmViewService . menus . getRepositoryMenus ( element . repository . provider ) ;
824
+ const menus = this . _scmViewService . menus . getRepositoryMenus ( element . repository . provider ) ;
796
825
const menu = menus . historyProviderMenu ?. getHistoryItemMenu2 ( element ) ;
797
826
798
827
actions = menu ? collectContextMenuActions ( menu ) : [ ] ;
@@ -821,7 +850,7 @@ export class SCMHistoryViewPane extends ViewPane {
821
850
return ;
822
851
}
823
852
824
- if ( this . scmViewService . visibleRepositories . length === 1 ) {
853
+ if ( this . _scmViewService . visibleRepositories . length === 1 ) {
825
854
this . _scmHistoryItemGroupHasRemoteContextKey . set ( ! ! currentHistoryItemGroup ?. remote ) ;
826
855
} else {
827
856
this . _scmHistoryItemGroupHasRemoteContextKey . reset ( ) ;
@@ -856,16 +885,16 @@ export class SCMHistoryViewPane extends ViewPane {
856
885
. filter ( r => ! ! r && isSCMHistoryItemViewModelTreeElement ( r ) ) ! ;
857
886
}
858
887
859
- private _loadMoreCallback ( repository : ISCMRepository , cursor : string ) : void {
860
- if ( this . _isLoadMoreInProgress ) {
888
+ private _loadMoreCallback ( repository : ISCMRepository ) : void {
889
+ if ( this . _isLoadMore . get ( ) ) {
861
890
return ;
862
891
}
863
892
864
- this . _isLoadMoreInProgress = true ;
893
+ this . _isLoadMore . set ( true , undefined ) ;
865
894
this . _treeDataSource . loadMore ( repository ) ;
866
895
867
896
this . _updateChildren ( repository )
868
- . finally ( ( ) => this . _isLoadMoreInProgress = false ) ;
897
+ . finally ( ( ) => this . _isLoadMore . set ( false , undefined ) ) ;
869
898
}
870
899
871
900
private _updateChildren ( element ?: ISCMRepository ) : Promise < void > {
0 commit comments