@@ -9,7 +9,9 @@ import {Injectable, Inject} from '@angular/core';
9
9
10
10
import { BreakPoint } from './break-point' ;
11
11
import { BREAKPOINTS } from './break-points-token' ;
12
+ import { sortAscendingPriority } from './breakpoint-tools' ;
12
13
14
+ type OptionalBreakPoint = BreakPoint | null ;
13
15
14
16
/**
15
17
* Registry of 1..n MediaQuery breakpoint ranges
@@ -18,55 +20,36 @@ import {BREAKPOINTS} from './break-points-token';
18
20
*/
19
21
@Injectable ( { providedIn : 'root' } )
20
22
export class BreakPointRegistry {
23
+ readonly items : BreakPoint [ ] ;
21
24
22
- constructor ( @Inject ( BREAKPOINTS ) private _registry : BreakPoint [ ] ) {
23
- }
24
-
25
- /**
26
- * Accessor to raw list
27
- */
28
- get items ( ) : BreakPoint [ ] {
29
- return [ ...this . _registry ] ;
30
- }
31
-
32
- /**
33
- * Accessor to sorted list used for registration with matchMedia API
34
- *
35
- * NOTE: During breakpoint registration, we want to register the overlaps FIRST
36
- * so the non-overlaps will trigger the MatchMedia:BehaviorSubject last!
37
- * And the largest, non-overlap, matching breakpoint should be the lastReplay value
38
- */
39
- get sortedItems ( ) : BreakPoint [ ] {
40
- let overlaps = this . _registry . filter ( it => it . overlapping === true ) ;
41
- let nonOverlaps = this . _registry . filter ( it => it . overlapping !== true ) ;
42
-
43
- return [ ...overlaps , ...nonOverlaps ] ;
25
+ constructor ( @Inject ( BREAKPOINTS ) list : BreakPoint [ ] ) {
26
+ this . items = [ ...list ] . sort ( sortAscendingPriority ) ;
44
27
}
45
28
46
29
/**
47
30
* Search breakpoints by alias (e.g. gt-xs)
48
31
*/
49
- findByAlias ( alias : string ) : BreakPoint | null {
50
- return this . _registry . find ( bp => bp . alias == alias ) || null ;
32
+ findByAlias ( alias : string ) : OptionalBreakPoint {
33
+ return this . findWithPredicate ( alias , ( bp ) => bp . alias == alias ) ;
51
34
}
52
35
53
- findByQuery ( query : string ) : BreakPoint | null {
54
- return this . _registry . find ( bp => bp . mediaQuery == query ) || null ;
36
+ findByQuery ( query : string ) : OptionalBreakPoint {
37
+ return this . findWithPredicate ( query , ( bp ) => bp . mediaQuery == query ) ;
55
38
}
56
39
57
40
/**
58
41
* Get all the breakpoints whose ranges could overlapping `normal` ranges;
59
42
* e.g. gt-sm overlaps md, lg, and xl
60
43
*/
61
44
get overlappings ( ) : BreakPoint [ ] {
62
- return this . _registry . filter ( it => it . overlapping == true ) ;
45
+ return this . items . filter ( it => it . overlapping == true ) ;
63
46
}
64
47
65
48
/**
66
49
* Get list of all registered (non-empty) breakpoint aliases
67
50
*/
68
51
get aliases ( ) : string [ ] {
69
- return this . _registry . map ( it => it . alias ) ;
52
+ return this . items . map ( it => it . alias ) ;
70
53
}
71
54
72
55
/**
@@ -75,6 +58,26 @@ export class BreakPointRegistry {
75
58
* for property layoutGtSM.
76
59
*/
77
60
get suffixes ( ) : string [ ] {
78
- return this . _registry . map ( it => ! ! it . suffix ? it . suffix : '' ) ;
61
+ return this . items . map ( it => ! ! it . suffix ? it . suffix : '' ) ;
79
62
}
63
+
64
+ /**
65
+ * Memoized lookup using custom predicate function
66
+ */
67
+ private findWithPredicate ( key : string ,
68
+ searchFn : ( bp : BreakPoint ) => boolean ) : OptionalBreakPoint {
69
+ let response = this . findByMap . get ( key ) ;
70
+ if ( ! response ) {
71
+ response = this . items . find ( searchFn ) || null ;
72
+ this . findByMap . set ( key , response ) ;
73
+ }
74
+ return response || null ;
75
+
76
+ }
77
+
78
+ /**
79
+ * Memoized BreakPoint Lookups
80
+ */
81
+ private readonly findByMap = new Map < String , OptionalBreakPoint > ( ) ;
80
82
}
83
+
0 commit comments