88 */
99
1010import { Component , Input , OnDestroy , OnInit } from '@angular/core' ;
11- import { EMPTY , merge , Observable , Subscription , timer } from 'rxjs' ;
12- import { debounce , delayWhen } from 'rxjs/operators' ;
11+ import { merge , Observable , Subscription , timer } from 'rxjs' ;
12+ import { debounce , distinctUntilChanged , partition , switchMap } from 'rxjs/operators' ;
1313import { PendingInterceptorService } from '../services/pending-interceptor.service' ;
1414import { SpinnerVisibilityService } from '../services/spinner-visibility.service' ;
1515import { Spinkit } from '../spinkits' ;
@@ -23,7 +23,7 @@ export class NgHttpLoaderComponent implements OnDestroy, OnInit {
2323 public isSpinnerVisible : boolean ;
2424 public spinkit = Spinkit ;
2525 private subscriptions : Subscription ;
26- private startTime : number ;
26+ private visibleUntil : number = Date . now ( ) ;
2727
2828 @Input ( )
2929 public backgroundColor : string ;
@@ -40,16 +40,21 @@ export class NgHttpLoaderComponent implements OnDestroy, OnInit {
4040 @Input ( )
4141 public minDuration = 0 ;
4242 @Input ( )
43+ public extraDuration = 0 ;
44+ @Input ( )
4345 public entryComponent : any = null ;
4446
4547 constructor ( private pendingInterceptorService : PendingInterceptorService , private spinnerVisibilityService : SpinnerVisibilityService ) {
48+ const [ showSpinner , hideSpinner ] = partition ( ( h : boolean ) => h ) ( this . pendingInterceptorService . pendingRequestsStatus$ ) ;
49+
4650 this . subscriptions = merge (
47- this . pendingInterceptorService . pendingRequestsStatus$ . pipe (
48- debounce ( h => this . handleDebounceDelay ( h ) ) ,
49- delayWhen ( h => this . handleMinDuration ( h ) )
51+ showSpinner . pipe ( debounce ( ( ) => timer ( this . debounceDelay ) ) ) ,
52+ showSpinner . pipe (
53+ switchMap ( ( ) => hideSpinner . pipe ( debounce ( ( ) => this . getHiddingTimer ( ) ) ) )
5054 ) ,
5155 this . spinnerVisibilityService . visibilityObservable$ ,
5256 )
57+ . pipe ( distinctUntilChanged ( ) )
5358 . subscribe ( h => this . handleSpinnerVisibility ( h ) ) ;
5459 }
5560
@@ -68,13 +73,13 @@ export class NgHttpLoaderComponent implements OnDestroy, OnInit {
6873 }
6974 }
7075
71- private initFilters ( ) {
76+ private initFilters ( ) : void {
7277 this . initFilteredUrlPatterns ( ) ;
7378 this . initFilteredMethods ( ) ;
7479 this . initFilteredHeaders ( ) ;
7580 }
7681
77- private initFilteredUrlPatterns ( ) {
82+ private initFilteredUrlPatterns ( ) : void {
7883 if ( ! ( this . filteredUrlPatterns instanceof Array ) ) {
7984 throw new TypeError ( '`filteredUrlPatterns` must be an array.' ) ;
8085 }
@@ -86,45 +91,29 @@ export class NgHttpLoaderComponent implements OnDestroy, OnInit {
8691 }
8792 }
8893
89- private initFilteredMethods ( ) {
94+ private initFilteredMethods ( ) : void {
9095 if ( ! ( this . filteredMethods instanceof Array ) ) {
9196 throw new TypeError ( '`filteredMethods` must be an array.' ) ;
9297 }
9398 this . pendingInterceptorService . filteredMethods = this . filteredMethods ;
9499 }
95100
96- private initFilteredHeaders ( ) {
101+ private initFilteredHeaders ( ) : void {
97102 if ( ! ( this . filteredHeaders instanceof Array ) ) {
98103 throw new TypeError ( '`filteredHeaders` must be an array.' ) ;
99104 }
100105 this . pendingInterceptorService . filteredHeaders = this . filteredHeaders ;
101106 }
102107
103- private handleSpinnerVisibility ( hasPendingRequests : boolean ) : void {
104- this . isSpinnerVisible = hasPendingRequests ;
105- }
106-
107- private handleDebounceDelay ( hasPendingRequests : boolean ) : Observable < number | never > {
108- if ( hasPendingRequests && ! ! this . debounceDelay ) {
109- return timer ( this . debounceDelay ) ;
110- }
111-
112- return EMPTY ;
113- }
114-
115- private handleMinDuration ( hasPendingRequests : boolean ) : Observable < number > {
116- if ( hasPendingRequests || ! this . minDuration ) {
117- if ( this . shouldInitStartTime ( ) ) {
118- this . startTime = Date . now ( ) ;
119- }
120-
121- return timer ( 0 ) ;
108+ private handleSpinnerVisibility ( showSpinner : boolean ) : void {
109+ const now = Date . now ( ) ;
110+ if ( showSpinner && this . visibleUntil <= now ) {
111+ this . visibleUntil = now + this . minDuration ;
122112 }
123-
124- return timer ( this . minDuration - ( Date . now ( ) - this . startTime ) ) ;
113+ this . isSpinnerVisible = showSpinner ;
125114 }
126115
127- private shouldInitStartTime ( ) : boolean {
128- return ! this . isSpinnerVisible ;
116+ private getHiddingTimer ( ) : Observable < number > {
117+ return timer ( Math . max ( this . extraDuration , this . visibleUntil - Date . now ( ) ) ) ;
129118 }
130119}
0 commit comments