perf(many): reduce delay when performing overlay or page transitions (#26189)

resolves #24346
This commit is contained in:
Liam DeBeasi
2022-11-01 12:08:27 -05:00
committed by GitHub
parent eea6ba996c
commit 30e3a1485d
8 changed files with 57 additions and 56 deletions

View File

@ -271,7 +271,6 @@ export class StackController {
if ((containerEl as any).commit) {
return containerEl.commit(enteringEl, leavingEl, {
deepWait: true,
duration: direction === undefined ? 0 : undefined,
direction,
showGoBack,

View File

@ -17,7 +17,7 @@ import type {
} from '../../interface';
import { findIonContent, printIonContentErrorMsg } from '../../utils/content';
import { CoreDelegate, attachComponent, detachComponent } from '../../utils/framework-delegate';
import { raf, inheritAttributes } from '../../utils/helpers';
import { raf, inheritAttributes, hasLazyBuild } from '../../utils/helpers';
import type { Attributes } from '../../utils/helpers';
import { KEYBOARD_DID_OPEN } from '../../utils/keyboard/keyboard';
import { printIonWarning } from '../../utils/logging';
@ -436,7 +436,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
return;
}
const { presentingElement } = this;
const { presentingElement, el } = this;
/**
* When using an inline modal
@ -462,9 +462,8 @@ export class Modal implements ComponentInterface, OverlayInterface {
};
const { inline, delegate } = this.getDelegate(true);
this.usersElement = await attachComponent(delegate, this.el, this.component, ['ion-page'], data, inline);
await deepReady(this.usersElement);
this.usersElement = await attachComponent(delegate, el, this.component, ['ion-page'], data, inline);
hasLazyBuild(el) && (await deepReady(this.usersElement));
writeTask(() => this.el.classList.add('show-modal'));

View File

@ -16,7 +16,7 @@ import type {
TriggerAction,
} from '../../interface';
import { CoreDelegate, attachComponent, detachComponent } from '../../utils/framework-delegate';
import { addEventListener, raf } from '../../utils/helpers';
import { addEventListener, raf, hasLazyBuild } from '../../utils/helpers';
import { BACKDROP, dismiss, eventMethod, focusFirstDescendant, prepareOverlay, present } from '../../utils/overlays';
import { isPlatform } from '../../utils/platform';
import { getClassMap } from '../../utils/theme';
@ -431,14 +431,16 @@ export class Popover implements ComponentInterface, PopoverInterface {
await this.currentTransition;
}
const { el } = this;
const data = {
...this.componentProps,
popover: this.el,
};
const { inline, delegate } = this.getDelegate(true);
this.usersElement = await attachComponent(delegate, this.el, this.component, ['popover-viewport'], data, inline);
await deepReady(this.usersElement);
this.usersElement = await attachComponent(delegate, el, this.component, ['popover-viewport'], data, inline);
hasLazyBuild(el) && (await deepReady(this.usersElement));
if (!this.keyboardEvents) {
this.configureKeyboardInteraction();

View File

@ -19,7 +19,7 @@ import type {
} from '../../interface';
import { getTimeGivenProgression } from '../../utils/animation/cubic-bezier';
import { attachComponent, detachComponent } from '../../utils/framework-delegate';
import { shallowEqualStringMap } from '../../utils/helpers';
import { shallowEqualStringMap, hasLazyBuild } from '../../utils/helpers';
import { transition } from '../../utils/transition';
@Component({
@ -238,6 +238,13 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
enteringEl,
leavingEl,
baseEl: el,
/**
* We need to wait for all Stencil components
* to be ready only when using the lazy
* loaded bundle.
*/
deepWait: hasLazyBuild(el),
progressCallback: opts.progressAnimation
? (ani) => {
/**

View File

@ -76,6 +76,15 @@ export const componentOnReady = (el: any, callback: any) => {
}
};
/**
* This functions checks if a Stencil component is using
* the lazy loaded build of Stencil. Returns `true` if
* the component is lazy loaded. Returns `false` otherwise.
*/
export const hasLazyBuild = (stencilEl: HTMLElement) => {
return (stencilEl as any).componentOnReady !== undefined;
};
export type Attributes = { [key: string]: any };
/**

View File

@ -7,7 +7,7 @@ import {
LIFECYCLE_WILL_LEAVE,
} from '../../components/nav/constants';
import type { Animation, AnimationBuilder, NavDirection, NavOptions } from '../../interface';
import { componentOnReady, raf } from '../helpers';
import { raf } from '../helpers';
const iosTransitionAnimation = () => import('./ios.transition');
const mdTransitionAnimation = () => import('./md.transition');
@ -135,11 +135,11 @@ const noAnimation = async (opts: TransitionOptions): Promise<TransitionResult> =
const waitForReady = async (opts: TransitionOptions, defaultDeep: boolean) => {
const deep = opts.deepWait !== undefined ? opts.deepWait : defaultDeep;
const promises = deep
? [deepReady(opts.enteringEl), deepReady(opts.leavingEl)]
: [shallowReady(opts.enteringEl), shallowReady(opts.leavingEl)];
await Promise.all(promises);
if (deep) {
await Promise.all([deepReady(opts.enteringEl), deepReady(opts.leavingEl)]);
}
await notifyViewReady(opts.viewIsReady, opts.enteringEl);
};
@ -195,13 +195,6 @@ export const lifecycle = (el: HTMLElement | undefined, eventName: string) => {
}
};
const shallowReady = (el: Element | undefined): Promise<any> => {
if (el) {
return new Promise((resolve) => componentOnReady(el, resolve));
}
return Promise.resolve();
};
export const deepReady = async (el: any | undefined): Promise<void> => {
const element = el as any;
if (element) {

View File

@ -365,7 +365,6 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
}
await routerOutlet.commit(enteringEl, leavingEl, {
deepWait: true,
duration: skipTransition || directionToUse === undefined ? 0 : undefined,
direction: directionToUse,
showGoBack: !!routeInfo.pushedByRoute,

View File

@ -195,7 +195,7 @@ export const IonRouterOutlet = /*@__PURE__*/ defineComponent({
}
});
const transition = (
const transition = async (
enteringEl: HTMLElement,
leavingEl: HTMLElement,
direction: any, // TODO types
@ -203,23 +203,19 @@ export const IonRouterOutlet = /*@__PURE__*/ defineComponent({
progressAnimation: boolean,
animationBuilder?: AnimationBuilder
) => {
return new Promise(resolve => {
if (skipTransition) {
skipTransition = false;
return resolve(false);
return Promise.resolve(false);
}
if (enteringEl === leavingEl) {
return resolve(false);
return Promise.resolve(false);
}
requestAnimationFrame(() => {
requestAnimationFrame(async () => {
enteringEl.classList.add('ion-page-invisible');
const hasRootDirection = direction === undefined || direction === 'root' || direction === 'none';
const result = await ionRouterOutlet.value.commit(enteringEl, leavingEl, {
deepWait: true,
/**
* replace operations result in a direction of none.
* These typically do not have need animations, so we set
@ -235,10 +231,7 @@ export const IonRouterOutlet = /*@__PURE__*/ defineComponent({
animationBuilder
});
return resolve(result);
});
});
});
return result;
}
const handlePageTransition = async () => {