Skip to content

Commit

Permalink
fix(modal): swipeToClose property is now reactive (#21073)
Browse files Browse the repository at this point in the history
fixes #21072
  • Loading branch information
liamdebeasi committed Apr 27, 2020
1 parent 1b11ff7 commit 4bd9134
Showing 1 changed file with 44 additions and 30 deletions.
74 changes: 44 additions & 30 deletions core/src/components/modal/modal.tsx
@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h, writeTask } from '@stencil/core';
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, Watch, h, writeTask } from '@stencil/core';

import { config } from '../../global/config';
import { getIonMode } from '../../global/ionic-global';
Expand Down Expand Up @@ -121,6 +121,15 @@ export class Modal implements ComponentInterface, OverlayInterface {
*/
@Event({ eventName: 'ionModalDidDismiss' }) didDismiss!: EventEmitter<OverlayEventDetail>;

@Watch('swipeToClose')
swipeToCloseChanged(enable: boolean) {
if (this.gesture) {
this.gesture.enable(enable);
} else if (enable) {
this.initSwipeToClose();
}
}

constructor() {
prepareOverlay(this.el);
}
Expand Down Expand Up @@ -148,38 +157,43 @@ export class Modal implements ComponentInterface, OverlayInterface {

await present(this, 'modalEnter', iosEnterAnimation, mdEnterAnimation, this.presentingElement);

const mode = getIonMode(this);
if (this.swipeToClose && mode === 'ios') {
// All of the elements needed for the swipe gesture
// should be in the DOM and referenced by now, except
// for the presenting el
const animationBuilder = this.leaveAnimation || config.get('modalLeave', iosLeaveAnimation);
const ani = this.animation = animationBuilder(this.el, this.presentingElement);
this.gesture = createSwipeToCloseGesture(
this.el,
ani,
() => {
/**
* While the gesture animation is finishing
* it is possible for a user to tap the backdrop.
* This would result in the dismiss animation
* being played again. Typically this is avoided
* by setting `presented = false` on the overlay
* component; however, we cannot do that here as
* that would prevent the element from being
* removed from the DOM.
*/
this.gestureAnimationDismissing = true;
this.animation!.onFinish(async () => {
await this.dismiss(undefined, 'gesture');
this.gestureAnimationDismissing = false;
});
},
);
this.gesture.enable(true);
if (this.swipeToClose) {
this.initSwipeToClose();
}
}

private initSwipeToClose() {
if (getIonMode(this) !== 'ios') { return; }

// All of the elements needed for the swipe gesture
// should be in the DOM and referenced by now, except
// for the presenting el
const animationBuilder = this.leaveAnimation || config.get('modalLeave', iosLeaveAnimation);
const ani = this.animation = animationBuilder(this.el, this.presentingElement);
this.gesture = createSwipeToCloseGesture(
this.el,
ani,
() => {
/**
* While the gesture animation is finishing
* it is possible for a user to tap the backdrop.
* This would result in the dismiss animation
* being played again. Typically this is avoided
* by setting `presented = false` on the overlay
* component; however, we cannot do that here as
* that would prevent the element from being
* removed from the DOM.
*/
this.gestureAnimationDismissing = true;
this.animation!.onFinish(async () => {
await this.dismiss(undefined, 'gesture');
this.gestureAnimationDismissing = false;
});
},
);
this.gesture.enable(true);
}

/**
* Dismiss the modal overlay after it has been presented.
*
Expand Down

0 comments on commit 4bd9134

Please sign in to comment.