@@ -19,7 +19,7 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
19
19
private waitPromise ?: Promise < void > ;
20
20
private gesture ?: Gesture ;
21
21
private ani ?: Animation ;
22
- private animationEnabled = true ;
22
+ private gestureOrAnimationInProgress = false ;
23
23
24
24
@Element ( ) el ! : HTMLElement ;
25
25
@@ -61,17 +61,22 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
61
61
@Event ( { bubbles : false } ) ionNavDidChange ! : EventEmitter < void > ;
62
62
63
63
async connectedCallback ( ) {
64
+ const onStart = ( ) => {
65
+ this . gestureOrAnimationInProgress = true ;
66
+ if ( this . swipeHandler ) {
67
+ this . swipeHandler . onStart ( ) ;
68
+ }
69
+ }
70
+
64
71
this . gesture = ( await import ( '../../utils/gesture/swipe-back' ) ) . createSwipeBackGesture (
65
72
this . el ,
66
- ( ) => ! ! this . swipeHandler && this . swipeHandler . canStart ( ) && this . animationEnabled ,
67
- ( ) => this . swipeHandler && this . swipeHandler . onStart ( ) ,
73
+ ( ) => ! this . gestureOrAnimationInProgress && ! ! this . swipeHandler && this . swipeHandler . canStart ( ) ,
74
+ ( ) => onStart ( ) ,
68
75
step => this . ani && this . ani . progressStep ( step ) ,
69
76
( shouldComplete , step , dur ) => {
70
77
if ( this . ani ) {
71
- this . animationEnabled = false ;
72
-
73
78
this . ani . onFinish ( ( ) => {
74
- this . animationEnabled = true ;
79
+ this . gestureOrAnimationInProgress = false ;
75
80
76
81
if ( this . swipeHandler ) {
77
82
this . swipeHandler . onEnd ( shouldComplete ) ;
@@ -97,7 +102,8 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
97
102
}
98
103
99
104
this . ani . progressEnd ( shouldComplete ? 1 : 0 , newStepValue , dur ) ;
100
-
105
+ } else {
106
+ this . gestureOrAnimationInProgress = false ;
101
107
}
102
108
}
103
109
) ;
@@ -191,7 +197,34 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
191
197
leavingEl,
192
198
baseEl : el ,
193
199
progressCallback : ( opts . progressAnimation
194
- ? ani => this . ani = ani
200
+ ? ani => {
201
+ /**
202
+ * Because this progress callback is called asynchronously
203
+ * it is possible for the gesture to start and end before
204
+ * the animation is ever set. In that scenario, we should
205
+ * immediately call progressEnd so that the transition promise
206
+ * resolves and the gesture does not get locked up.
207
+ */
208
+ if ( ani !== undefined && ! this . gestureOrAnimationInProgress ) {
209
+ this . gestureOrAnimationInProgress = true ;
210
+ ani . onFinish ( ( ) => {
211
+ this . gestureOrAnimationInProgress = false ;
212
+ if ( this . swipeHandler ) {
213
+ this . swipeHandler . onEnd ( false ) ;
214
+ }
215
+ } , { oneTimeCallback : true } ) ;
216
+
217
+ /**
218
+ * Playing animation to beginning
219
+ * with a duration of 0 prevents
220
+ * any flickering when the animation
221
+ * is later cleaned up.
222
+ */
223
+ ani . progressEnd ( 0 , 0 , 0 ) ;
224
+ } else {
225
+ this . ani = ani ;
226
+ }
227
+ }
195
228
: undefined
196
229
) ,
197
230
...opts ,
0 commit comments