import { distinctUntilChanged , filter , takeUntil } from 'rxjs/operators' ; import { Subject } from 'rxjs' ; import { ConduitZone } from './conduit-zone.service' ; import { ConduitEvent } from './interfaces/conduit-event' ; import { ConduitMetadata } from './interfaces/conduit-metadata' ; export class ConduitSubject { private _subject : Subject < any > ; private _onDestroy = new Subject < void > ( ) ; constructor ( public conduit , private _zone , public zoneId ) { this . _subject = conduit . subject ; this . getInitialValue ( ) ; this . _subject . pipe ( distinctUntilChanged ( conduit . changeDetection ) , takeUntil ( this . _onDestroy ) ) . subscribe ( this . onOutput . bind ( this ) ) ; _zone . getEvents ( ) . pipe ( filter ( event => event . conduit . id === conduit . id ) , takeUntil ( this . _onDestroy ) ) . subscribe ( this . onInput . bind ( this ) ) ; } /** Check all allow inputs to see if there is a value we should initially set the conduit to */ getInitialValue ( ) { if ( this . conduit . acceptsInput === false ) { return ; } const subjects = this . _zone . getSubjects ( ) . filter ( subject => { if ( subject === this || subject . conduit . id !== this . conduit . id || ! subject . conduit . hasOwnProperty ( 'currentValue' ) ) { return false ; } if ( this . conduit . acceptsInput === true ) { return true ; } if ( Array . isArray ( this . conduit . acceptsInput ) ) { return this . conduit . acceptsInput . indexOf ( subject . zoneId ) !== - 1 ; } } ) ; if ( subjects . length === 0 ) { return ; } subjects . sort ( ( subjectOne , subjectTwo ) => subjectOne . conduit . lastModified . getTime ( ) < subjectTwo . conduit . lastModified . getTime ( ) ? 1 : - 1 ) ; this . _subject . next ( subjects [ 0 ] . conduit . currentValue ) ; } /** This will be triggered when a conduits value has changed */ onInput ( event ) { if ( this . conduit . acceptsInput === false || event . conduit === this . conduit ) { return ; } if ( event . conduit . producesOutput === false && event . zoneId !== this . zoneId ) { return ; } if ( Array . isArray ( this . conduit . acceptsInput ) ) { if ( ! this . conduit . acceptsInput . find ( zone => zone === event . zoneId ) ) { return ; } } const outputValue = this . conduit . map ? this . conduit . map ( event . value ) : event . value ; this . _subject . next ( outputValue ) ; } /** This will be fired when this conduit emits a new value */ onOutput ( value ) { this . conduit . currentValue = value ; this . conduit . lastModified = new Date ( ) ; if ( this . conduit . producesOutput ) { this . _zone . emit ( { conduit : this . conduit , zoneId : this . zoneId , value } ) ; } } /** Unsubscribe once this subject is destroyed */ destroy ( ) { this . _onDestroy . next ( ) ; this . _onDestroy . complete ( ) ; } }