Skip to content

Commit

Permalink
fix(overlay): animation can be interrupted
Browse files Browse the repository at this point in the history
fixes #15506
  • Loading branch information
manucorporat committed Sep 13, 2018
1 parent 6e5c035 commit ca58664
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 32 deletions.
4 changes: 4 additions & 0 deletions core/src/components/animation-controller/animator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1152,6 +1152,9 @@ export class Animator {
* NO RECURSION
*/
_didFinish(hasCompleted: boolean) {
if (!this.isPlaying) {
return;
}
this.isPlaying = false;
this.hasCompleted = hasCompleted;

Expand Down Expand Up @@ -1189,6 +1192,7 @@ export class Animator {
* Recursively destroy this animation and all child animations.
*/
destroy() {
this._didFinish(false);
this._destroyed = true;

const children = this._childAnimations;
Expand Down
28 changes: 26 additions & 2 deletions core/src/components/modal/test/basic/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
<p>
<ion-button id="presentModal" class="e2ePresentModal" onclick="presentModal()">Present modal</ion-button>
</p>
<p>
<ion-button id="presentModal" class="e2ePresentModal" onclick="presentCloseModal()">Present and close modal</ion-button>
</p>
<p>
<ion-button id="presentModal" class="e2ePresentModal" onclick="presentCloseModal2()">Present and close modal (crash)</ion-button>
</p>
</ion-content>
<ion-modal-controller></ion-modal-controller>

Expand All @@ -30,8 +36,8 @@
<script>
window.addEventListener("ionModalDidDismiss", function (e) { console.log('DidDismiss', e) })
window.addEventListener("ionModalWillDismiss", function (e) { console.log('WillDismiss', e) })
async function presentModal() {

async function createModal() {
// initialize controller
const modalController = document.querySelector('ion-modal-controller');
await modalController.componentOnReady();
Expand Down Expand Up @@ -61,7 +67,25 @@ <h1>Content of doom</h1>
const modalElement = await modalController.create({
component: element
});
modalElement.present();
return modalElement;
}

async function presentModal() {
const modal = await createModal();
await modal.present();
}
async function presentCloseModal() {
const modal = await createModal();
await modal.present();
await modal.dismiss();
}

async function presentCloseModal2() {
const modal = await createModal();
modal.present();
setTimeout(() => {
modal.dismiss();
}, 20);
}
</script>
</body>
Expand Down
68 changes: 38 additions & 30 deletions core/src/utils/overlays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ export async function present(
? overlay.enterAnimation
: overlay.config.get(name, overlay.mode === 'ios' ? iosEnterAnimation : mdEnterAnimation);

await overlayAnimation(overlay, animationBuilder, overlay.el, opts);

overlay.didPresent.emit();
const completed = await overlayAnimation(overlay, animationBuilder, overlay.el, opts);
if (completed) {
overlay.didPresent.emit();
}
}

export async function dismiss(
Expand All @@ -115,15 +116,20 @@ export async function dismiss(
}
overlay.presented = false;

overlay.willDismiss.emit({ data, role });
try {
overlay.willDismiss.emit({ data, role });

const animationBuilder = (overlay.leaveAnimation)
? overlay.leaveAnimation
: overlay.config.get(name, overlay.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation);
const animationBuilder = (overlay.leaveAnimation)
? overlay.leaveAnimation
: overlay.config.get(name, overlay.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation);

await overlayAnimation(overlay, animationBuilder, overlay.el, opts);
await overlayAnimation(overlay, animationBuilder, overlay.el, opts);
overlay.didDismiss.emit({ data, role });

} catch (err) {
console.error(err);
}

overlay.didDismiss.emit({ data, role });
overlay.el.remove();
return true;
}
Expand All @@ -137,33 +143,35 @@ async function overlayAnimation(
animationBuilder: AnimationBuilder,
baseEl: HTMLElement,
opts: any
): Promise<void> {
): Promise<boolean> {
if (overlay.animation) {
overlay.animation.destroy();
overlay.animation = undefined;
}
return false;

// Make overlay visible in case it's hidden
baseEl.classList.remove('ion-page-invisible');
} else {
// Make overlay visible in case it's hidden
baseEl.classList.remove('ion-page-invisible');

const aniRoot = baseEl.shadowRoot || overlay.el;
const animation = overlay.animation = await overlay.animationCtrl.create(animationBuilder, aniRoot, opts);
overlay.animation = animation;
if (!overlay.animated) {
animation.duration(0);
}
if (overlay.keyboardClose) {
animation.beforeAddWrite(() => {
const activeElement = baseEl.ownerDocument.activeElement as HTMLElement;
if (activeElement && activeElement.matches('input, ion-input, ion-textarea')) {
activeElement.blur();
}
});
const aniRoot = baseEl.shadowRoot || overlay.el;
const animation = overlay.animation = await overlay.animationCtrl.create(animationBuilder, aniRoot, opts);
overlay.animation = animation;
if (!overlay.animated) {
animation.duration(0);
}
if (overlay.keyboardClose) {
animation.beforeAddWrite(() => {
const activeElement = baseEl.ownerDocument.activeElement as HTMLElement;
if (activeElement && activeElement.matches('input, ion-input, ion-textarea')) {
activeElement.blur();
}
});
}
await animation.playAsync();
animation.destroy();
overlay.animation = undefined;
return animation.hasCompleted;
}
await animation.playAsync();

animation.destroy();
overlay.animation = undefined;
}

export function autoFocus(containerEl: HTMLElement): HTMLElement | undefined {
Expand Down

0 comments on commit ca58664

Please sign in to comment.