import { Injectable } from '@angular/core' ; import { BehaviorSubject , timer , Observable , of } from 'rxjs' ; import { tap , takeWhile , scan , map } from 'rxjs/operators' ; import { AbstractSubscriberComponent } from '../../../../../common/components/abstract-subscriber/abstract-subscriber.component' ; import { RelatedContentService } from '../../../../../common/services/related-content.service' ; import { IsCommentingService } from '../../../../comments/poster/is-commenting.service' ; import { ActivityEntity } from '../../../../newsfeed/activity/activity.service' ; /**
 * Singleton holding a goNext$ value, to be pushed too when wanting
 * the next video in a sequence to load.
 */ @ Injectable ( { providedIn : 'root' } ) export class AutoProgressVideoService extends AbstractSubscriberComponent { /**
     * Holds countdown timer Observable. Can be destroyed.
     */ public timer$ : Observable < number > = new Observable < number > ( ) ; /**
     * Push a new value to trigger subscribers to play the next video instantly.
     */ public readonly goNext$ : BehaviorSubject < boolean > = new BehaviorSubject < boolean > ( false ) ; /**
     * Holds the next entity to play.
     */ private readonly nextEntity$ : BehaviorSubject < ActivityEntity > = new BehaviorSubject < ActivityEntity > ( null ) ; returns { void } public updateNextEntity ( ) { this . nextEntity$ . next ( this . relatedContent . getNextEntity ( ) ) ; } returns { Observable < string > } public get nextTitle$ ( ) : Observable < string > { return this . nextEntity$ . pipe ( map ( entity => { if ( ! entity || ! entity . title ) return 'Untitled' ; if ( entity . title . length > 100 ) { return entity . title . substr ( 0 , 97 ) + '...' ; } return entity . title ; } ) ) ; } returns { Observable < string > } public get nextAuthor$ ( ) : Observable < string > { return this . nextEntity$ . pipe ( map ( entity => { return entity && entity . ownerObj . username ? entity . ownerObj . username : '' ; } ) ) ; } returns { Observable < string > } public get nextThumbnailSrc$ ( ) : Observable < string > { return this . nextEntity$ . pipe ( map ( entity => { return entity && entity . thumbnail_src ? entity . thumbnail_src : null ; } ) ) ; } constructor ( private relatedContent , isCommentingService ) { super ( ) ; this . subscriptions . push ( isCommentingService . isCommenting$ . subscribe ( ( isCommenting ) => { if ( isCommenting ) { this . cancel ( ) ; } } ) ) ; } returns { AutoProgressVideoService } public next ( ) { if ( this . relatedContent && this . relatedContent . hasNext ) { const entity = this . updateNextEntity ( ) ; this . delayed ( 6 ) ; } return this ; } returns { AutoProgressVideoService } public cancel ( ) { this . timer$ = of ( 0 ) ; return this ; } param { number } returns { AutoProgressVideoService } private delayed ( seconds = 5 ) { seconds = 7 ; this . timer$ = timer ( 0 , 1000 ) . pipe ( scan ( acc => -- acc , seconds ) , tap ( x => { if ( x === 0 ) { this . goNext$ . next ( true ) ; } } ) , takeWhile ( x => x >= 0 ) ) ; return this ; } }