66 * found in the LICENSE file at https://angular.io/license
77 */
88
9+ import { coerceArray } from '@angular/cdk/coercion' ;
910import { Injectable , NgZone , OnDestroy } from '@angular/core' ;
10- import { MediaMatcher } from './media-matcher' ;
11- import { asapScheduler , combineLatest , Observable , Subject , Observer } from 'rxjs' ;
11+ import { asapScheduler , combineLatest , Observable , Observer , Subject } from 'rxjs' ;
1212import { debounceTime , map , startWith , takeUntil } from 'rxjs/operators' ;
13- import { coerceArray } from '@angular/cdk/coercion' ;
13+
14+ import { MediaMatcher } from './media-matcher' ;
1415
1516
1617/** The current state of a layout breakpoint. */
@@ -60,7 +61,7 @@ export class BreakpointObserver implements OnDestroy {
6061 * @param value One or more media queries to check.
6162 * @returns Whether any of the media queries match.
6263 */
63- isMatched ( value : string | string [ ] ) : boolean {
64+ isMatched ( value : string | string [ ] ) : boolean {
6465 const queries = splitQueries ( coerceArray ( value ) ) ;
6566 return queries . some ( mediaQuery => this . _registerQuery ( mediaQuery ) . mql . matches ) ;
6667 }
@@ -71,23 +72,22 @@ export class BreakpointObserver implements OnDestroy {
7172 * @param value One or more media queries to check.
7273 * @returns A stream of matches for the given queries.
7374 */
74- observe ( value : string | string [ ] ) : Observable < BreakpointState > {
75+ observe ( value : string | string [ ] ) : Observable < BreakpointState > {
7576 const queries = splitQueries ( coerceArray ( value ) ) ;
7677 const observables = queries . map ( query => this . _registerQuery ( query ) . observable ) ;
7778
78- return combineLatest ( observables ) . pipe (
79- debounceTime ( 0 , asapScheduler ) ,
80- map ( ( breakpointStates : InternalBreakpointState [ ] ) => {
81- const response : BreakpointState = {
82- matches : false ,
83- breakpoints : { } ,
84- } ;
85- breakpointStates . forEach ( ( state : InternalBreakpointState ) => {
86- response . matches = response . matches || state . matches ;
87- response . breakpoints [ state . query ] = state . matches ;
88- } ) ;
89- return response ;
90- } ) ) ;
79+ return combineLatest ( observables )
80+ . pipe ( debounceTime ( 0 , asapScheduler ) , map ( ( breakpointStates : InternalBreakpointState [ ] ) => {
81+ const response : BreakpointState = {
82+ matches : false ,
83+ breakpoints : { } ,
84+ } ;
85+ breakpointStates . forEach ( ( state : InternalBreakpointState ) => {
86+ response . matches = response . matches || state . matches ;
87+ response . breakpoints [ state . query ] = state . matches ;
88+ } ) ;
89+ return response ;
90+ } ) ) ;
9191 }
9292
9393 /** Registers a specific query to be listened for. */
@@ -100,23 +100,24 @@ export class BreakpointObserver implements OnDestroy {
100100 const mql : MediaQueryList = this . mediaMatcher . matchMedia ( query ) ;
101101
102102 // Create callback for match changes and add it is as a listener.
103- const queryObservable = new Observable < MediaQueryList > ( ( observer : Observer < MediaQueryList > ) => {
104- // Listener callback methods are wrapped to be placed back in ngZone. Callbacks must be placed
105- // back into the zone because matchMedia is only included in Zone.js by loading the
106- // webapis-media-query.js file alongside the zone.js file. Additionally, some browsers do not
107- // have MediaQueryList inherit from EventTarget, which causes inconsistencies in how Zone.js
108- // patches it.
109- const handler = ( e : any ) => this . zone . run ( ( ) => observer . next ( e ) ) ;
110- mql . addListener ( handler ) ;
111-
112- return ( ) => {
113- mql . removeListener ( handler ) ;
114- } ;
115- } ) . pipe (
116- startWith ( mql ) ,
117- map ( ( nextMql : MediaQueryList ) => ( { query, matches : nextMql . matches } ) ) ,
118- takeUntil ( this . _destroySubject )
119- ) ;
103+ const queryObservable =
104+ new Observable < MediaQueryListEvent > ( ( observer : Observer < MediaQueryListEvent > ) => {
105+ // Listener callback methods are wrapped to be placed back in ngZone. Callbacks must be
106+ // placed back into the zone because matchMedia is only included in Zone.js by loading the
107+ // webapis-media-query.js file alongside the zone.js file. Additionally, some browsers do
108+ // not have MediaQueryList inherit from EventTarget, which causes inconsistencies in how
109+ // Zone.js patches it.
110+ const handler : ( event : MediaQueryListEvent ) => void = e =>
111+ this . zone . run ( ( ) => observer . next ( e ) ) ;
112+ mql . addListener ( handler ) ;
113+
114+ return ( ) => {
115+ mql . removeListener ( handler ) ;
116+ } ;
117+ } )
118+ . pipe (
119+ map ( ( nextMql : MediaQueryListEvent ) => ( { query, matches : nextMql . matches } ) ) ,
120+ startWith ( { query, matches : mql . matches } ) , takeUntil ( this . _destroySubject ) ) ;
120121
121122 // Add the MediaQueryList to the set of queries.
122123 const output = { observable : queryObservable , mql} ;
@@ -131,6 +132,6 @@ export class BreakpointObserver implements OnDestroy {
131132 */
132133function splitQueries ( queries : string [ ] ) : string [ ] {
133134 return queries . map ( ( query : string ) => query . split ( ',' ) )
134- . reduce ( ( a1 : string [ ] , a2 : string [ ] ) => a1 . concat ( a2 ) )
135- . map ( query => query . trim ( ) ) ;
135+ . reduce ( ( a1 : string [ ] , a2 : string [ ] ) => a1 . concat ( a2 ) )
136+ . map ( query => query . trim ( ) ) ;
136137}
0 commit comments