@@ -4,6 +4,7 @@ import { CSSType, View } from '../../core/view';
4
4
import { GridLayout } from '../grid-layout' ;
5
5
import { RootLayout , RootLayoutOptions , ShadeCoverOptions , TransitionAnimation } from '.' ;
6
6
import { Animation } from '../../animation' ;
7
+ import { AnimationDefinition } from '../../animation' ;
7
8
8
9
@CSSType ( 'RootLayout' )
9
10
export class RootLayoutBase extends GridLayout {
@@ -33,16 +34,15 @@ export class RootLayoutBase extends GridLayout {
33
34
// keep track of the views locally to be able to use their options later
34
35
this . popupViews . push ( { view : view , options : options } ) ;
35
36
36
- // only insert 1 layer of shade cover (don't insert another one if already present)
37
- if ( options ?. shadeCover && ! this . shadeCover ) {
38
- this . shadeCover = this . createShadeCover ( options . shadeCover ) ;
39
- // insert shade cover at index right above the first layout
40
- this . insertChild ( this . shadeCover , this . staticChildCount + 1 ) ;
41
- }
42
-
43
- // overwrite current shadeCover options if topmost popupview has additional shadeCover configurations
44
- else if ( options ?. shadeCover && this . shadeCover ) {
45
- this . updateShadeCover ( this . shadeCover , options . shadeCover ) ;
37
+ if ( options ?. shadeCover ) {
38
+ // perf optimization note: we only need 1 layer of shade cover
39
+ // we just update properties if needed by additional overlaid views
40
+ if ( this . shadeCover ) {
41
+ // overwrite current shadeCover options if topmost popupview has additional shadeCover configurations
42
+ this . updateShadeCover ( this . shadeCover , options . shadeCover ) ;
43
+ } else {
44
+ this . openShadeCover ( options . shadeCover ) ;
45
+ }
46
46
}
47
47
48
48
view . opacity = 0 ; // always begin with view invisible when adding dynamically
@@ -77,47 +77,46 @@ export class RootLayoutBase extends GridLayout {
77
77
close ( view : View , exitTo ?: TransitionAnimation ) : Promise < void > {
78
78
return new Promise ( ( resolve , reject ) => {
79
79
if ( this . hasChild ( view ) ) {
80
+ const cleanupAndFinish = ( ) => {
81
+ this . removeChild ( view ) ;
82
+ resolve ( ) ;
83
+ } ;
84
+
80
85
try {
81
86
const popupIndex = this . getPopupIndex ( view ) ;
87
+ const poppedView = this . popupViews [ popupIndex ] ;
82
88
// use exitAnimation that is passed in and fallback to the exitAnimation passed in when opening
83
- const exitAnimationDefinition = exitTo || this . popupViews [ popupIndex ] ?. options ?. animation ?. exitTo ;
89
+ const exitAnimationDefinition = exitTo || poppedView ?. options ?. animation ?. exitTo ;
84
90
85
- // Remove view from local array
86
- const poppedView = this . popupViews [ popupIndex ] ;
91
+ // Remove view from tracked popupviews
87
92
this . popupViews . splice ( popupIndex , 1 ) ;
88
93
89
- // update shade cover with the topmost popupView options (if not specifically told to ignore)
90
- const shadeCoverOptions = this . popupViews [ this . popupViews . length - 1 ] ?. options ?. shadeCover ;
91
- if ( this . shadeCover && shadeCoverOptions && ! poppedView ?. options ?. shadeCover . ignoreShadeRestore ) {
92
- this . updateShadeCover ( this . shadeCover , shadeCoverOptions ) ;
94
+ if ( this . shadeCover ) {
95
+ // update shade cover with the topmost popupView options (if not specifically told to ignore)
96
+ if ( ! poppedView ?. options ?. shadeCover . ignoreShadeRestore ) {
97
+ const shadeCoverOptions = this . popupViews [ this . popupViews . length - 1 ] ?. options ?. shadeCover ;
98
+ if ( shadeCoverOptions ) {
99
+ this . updateShadeCover ( this . shadeCover , shadeCoverOptions ) ;
100
+ }
101
+ }
102
+ // remove shade cover animation if this is the last opened popup view
93C6
div>
103
+ if ( this . popupViews . length === 0 ) {
104
+ this . closeShadeCover ( poppedView . options . shadeCover ) ;
105
+ }
93
106
}
94
107
95
108
if ( exitAnimationDefinition ) {
96
- const exitAnimation = this . getExitAnimation ( view , exitAnimationDefinition ) ;
97
- const exitAnimations : Promise < any > [ ] = [ exitAnimation . play ( ) ] ;
98
-
99
- // add remove shade cover animation if this is the last opened popup view
100
- if ( this . popupViews . length === 0 && this . shadeCover ) {
101
- exitAnimations . push ( this . closeShadeCover ( poppedView . options . shadeCover ) ) ;
102
- }
103
- return Promise . all ( exitAnimations )
104
- . then ( ( ) => {
105
- this . removeChild ( view ) ;
106
- resolve ( ) ;
107
- } )
109
+ this . getExitAnimation ( view , exitAnimationDefinition )
110
+ . play ( )
111
+ . then ( cleanupAndFinish . bind ( this ) )
108
112
. catch ( ( ex ) => {
109
113
if ( Trace . isEnabled ( ) ) {
110
114
Trace . write ( `Error playing exit animation: ${ ex } ` , Trace . categories . Layout , Trace . messageType . error ) ;
111
115
}
112
116
} ) ;
117
+ } else {
118
+ cleanupAndFinish ( ) ;
113
119
}
114
- this . removeChild ( view ) ;
115
-
116
- // also remove shade cover if this is the last opened popup view
117
- if ( this . popupViews . length === 0 ) {
118
- this . closeShadeCover ( poppedView . options . shadeCover ) ;
119
- }
120
- resolve ( ) ;
121
120
} catch ( ex ) {
122
121
if ( Trace . isEnabled ( ) ) {
123
122
Trace . write ( `Error closing popup (${ view } ): ${ ex } ` , Trace . categories . Layout , Trace . messageType . error ) ;
@@ -147,6 +146,44 @@ export class RootLayoutBase extends GridLayout {
147
146
} ) ;
148
147
}
149
148
149
+ getShadeCover ( ) : View {
150
+ return this . shadeCover ;
151
+ }
152
+
153
+ openShadeCover ( options : ShadeCoverOptions ) {
154
+ if ( this . shadeCover ) {
155
+ if ( Trace . isEnabled ( ) ) {
156
+ Trace . write ( `RootLayout shadeCover already open.` , Trace . categories . Layout , Trace . messageType . warn ) ;
157
+ }
158
+ } else {
159
+ // create the one and only shade cover
160
+ this . shadeCover = this . createShadeCover ( options ) ;
161
+ // insert shade cover at index right above the first layout
162
+ this . insertChild ( this . shadeCover , this . staticChildCount + 1 ) ;
163
+ }
164
+ }
165
+
166
+ closeShadeCover ( shadeCoverOptions ?: ShadeCoverOptions ) : Promise < void > {
167
+ return new Promise ( ( resolve ) => {
168
+ // if shade cover is displayed and the last popup is closed, also close the shade cover
169
+ if ( this . shadeCover ) {
170
+ return this . _closeShadeCover ( this . shadeCover , shadeCoverOptions ) . then ( ( ) => {
171
+ if ( this . shadeCover ) {
172
+ this . shadeCover . off ( 'loaded' ) ;
173
+ if ( this . shadeCover . parent ) {
174
+ this . removeChild ( this . shadeCover ) ;
175
+ }
176
+ }
177
+ this . shadeCover = null ;
178
+ // cleanup any platform specific details related to shade cover
179
+ this . _cleanupPlatformShadeCover ( ) ;
180
+ resolve ( ) ;
181
+ } ) ;
182
+ }
183
+ resolve ( ) ;
184
+ } ) ;
185
+ }
186
+
150
187
// bring any view instance open on the rootlayout to front of all the children visually
151
188
bringToFront ( view : View , animated : boolean = false ) : Promise < void > {
152
189
return new Promise ( ( resolve , reject ) => {
@@ -214,10 +251,6 @@ export class RootLayoutBase extends GridLayout {
214
251
} ) ;
215
252
}
216
253
217
- getShadeCover ( ) : View {
218
- return this . shadeCover ;
219
- }
220
-
221
254
private getPopupIndex ( view : View ) : number {
222
255
return this . popupViews . findIndex ( ( popupView ) => popupView . view === view ) ;
223
256
}
@@ -287,21 +320,17 @@ export class RootLayoutBase extends GridLayout {
287
320
}
288
321
289
322
private getExitAnimation ( targetView : View , exitTo : TransitionAnimation ) : Animation {
290
- const animationOptions = {
323
+ return new Animation ( [ this . getExitAnimationDefinition ( targetView , exitTo ) ] ) ;
324
+ }
325
+
326
+ private getExitAnimationDefinition ( targetView : View , exitTo : TransitionAnimation ) : AnimationDefinition {
327
+ return {
328
+ target : targetView ,
291
329
...defaultTransitionAnimation ,
292
- ...exitTo ,
330
+ ...( exitTo || { } ) ,
331
+ translate : { x : exitTo . translateX || defaultTransitionAnimation . translateX , y : exitTo . translateY || defaultTransitionAnimation . translateY } ,
332
+ scale : { x : exitTo . scaleX || defaultTransitionAnimation . scaleX , y : exitTo . scaleY || defaultTransitionAnimation . scaleY } ,
293
333
} ;
294
- return new Animation ( [
295
- {
296
- target : targetView ,
297
- translate : { x : animationOptions . translateX , y : animationOptions . translateY } ,
298
- scale : { x : animationOptions . scaleX , y : animationOptions . scaleY } ,
299
- rotate : animationOptions . rotate ,
300
- opacity : animationOptions . opacity ,
301
- duration : animationOptions . duration ,
302
- curve : animationOptions . curve ,
303
- } ,
304
- ] ) ;
305
334
}
306
335
307
336
private createShadeCover ( shadeOptions : ShadeCoverOptions ) : View {
@@ -330,21 +359,6 @@ export class RootLayoutBase extends GridLayout {
330
359
return this . getChildIndex ( view ) >= 0 ;
331
360
}
332
361
333
- private closeShadeCover ( shadeCoverOptions ?: ShadeCoverOptions ) : Promise < void > {
334
- return new Promise ( ( resolve ) => {
335
- // if shade cover is displayed and the last popup is closed, also close the shade cover
336
- if ( this . shadeCover ) {
337
- return this . _closeShadeCover ( this . shadeCover , shadeCoverOptions ) . then ( ( ) => {
338
- this . removeChild ( this . shadeCover ) ;
339
- this . shadeCover . off ( 'loaded' ) ;
340
- this . shadeCover = null ;
341
- resolve ( ) ;
342
- } ) ;
343
- }
344
- resolve ( ) ;
345
- } ) ;
346
- }
347
-
348
362
protected _bringToFront ( view : View ) { }
349
363
350
364
protected _initShadeCover ( view : View , shadeOption : ShadeCoverOptions ) : void { }
@@ -356,6 +370,8 @@ export class RootLayoutBase extends GridLayout {
356
370
protected _closeShadeCover ( view : View , shadeOptions : ShadeCoverOptions ) : Promise < void > {
357
371
return new Promise ( ( ) => { } ) ;
358
372
}
373
+
374
+ protected _cleanupPlatformShadeCover ( ) : void { }
359
375
}
360
376
361
377
export function getRootLayout ( ) : RootLayout {
0 commit comments