import { BreakpointObserver , Breakpoints } from '@angular/cdk/layout' ; import { OverlayContainer } from '@angular/cdk/overlay' ; import { Injectable } from '@angular/core' ; import { Router } from '@angular/router' ; import { Actions , Effect , ofType } from '@ngrx/effects' ; import { ROUTER_NAVIGATION } from '@ngrx/router-store' ; import { INIT , select , Store } from '@ngrx/store' ; import { AnimationsService , filterWith , LocalStorageService } from '@nx-mean-starter/shared' ; import Browser from 'browser-detect' ; import { defer , merge , Observable , of } from 'rxjs' ; import { filter , map , tap , withLatestFrom } from 'rxjs/operators' ; import { changeAnimationsElements , changeAnimationsPage , changeAnimationsPageDisabled , changeTheme , setIsMobile , setSidenav , } from './actions' ; import { State } from './model' ; import { getIsMobile , getState , getTheme } from './selectors' ; export const SETTINGS_KEY = 'LAYOUT' ; @ Injectable ( ) export class Effects { isMobile$ : Observable < boolean > = this . store . pipe ( select ( getIsMobile ) ) ; private browser = Browser ( ) ; @ Effect ( ) setIsMobile$ = defer ( ( ) => this . breakpointObserver . observe ( [ Breakpoints . Small , Breakpoints . XSmall ] ) . pipe ( map ( result => result . matches ) , map ( isMobile => setIsMobile ( { isMobile } ) ) ) ) ; @ Effect ( ) closeSidenavOnNavigationIfMobile$ = this . actions$ . pipe ( ofType ( ROUTER_NAVIGATION ) , filterWith ( this . isMobile$ , ( isMobile ) => isMobile ) , map ( ( ) => setSidenav ( { showSidenav : false } ) ) ) ; @ Effect ( { dispatch : false } ) persistSettings = this . actions$ . pipe ( ofType ( changeAnimationsElements , changeAnimationsPage , changeAnimationsPageDisabled , changeTheme ) , withLatestFrom ( this . store . pipe ( select ( getState ) ) ) , tap ( ( [ action , settings ] ) => this . localStorageService . setItem ( SETTINGS_KEY , settings ) ) ) ; @ Effect ( { dispatch : false } ) updateRouteAnimationType$ = merge ( INIT , this . actions$ . pipe ( ofType ( changeAnimationsElements , changeAnimationsPage , changeAnimationsPageDisabled ) ) ) . pipe ( withLatestFrom ( this . store . pipe ( select ( getState ) ) ) , tap ( ( [ action , settings ] ) => this . animationsService . updateRouteAnimationType ( settings . pageAnimations , settings . elementsAnimations ) ) ) ; @ Effect ( ) setBrowserAnimations$ = of ( 1 ) . pipe ( filter ( ( ) => this . isDefectiveBrowser ( ) ) , map ( ( ) => changeAnimationsPageDisabled ( { pageAnimationsDisabled : true } ) ) ) ; @ Effect ( { dispatch : false } ) updateTheme$ = merge ( INIT , this . actions$ . pipe ( ofType ( changeTheme ) ) ) . pipe ( withLatestFrom ( this . store . pipe ( select ( getTheme ) ) ) , tap ( ( [ action , effectiveTheme ] ) => { const classList = this . overlayContainer . getContainerElement ( ) . classList ; const toRemove = Array . from ( classList ) . filter ( ( item ) => item . includes ( '-theme' ) ) ; if ( toRemove . length ) { classList . remove ( ... toRemove ) ; } classList . add ( effectiveTheme ) ; } ) ) ; constructor ( private actions$ , private store , private breakpointObserver , private router , private overlayContainer , private animationsService , private localStorageService ) { } private isDefectiveBrowser ( ) { return [ 'ie' , 'edge' , 'safari' , 'crios' ] . includes ( this . browser . name ) ; } }