import { AfterViewInit , Component , ElementRef , OnDestroy , ViewChild , } from '@angular/core' ; import { FormControl , FormGroup , Validators } from '@angular/forms' ; import { BehaviorSubject , combineLatest , fromEvent , Subscription } from 'rxjs' ; import { map , skip , take } from 'rxjs/operators' ; import { BoostModalService , BoostTab , MAXIMUM_SINGLE_BOOST_IMPRESSIONS , MINIMUM_BOOST_OFFER_TOKENS , MINIMUM_SINGLE_BOOST_IMPRESSIONS , } from '../../boost-modal.service' ; @ Component ( { selector : 'm-boostModal__amountInput' , templateUrl : './amount-input.component.html' , styleUrls : [ './amount-input.component.ng.scss' ] , } ) export class BoostModalAmountInputComponent implements OnDestroy , AfterViewInit { private subscriptions : Subscription [ ] = [ ] ; private focusListenerSubscriptions : Subscription [ ] = [ ] ; public maxImpressions = MAXIMUM_SINGLE_BOOST_IMPRESSIONS ; public minImpressions = MINIMUM_SINGLE_BOOST_IMPRESSIONS ; public minTokens = MINIMUM_BOOST_OFFER_TOKENS ; public readonly isFocused$ : BehaviorSubject < boolean > = new BehaviorSubject < boolean > ( false ) ; public form : FormGroup ; @ ViewChild ( 'impressionsInput' ) impressionsInput : ElementRef ; @ ViewChild ( 'tokensInput' ) tokensInput : ElementRef ; @ ViewChild ( 'tokensLabel' ) tokensLabel : ElementRef ; @ ViewChild ( 'impressionsLabel' ) impressionsLabel : ElementRef ; constructor ( private service ) { } returns { BehaviorSubject < number > } get impressions$ ( ) : BehaviorSubject < number > { return this . service . impressions$ ; } returns { BehaviorSubject < number > } get tokens$ ( ) : BehaviorSubject < number > { return this . service . tokens$ ; } returns { BehaviorSubject < number > } get rate$ ( ) : BehaviorSubject < number > { return this . service . rate$ ; } returns { BehaviorSubject < BoostTab > } get activeTab$ ( ) : BehaviorSubject < BoostTab > { return this . service . activeTab$ ; } ngOnInit ( ) { this . subscriptions . push ( combineLatest ( [ this . rate$ , this . activeTab$ ] ) . pipe ( map ( ( [ rate , activeTab ] ) => { this . setupFormControls ( rate , activeTab ) ; } ) ) . subscribe ( ) ) ; } ngAfterViewInit ( ) { this . resetFocusListenerSubscriptions ( ) ; this . subscriptions . push ( this . activeTab$ . pipe ( skip ( 1 ) ) . subscribe ( ( ) => { setTimeout ( ( ) => this . resetFocusListenerSubscriptions ( ) ) ; } ) ) ; setTimeout ( ( ) => this . impressionsInput . nativeElement . focus ( ) , 0 ) ; } ngOnDestroy ( ) { for ( let subscription of [ ... this . subscriptions , ... this . focusListenerSubscriptions , ] ) { subscription . unsubscribe ( ) ; } } param { number } $event returns { void } public viewsValueChanged ( $event ) { this . impressions$ . next ( $event ) ; this . tokens$ . next ( $event / this . rate$ . getValue ( ) ) ; } param { number } $event returns { void } public tokensValueChanged ( $event ) { this . tokens$ . next ( $event ) ; this . impressions$ . next ( $event * this . rate$ . getValue ( ) ) ; } returns { void } private resetFocusListenerSubscriptions ( ) { for ( let subscription of this . focusListenerSubscriptions ) { subscription . unsubscribe ( ) ; } if ( this . impressionsInput && this . impressionsInput . nativeElement ) { this . setupImpressionsInputListeners ( ) ; } this . setupTokenInputListeners ( ) ; } returns { void } private setupTokenInputListeners ( ) { this . focusListenerSubscriptions . push ( fromEvent ( this . tokensInput . nativeElement , 'focus' ) . subscribe ( value => { this . isFocused$ . next ( true ) ; } ) , fromEvent ( this . tokensInput . nativeElement , 'focusout' ) . subscribe ( value => { this . isFocused$ . next ( false ) ; } ) , fromEvent ( this . tokensLabel . nativeElement , 'click' ) . subscribe ( value => { this . tokensInput . nativeElement . focus ( ) ; } ) ) ; } returns { void } private setupImpressionsInputListeners ( ) { this . focusListenerSubscriptions . push ( fromEvent ( this . impressionsInput . nativeElement , 'focus' ) . subscribe ( value => { this . isFocused$ . next ( true ) ; } ) , fromEvent ( this . impressionsInput . nativeElement , 'focusout' ) . subscribe ( value => { this . isFocused$ . next ( false ) ; } ) , fromEvent ( this . impressionsLabel . nativeElement , 'click' ) . subscribe ( value => { this . impressionsInput . nativeElement . focus ( ) ; } ) ) ; } param { number } rate param { BoostTab } activeTab returns { void } private setupFormControls ( rate , activeTab ) { const defaultViews = this . maxImpressions / 2 ; const defaultTokens = defaultViews / rate ; const minTokens = this . minImpressions / rate ; if ( activeTab === 'offer' ) { this . form = new FormGroup ( { tokens : new FormControl ( defaultTokens , { validators : [ Validators . required , Validators . min ( minTokens ) ] , } ) , } ) ; return ; } const maxTokens = this . maxImpressions / rate ; this . form = new FormGroup ( { tokens : new FormControl ( defaultTokens , { validators : [ Validators . required , Validators . max ( maxTokens ) , Validators . min ( minTokens ) , ] , } ) , impressions : new FormControl ( defaultViews , { validators : [ Validators . required , Validators . max ( this . maxImpressions ) , Validators . min ( this . minImpressions ) , ] , } ) , } ) ; } }