diff --git a/apps/toolbox/src/pages/transitions.ts b/apps/toolbox/src/pages/transitions.ts index 448d068c6..826d3711f 100644 --- a/apps/toolbox/src/pages/transitions.ts +++ b/apps/toolbox/src/pages/transitions.ts @@ -13,38 +13,29 @@ export class TransitionsModel extends Observable { open() { page.frame.navigate({ moduleName: `pages/transitions/transitions-detail`, - transition: { - instance: SharedTransition.configure({ - page, - instance: new PageTransition(), - toPageStart: { - duration: 1000, - }, - fromPageEnd: { - duration: 500, - }, - }), - }, + transition: SharedTransition.custom(new PageTransition(), { + toPageStart: { + duration: 1000, + }, + fromPageEnd: { + duration: 500, + }, + }), }); } openModal() { page.showModal('pages/transitions/transitions-modal', { - context: {}, - transition: { - instance: SharedTransition.configure({ - page, - instance: new ModalTransition(), - toPageStart: { - y: 200, - duration: 1000, - }, - fromPageEnd: { - y: 100, - duration: 500, - }, - }), - }, + transition: SharedTransition.custom(new ModalTransition(), { + toPageStart: { + y: 200, + duration: 1000, + }, + fromPageEnd: { + y: 100, + duration: 500, + }, + }), closeCallback(args) { console.log('close modal callback', args); }, diff --git a/packages/core/ui/core/view/view-common.ts b/packages/core/ui/core/view/view-common.ts index a166daf04..e1d1a96cb 100644 --- a/packages/core/ui/core/view/view-common.ts +++ b/packages/core/ui/core/view/view-common.ts @@ -27,6 +27,7 @@ import { AccessibilityEventOptions, AccessibilityLiveRegion, AccessibilityRole, import { accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityValueProperty, accessibilityIgnoresInvertColorsProperty } from '../../../accessibility/accessibility-properties'; import { accessibilityBlurEvent, accessibilityFocusChangedEvent, accessibilityFocusEvent, accessibilityPerformEscapeEvent, getCurrentFontScale } from '../../../accessibility'; import { CSSShadow } from '../../styling/css-shadow'; +import { SharedTransition } from '../../transition/shared-transition'; // helpers (these are okay re-exported here) export * from './view-helper'; @@ -362,7 +363,12 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { public showModal(...args): ViewDefinition { const { view, options } = this.getModalOptions(args); - + if (options.transition?.instance) { + SharedTransition.updateState(options.transition?.instance.id, { + page: this, + toPage: view, + }); + } view._showNativeModalView(this, options); return view; diff --git a/packages/core/ui/frame/frame-common.ts b/packages/core/ui/frame/frame-common.ts index f16484b23..68c3e8016 100644 --- a/packages/core/ui/frame/frame-common.ts +++ b/packages/core/ui/frame/frame-common.ts @@ -11,6 +11,7 @@ import { Builder } from '../builder'; import { sanitizeModuleName } from '../builder/module-name-sanitizer'; import { profile } from '../../profiling'; import { FRAME_SYMBOL } from './frame-helpers'; +import { SharedTransition } from '../transition/shared-transition'; export { NavigationType } from './frame-interfaces'; export type { AndroidActivityCallbacks, AndroidFragmentCallbacks, AndroidFrame, BackstackEntry, NavigationContext, NavigationEntry, NavigationTransition, TransitionState, ViewEntry, iOSFrame } from './frame-interfaces'; @@ -398,6 +399,13 @@ export class FrameBase extends CustomLayoutView { const backstackEntry = navigationContext.entry; const isBackNavigation = navigationContext.navigationType === NavigationType.back; this._onNavigatingTo(backstackEntry, isBackNavigation); + const navigationTransition = this._getNavigationTransition(backstackEntry.entry); + if (navigationTransition?.instance) { + SharedTransition.updateState(navigationTransition?.instance.id, { + page: this.currentPage, + toPage: this, + }); + } this._navigateCore(backstackEntry); } diff --git a/packages/core/ui/page/index.ios.ts b/packages/core/ui/page/index.ios.ts index f2c1faaaa..25b8434fc 100644 --- a/packages/core/ui/page/index.ios.ts +++ b/packages/core/ui/page/index.ios.ts @@ -427,12 +427,8 @@ export class Page extends PageBase { constructor() { super(); const controller = UIViewControllerImpl.initWithOwner(new WeakRef(this)); - this.viewController = this._ios = controller; - - // Make transitions look good controller.view.backgroundColor = this._backgroundColor; - console.log('here for Page:', this.viewController); - SharedTransition.addPageToTop(this); + this.viewController = this._ios = controller; } createNativeView() { diff --git a/packages/core/ui/transition/modal-transition.ios.ts b/packages/core/ui/transition/modal-transition.ios.ts index f7677866d..b50b1dfd4 100644 --- a/packages/core/ui/transition/modal-transition.ios.ts +++ b/packages/core/ui/transition/modal-transition.ios.ts @@ -168,8 +168,7 @@ class ModalTransitionController extends NSObject implements UIViewControllerAnim for (const presenting of owner.sharedElements.presenting) { presenting.snapshot.removeFromSuperview(); } - SharedTransition.updateState({ - id: owner.id, + SharedTransition.updateState(owner.id, { activeType: SharedTransitionAnimationType.dismiss, }); transitionContext.completeTransition(true); diff --git a/packages/core/ui/transition/page-transition.ios.ts b/packages/core/ui/transition/page-transition.ios.ts index 8e76decf0..7d85a0181 100644 --- a/packages/core/ui/transition/page-transition.ios.ts +++ b/packages/core/ui/transition/page-transition.ios.ts @@ -107,8 +107,7 @@ export class PageTransition extends Transition { presentingView.opacity = 0; presentedView.opacity = 0; // add snapshot to animate - // transitionContext.containerView.addSubview(sharedElementSnapshot); - transitionContext.containerView.insertSubviewAboveSubview(sharedElementSnapshot, this.presented.view); + transitionContext.containerView.addSubview(sharedElementSnapshot); } const cleanupPresent = () => { @@ -129,8 +128,7 @@ export class PageTransition extends Transition { for (const presenting of this.sharedElements.presenting) { presenting.snapshot.removeFromSuperview(); } - SharedTransition.updateState({ - id: this.id, + SharedTransition.updateState(this.id, { activeType: SharedTransitionAnimationType.dismiss, }); transitionContext.completeTransition(true); @@ -219,7 +217,6 @@ export class PageTransition extends Transition { for (const p of this.sharedElements.presenting) { p.snapshot.alpha = p.endOpacity; transitionContext.containerView.addSubview(p.snapshot); - // transitionContext.containerView.insertSubviewBelowSubview(p.snapshot, fromViewCtrl.view); } const cleanupDismiss = () => { diff --git a/packages/core/ui/transition/shared-transition.ts b/packages/core/ui/transition/shared-transition.ts index 829b99810..ff48464ba 100644 --- a/packages/core/ui/transition/shared-transition.ts +++ b/packages/core/ui/transition/shared-transition.ts @@ -1,7 +1,6 @@ import type { Transition } from '.'; -import { querySelectorAll } from '../core/view-base'; +import { querySelectorAll, ViewBase } from '../core/view-base'; import type { View } from '../core/view'; -import type { Page } from '../page'; export const DEFAULT_DURATION = 0.35; // always increment when adding new transitions to be able to track their state @@ -13,7 +12,7 @@ export interface SharedTransitionConfig { /** * Page which will start the transition */ - page?: Page; + page?: ViewBase; /** * Preconfigured transition or your own custom configured one */ @@ -32,9 +31,8 @@ export interface SharedTransitionConfig { fromPageEnd?: SharedTransitionPageProperties; } export interface SharedTransitionState extends SharedTransitionConfig { - id?: number; activeType?: SharedTransitionAnimationType; - toPage?: Page; + toPage?: ViewBase; } type SharedTransitionPageProperties = { x?: number; @@ -48,27 +46,26 @@ type SharedTransitionPageProperties = { duration?: number; }; /** - * Shared Element Transition (experimental) + * Shared Element Transitions (experimental) * - * no - * Note: some APIs may change in subsequent releases + * Note: some APIs may change in future releases */ export class SharedTransition { - static configure(options: SharedTransitionConfig): Transition { - SharedTransition.updateState({ + static custom(instance: Transition, options: SharedTransitionConfig): { instance: Transition } { + SharedTransition.updateState(instance.id, { ...options, - id: options.instance.id, + instance, activeType: SharedTransitionAnimationType.present, }); - return options.instance; + return { instance }; } static currentStack: Array; - static updateState(state: SharedTransitionState) { + static updateState(id: number, state: SharedTransitionState) { if (!SharedTransition.currentStack) { SharedTransition.currentStack = []; } - const existingTransition = SharedTransition.getState(state.id); + const existingTransition = SharedTransition.getState(id); if (existingTransition) { // updating existing for (const key in state) { @@ -79,29 +76,18 @@ export class SharedTransition { SharedTransition.currentStack.push(state); } } - static addPageToTop(page: Page) { - if (SharedTransition.currentStack?.length) { - const top = SharedTransition.currentStack.slice(-1)[0]; - if (top) { - SharedTransition.updateState({ - id: top.id, - toPage: page, - }); - } - } - } static getState(id: number) { - return SharedTransition.currentStack.find((t) => t.id === id); + return SharedTransition.currentStack.find((t) => t.instance.id === id); } static finishState(id: number) { - const index = SharedTransition.currentStack.findIndex((t) => t.id === id); + const index = SharedTransition.currentStack.findIndex((t) => t.instance.id === id); if (index > -1) { SharedTransition.currentStack.splice(index, 1); } } static getSharedElements( - fromPage: Page, - toPage: Page + fromPage: ViewBase, + toPage: ViewBase ): { sharedElements: Array; presented: Array;