@@ -10,6 +10,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
1010import { IPanelService } from 'vs/workbench/services/panel/common/panelService' ;
1111import { IProgressRunner , IProgressIndicator , emptyProgressRunner } from 'vs/platform/progress/common/progress' ;
1212import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor' ;
13+ import { ViewPane } from 'vs/workbench/browser/parts/views/viewPaneContainer' ;
1314
1415export class ProgressBarIndicator extends Disposable implements IProgressIndicator {
1516
@@ -350,3 +351,160 @@ export class CompositeProgressIndicator extends CompositeScope implements IProgr
350351 }
351352 }
352353}
354+
355+ export class ViewProgressIndicator extends Disposable implements IProgressIndicator {
356+ private progressState : ProgressIndicatorState . State = ProgressIndicatorState . None ;
357+
358+ private isVisible : boolean ;
359+
360+ constructor (
361+ view : ViewPane ,
362+ private progressbar : ProgressBar ,
363+ ) {
364+ super ( ) ;
365+
366+ this . progressbar = progressbar ;
367+ this . _register ( view . onDidChangeBodyVisibility ( this . onVisible , this ) ) ;
368+ this . isVisible = view . isVisible ( ) ;
369+ }
370+
371+ onVisible ( visible : boolean ) {
372+ this . isVisible = visible ;
373+
374+ // Return early if progress state indicates that progress is done
375+ if ( ! visible || this . progressState . type === ProgressIndicatorState . Done . type ) {
376+ this . progressbar . stop ( ) . hide ( ) ;
377+ return ;
378+ }
379+
380+ // Replay Infinite Progress from Promise
381+ if ( this . progressState . type === ProgressIndicatorState . Type . While ) {
382+ let delay : number | undefined ;
383+ if ( this . progressState . whileDelay > 0 ) {
384+ const remainingDelay = this . progressState . whileDelay - ( Date . now ( ) - this . progressState . whileStart ) ;
385+ if ( remainingDelay > 0 ) {
386+ delay = remainingDelay ;
387+ }
388+ }
389+
390+ this . doShowWhile ( delay ) ;
391+ }
392+
393+ // Replay Infinite Progress
394+ else if ( this . progressState . type === ProgressIndicatorState . Type . Infinite ) {
395+ this . progressbar . infinite ( ) . show ( ) ;
396+ }
397+
398+ // Replay Finite Progress (Total & Worked)
399+ else if ( this . progressState . type === ProgressIndicatorState . Type . Work ) {
400+ if ( this . progressState . total ) {
401+ this . progressbar . total ( this . progressState . total ) . show ( ) ;
402+ }
403+
404+ if ( this . progressState . worked ) {
405+ this . progressbar . worked ( this . progressState . worked ) . show ( ) ;
406+ }
407+ }
408+ }
409+
410+ show ( infinite : true , delay ?: number ) : IProgressRunner ;
411+ show ( total : number , delay ?: number ) : IProgressRunner ;
412+ show ( infiniteOrTotal : true | number , delay ?: number ) : IProgressRunner {
413+
414+ // Sort out Arguments
415+ if ( typeof infiniteOrTotal === 'boolean' ) {
416+ this . progressState = ProgressIndicatorState . Infinite ;
417+ } else {
418+ this . progressState = new ProgressIndicatorState . Work ( infiniteOrTotal , undefined ) ;
419+ }
420+
421+ // Active: Show Progress
422+ if ( this . isVisible ) {
423+
424+ // Infinite: Start Progressbar and Show after Delay
425+ if ( this . progressState . type === ProgressIndicatorState . Type . Infinite ) {
426+ this . progressbar . infinite ( ) . show ( delay ) ;
427+ }
428+
429+ // Finite: Start Progressbar and Show after Delay
430+ else if ( this . progressState . type === ProgressIndicatorState . Type . Work && typeof this . progressState . total === 'number' ) {
431+ this . progressbar . total ( this . progressState . total ) . show ( delay ) ;
432+ }
433+ }
434+
435+ return {
436+ total : ( total : number ) => {
437+ this . progressState = new ProgressIndicatorState . Work (
438+ total ,
439+ this . progressState . type === ProgressIndicatorState . Type . Work ? this . progressState . worked : undefined ) ;
440+
441+ if ( this . isVisible ) {
442+ this . progressbar . total ( total ) ;
443+ }
444+ } ,
445+
446+ worked : ( worked : number ) => {
447+
448+ // Verify first that we are either not active or the progressbar has a total set
449+ if ( ! this . isVisible || this . progressbar . hasTotal ( ) ) {
450+ this . progressState = new ProgressIndicatorState . Work (
451+ this . progressState . type === ProgressIndicatorState . Type . Work ? this . progressState . total : undefined ,
452+ this . progressState . type === ProgressIndicatorState . Type . Work && typeof this . progressState . worked === 'number' ? this . progressState . worked + worked : worked ) ;
453+
454+ if ( this . isVisible ) {
455+ this . progressbar . worked ( worked ) ;
456+ }
457+ }
458+
459+ // Otherwise the progress bar does not support worked(), we fallback to infinite() progress
460+ else {
461+ this . progressState = ProgressIndicatorState . Infinite ;
462+ this . progressbar . infinite ( ) . show ( ) ;
463+ }
464+ } ,
465+
466+ done : ( ) => {
467+ this . progressState = ProgressIndicatorState . Done ;
468+
469+ this . progressbar . stop ( ) . hide ( ) ;
470+ }
471+ } ;
472+ }
473+
474+ async showWhile ( promise : Promise < unknown > , delay ?: number ) : Promise < void > {
475+
476+ // Join with existing running promise to ensure progress is accurate
477+ if ( this . progressState . type === ProgressIndicatorState . Type . While ) {
478+ promise = Promise . all ( [ promise , this . progressState . whilePromise ] ) ;
479+ }
480+
481+ // Keep Promise in State
482+ this . progressState = new ProgressIndicatorState . While ( promise , delay || 0 , Date . now ( ) ) ;
483+
484+ try {
485+ this . doShowWhile ( delay ) ;
486+
487+ await promise ;
488+ } catch ( error ) {
489+ // ignore
490+ } finally {
491+
492+ // If this is not the last promise in the list of joined promises, skip this
493+ if ( this . progressState . type !== ProgressIndicatorState . Type . While || this . progressState . whilePromise === promise ) {
494+
495+ // The while promise is either null or equal the promise we last hooked on
496+ this . progressState = ProgressIndicatorState . None ;
497+
498+ this . progressbar . stop ( ) . hide ( ) ;
499+ }
500+ }
501+ }
502+
503+ private doShowWhile ( delay ?: number ) : void {
504+
505+ // Show Progress when active
506+ if ( this . isVisible ) {
507+ this . progressbar . infinite ( ) . show ( delay ) ;
508+ }
509+ }
510+ }
0 commit comments