| 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 |
1×
1×
1×
1×
32×
32×
32×
32×
32×
32×
32×
32×
128×
128×
32×
32×
45×
45×
1×
1×
1×
| /*
* @license
* Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
*
* Use of this source code is governed by an Apache-2.0 license that can be
* found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
*/
/* From Angular for infos
export const DEFAULT_BREAKPOINTS = [
{
alias: 'xs',
mediaQuery: '(min-width: 0px) and (max-width: 599px)'
},
{
alias: 'gt-xs',
overlapping: true,
mediaQuery: '(min-width: 600px)'
},
{
alias: 'lt-sm',
overlapping: true,
mediaQuery: '(max-width: 599px)'
},
{
alias: 'sm',
mediaQuery: '(min-width: 600px) and (max-width: 959px)'
},
{
alias: 'gt-sm',
overlapping: true,
mediaQuery: '(min-width: 960px)'
},
{
alias: 'lt-md',
overlapping: true,
mediaQuery: '(max-width: 959px)'
},
{
alias: 'md',
mediaQuery: '(min-width: 960px) and (max-width: 1279px)'
},
{
alias: 'gt-md',
overlapping: true,
mediaQuery: '(min-width: 1280px)'
},
{
alias: 'lt-lg',
overlapping: true,
mediaQuery: '(max-width: 1279px)'
},
{
alias: 'lg',
mediaQuery: '(min-width: 1280px) and (max-width: 1919px)'
},
{
alias: 'gt-lg',
overlapping: true,
mediaQuery: '(min-width: 1920px)'
},
{
alias: 'lt-xl',
overlapping: true,
mediaQuery: '(max-width: 1920px)'
},
{
alias: 'xl',
mediaQuery: '(min-width: 1920px) and (max-width: 5000px)'
}
];
*/
import { Injectable, NgZone, OnDestroy } from '@angular/core';
import { BehaviorSubject, from as observableFrom, Observable } from 'rxjs';
import { distinctUntilChanged, map, takeWhile } from 'rxjs/operators';
@Injectable()
export class MediaService implements OnDestroy {
private isAlive = true;
public isMobile$: Observable<boolean>;
public mediaChanged$: BehaviorSubject<string>;
public mql = {} as { [alias: string]: MediaQueryList };
constructor(private zone: NgZone) {
this.mql.xs = window.matchMedia('(max-width: 599px)');
this.mql.sm = window.matchMedia('(min-width: 600px) and (max-width:959px)');
this.mql.md = window.matchMedia('(min-width: 860px) and (max-width:1279px)');
this.mql.lg = window.matchMedia('(min-width: 1280px)');
Object.keys(this.mql).forEach((alias) => {
this.mql[alias].addListener(this.onMQLEvent.bind(this, alias));
if (this.mql[alias].matches) {
this.mediaChanged$ = new BehaviorSubject(alias);
}
});
this.isMobile$ = observableFrom(this.mediaChanged$).pipe(
takeWhile(() => this.isAlive),
map(() => this.mql.xs.matches || this.mql.sm.matches),
distinctUntilChanged());
}
public ngOnDestroy() {
Object.keys(this.mql).forEach((alias) => {
this.mql[alias].removeListener(this.onMQLEvent as any);
delete this.mql[alias];
});
this.isAlive = false;
}
private onMQLEvent(alias: string) {
this.zone.run(() => {
this.mediaChanged$.next(alias);
});
}
}
|