chore: cleanup

This commit is contained in:
Nathan Walker
2023-03-17 22:54:33 -07:00
parent 1e72b89b7e
commit fd228dbff5
7 changed files with 115 additions and 63 deletions

View File

@@ -15,7 +15,11 @@ export class TransitionsModel extends Observable {
page.frame.navigate({
moduleName: `pages/transitions/transitions-detail`,
transition: SharedTransition.custom(new PageTransition(), {
interactiveDismissal: true,
interactive: {
dismiss: {
finishThreshold: 0.5,
},
},
// toPageStart: {
// duration: 400,
// },
@@ -29,7 +33,11 @@ export class TransitionsModel extends Observable {
openModal() {
page.showModal('pages/transitions/transitions-modal', {
transition: SharedTransition.custom(new ModalTransition(), {
interactiveDismissal: true,
interactive: {
dismiss: {
finishThreshold: 0.5,
},
},
toPageStart: {
y: 200,
// duration: 400,

View File

@@ -6,6 +6,7 @@ import { ViewCommon, isEnabledProperty, originXProperty, originYProperty, isUser
import { ShowModalOptions, hiddenProperty } from '../view-base';
import { Trace } from '../../../trace';
import { layout, iOSNativeHelper } from '../../../utils';
import { isNumber } from '../../../utils/types';
import { IOSHelper } from './view-helper';
import { ios as iosBackground, Background } from '../../styling/background';
import { perspectiveProperty, visibilityProperty, opacityProperty, rotateProperty, rotateXProperty, rotateYProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty, zIndexProperty, backgroundInternalProperty, clipPathProperty } from '../../styling/style-properties';
@@ -32,7 +33,7 @@ const majorVersion = iOSNativeHelper.MajorVersion;
export class View extends ViewCommon implements ViewDefinition {
nativeViewProtected: UIView;
viewController: UIViewController;
transitionIteractiveCtrl: UIPercentDrivenInteractiveTransition;
transitionInteractiveCtrl: UIPercentDrivenInteractiveTransition;
private _popoverPresentationDelegate: IOSHelper.UIPopoverPresentationControllerDelegateImp;
private _adaptivePresentationDelegate: IOSHelper.UIAdaptivePresentationControllerDelegateImp;
private _transitioningDelegate: UIViewControllerTransitioningDelegateImpl;
@@ -473,7 +474,7 @@ export class View extends ViewCommon implements ViewDefinition {
this._transitioningDelegate = UIViewControllerTransitioningDelegateImpl.initWithOwner(new WeakRef(options.transition.instance), new WeakRef(this));
controller.transitioningDelegate = this._transitioningDelegate;
const transitionState = SharedTransition.getState(options.transition.instance.id);
if (transitionState?.interactiveDismissal) {
if (transitionState?.interactive?.dismiss) {
// interactive transitions via gestures
// TODO - these could be typed as: boolean | (view: View) => void
// to allow users to define their own custom gesture dismissals
@@ -563,11 +564,13 @@ export class View extends ViewCommon implements ViewDefinition {
private _interactiveDismissGestureHandler(args: PanGestureEventData) {
if (args?.ios?.view) {
this.interactiveDismissGestureBegan = true;
this.interactiveDismissGestureCancelled = false;
const percent = args.deltaY / (args.ios.view.bounds.size.height / 2);
this._updateInteractiveTransition({
began: true,
cancelled: false,
});
const percent = this.interactiveTransition?.options.percentFormula ? this.interactiveTransition?.options.percentFormula(args) : args.deltaY / (args.ios.view.bounds.size.height / 2);
if (SharedTransition.DEBUG) {
console.log('interactive dismissal pan:', percent);
console.log('Interactive dismissal percentage:', percent);
}
switch (args.state) {
case GestureStateTypes.began:
@@ -576,21 +579,23 @@ export class View extends ViewCommon implements ViewDefinition {
}
break;
case GestureStateTypes.changed:
// TODO: allow customization of threshold
if (percent < 1) {
if (this.transitionIteractiveCtrl) {
this.transitionIteractiveCtrl.updateInteractiveTransition(percent);
if (this.transitionInteractiveCtrl) {
this.transitionInteractiveCtrl.updateInteractiveTransition(percent);
}
}
break;
case GestureStateTypes.cancelled:
case GestureStateTypes.ended:
if (this.transitionIteractiveCtrl) {
if (percent > 0.5) {
this.transitionIteractiveCtrl.finishInteractiveTransition();
if (this.transitionInteractiveCtrl) {
const finishThreshold = isNumber(this.interactiveTransition?.options?.finishThreshold) ? this.interactiveTransition?.options?.finishThreshold : 0.5;
if (percent > finishThreshold) {
this.transitionInteractiveCtrl.finishInteractiveTransition();
} else {
this.interactiveDismissGestureCancelled = true;
this.transitionIteractiveCtrl.cancelInteractiveTransition();
this._updateInteractiveTransition({
cancelled: true,
});
this.transitionInteractiveCtrl.cancelInteractiveTransition();
}
}
break;
@@ -619,9 +624,9 @@ export class View extends ViewCommon implements ViewDefinition {
}
parentController.dismissViewControllerAnimatedCompletion(animated, () => {
if (!this.interactiveDismissGestureCancelled) {
if (!this.interactiveTransition?.cancelled) {
this._transitioningDelegate = null;
this.transitionIteractiveCtrl = null;
this.transitionInteractiveCtrl = null;
this.off('pan', this._interactiveDismissGesture);
if (this._modalAnimatedOptions) {
this._modalAnimatedOptions.pop();
@@ -1013,9 +1018,9 @@ class UIViewControllerTransitioningDelegateImpl extends NSObject implements UIVi
if (owner?.iosInteractionDismiss) {
const ownerView = this.ownerView?.deref();
if (ownerView) {
if (ownerView.interactiveDismissGestureBegan) {
ownerView.transitionIteractiveCtrl = owner.iosInteractionDismiss(animator);
return ownerView.transitionIteractiveCtrl;
if (ownerView.interactiveTransition?.began) {
ownerView.transitionInteractiveCtrl = owner.iosInteractionDismiss(animator);
return ownerView.transitionInteractiveCtrl;
}
}
}

View File

@@ -27,7 +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';
import { SharedTransition, SharedTransitionInteractiveOptions } from '../../transition/shared-transition';
// helpers (these are okay re-exported here)
export * from './view-helper';
@@ -69,6 +69,8 @@ export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator
export const _rootModalViews = new Array<ViewBase>();
type InteractiveTransitionState = { began?: boolean; cancelled?: boolean; options?: SharedTransitionInteractiveOptions };
export abstract class ViewCommon extends ViewBase implements ViewDefinition {
public static layoutChangedEvent = 'layoutChanged';
public static shownModallyEvent = 'shownModally';
@@ -94,8 +96,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
public _modalParent: ViewCommon;
private _modalContext: any;
private _modal: ViewCommon;
interactiveDismissGestureBegan = false;
interactiveDismissGestureCancelled = false;
interactiveTransition: InteractiveTransitionState;
private _measuredWidth: number;
private _measuredHeight: number;
@@ -249,6 +250,13 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
return false;
}
_updateInteractiveTransition(state: InteractiveTransitionState) {
this.interactiveTransition = {
...(this.interactiveTransition || {}),
...state,
};
}
_setupAsRootView(context: any): void {
super._setupAsRootView(context);
if (!this._styleScope) {
@@ -415,14 +423,16 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
};
const whenClosedCallback = () => {
if (this.interactiveDismissGestureBegan) {
this.interactiveDismissGestureBegan = false;
if (!this.interactiveDismissGestureCancelled) {
if (this.interactiveTransition?.began) {
this._updateInteractiveTransition({
began: false,
});
if (!this.interactiveTransition?.cancelled) {
cleanupModalViews();
}
}
if (!this.interactiveDismissGestureCancelled) {
if (!this.interactiveTransition?.cancelled) {
if (typeof options.closeCallback === 'function') {
options.closeCallback.apply(undefined, originalArgs);
}
@@ -431,7 +441,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
}
};
if (!this.interactiveDismissGestureBegan) {
if (!this.interactiveTransition?.began) {
cleanupModalViews();
}

View File

@@ -30,7 +30,7 @@ let navDepth = -1;
export class Frame extends FrameBase {
viewController: UINavigationControllerImpl;
_animatedDelegate = <UINavigationControllerDelegate>UINavigationControllerAnimatedDelegate.initWithOwner(new WeakRef(this));
transitionIteractiveCtrl: UIPercentDrivenInteractiveTransition;
transitionInteractiveCtrl: UIPercentDrivenInteractiveTransition;
public _ios: iOSFrame;
private _interactiveDismissGesture: (args: PanGestureEventData) => void;
@@ -106,10 +106,12 @@ export class Frame extends FrameBase {
this._ios.controller.delegate = this._animatedDelegate;
viewController[DELEGATE] = this._animatedDelegate;
const transitionState = SharedTransition.getState(navigationTransition.instance.id);
if (transitionState?.interactiveDismissal) {
if (transitionState?.interactive?.dismiss) {
this._updateInteractiveTransition({
options: transitionState?.interactive?.dismiss,
});
// interactive transitions via gestures
// TODO - these could be typed as: boolean | (view: View) => void
// to allow users to define their own custom gesture dismissals
// TODO - allow users to define their own custom gesture dismissals
this._interactiveDismissGesture = this._interactiveDismissGestureHandler.bind(this);
this.on('pan', this._interactiveDismissGesture);
}
@@ -198,35 +200,42 @@ export class Frame extends FrameBase {
private _interactiveDismissGestureHandler(args: PanGestureEventData) {
if (args?.ios?.view) {
this.interactiveDismissGestureBegan = true;
this.interactiveDismissGestureCancelled = false;
const percent = args.deltaX / (args.ios.view.bounds.size.width / 2);
this._updateInteractiveTransition({
began: true,
cancelled: false,
});
const percent = this.interactiveTransition?.options.percentFormula ? this.interactiveTransition?.options.percentFormula(args) : args.deltaX / (args.ios.view.bounds.size.width / 2);
if (SharedTransition.DEBUG) {
console.log('interactive dismissal pan:', percent);
console.log('Interactive dismissal percentage:', percent);
}
switch (args.state) {
case GestureStateTypes.began:
// const navigationContext = this.parent.page.frame._navigationQueue[0];
// this.performGoBack(navigationContext);
this._ios.controller.popViewControllerAnimated(true);
// this._ios.controller.popViewControllerAnimated(true);
this._goBackCore(this.backStack.slice(-1)[0]);
break;
case GestureStateTypes.changed:
// TODO: allow customization of threshold
if (percent < 1) {
if (this.transitionIteractiveCtrl) {
this.transitionIteractiveCtrl.updateInteractiveTransition(percent);
if (this.transitionInteractiveCtrl) {
this.transitionInteractiveCtrl.updateInteractiveTransition(percent);
}
}
break;
case GestureStateTypes.cancelled:
case GestureStateTypes.ended:
if (this.transitionIteractiveCtrl) {
if (percent > 0.5) {
this.transitionIteractiveCtrl.finishInteractiveTransition();
if (this.transitionInteractiveCtrl) {
const finishThreshold = isNumber(this.interactiveTransition?.options?.finishThreshold) ? this.interactiveTransition?.options?.finishThreshold : 0.5;
if (percent > finishThreshold) {
this.callUnloaded();
this._tearDownUI(true);
this.transitionInteractiveCtrl.finishInteractiveTransition();
} else {
this.interactiveDismissGestureCancelled = true;
this.transitionIteractiveCtrl.cancelInteractiveTransition();
this._updateInteractiveTransition({
cancelled: true,
});
this.transitionInteractiveCtrl.cancelInteractiveTransition();
}
}
break;
@@ -253,7 +262,7 @@ export class Frame extends FrameBase {
const controller = backstackEntry.resolvedPage.ios;
const animated = this._currentEntry ? this._getIsAnimatedNavigation(this._currentEntry.entry) : false;
if (!this.interactiveDismissGestureCancelled) {
if (!this.interactiveTransition?.cancelled) {
this._updateActionBar(backstackEntry.resolvedPage);
}
if (Trace.isEnabled()) {
@@ -475,9 +484,9 @@ class UINavigationControllerAnimatedDelegate extends NSObject implements UINavig
navigationControllerInteractionControllerForAnimationController(navigationController: UINavigationController, animationController: UIViewControllerAnimatedTransitioning): UIViewControllerInteractiveTransitioning {
const owner = this.owner?.deref();
if (owner) {
if (owner.interactiveDismissGestureBegan) {
owner.transitionIteractiveCtrl = PercentInteractiveController.initWithOwner(new WeakRef(this.transition));
return owner.transitionIteractiveCtrl;
if (owner.interactiveTransition?.began) {
owner.transitionInteractiveCtrl = PercentInteractiveController.initWithOwner(new WeakRef(this.transition));
return owner.transitionInteractiveCtrl;
}
}
@@ -500,12 +509,11 @@ class PercentInteractiveController extends UIPercentDrivenInteractiveTransition
}
startInteractiveTransition(transitionContext: UIViewControllerContextTransitioning) {
console.log('startInteractiveTransition');
// console.log('startInteractiveTransition');
this.transitionContext = transitionContext;
}
updateInteractiveTransition(percentComplete: number) {
console.log('percentComplete:', percentComplete);
const owner: any = this.owner?.deref();
if (owner) {
if (!this.started) {
@@ -534,7 +542,7 @@ class PercentInteractiveController extends UIPercentDrivenInteractiveTransition
}
cancelInteractiveTransition() {
console.log('cancelInteractiveTransition');
// console.log('cancelInteractiveTransition');
const owner: any = this.owner?.deref();
if (owner && this.started) {
const state = SharedTransition.getState(owner.id);
@@ -562,7 +570,7 @@ class PercentInteractiveController extends UIPercentDrivenInteractiveTransition
}
finishInteractiveTransition() {
console.log('finishInteractiveTransition');
// console.log('finishInteractiveTransition');
const owner: any = this.owner?.deref();
if (owner && this.started) {
if (this.backgroundAnimation) {

View File

@@ -65,7 +65,6 @@ class PercentInteractiveController extends UIPercentDrivenInteractiveTransition
}
updateInteractiveTransition(percentComplete: number) {
// console.log('percentComplete:', percentComplete);
const owner = this.owner?.deref();
if (owner) {
if (!this.started) {
@@ -185,7 +184,7 @@ class ModalTransitionController extends NSObject implements UIViewControllerAnim
const { sharedElements, presented } = SharedTransition.getSharedElements(state.page, state.toPage);
if (SharedTransition.DEBUG) {
console.log(' ');
console.log(' ModalTransition: Present');
console.log(
`1. Found sharedTransitionTags to animate:`,
sharedElements.map((v) => v.sharedTransitionTag)
@@ -362,7 +361,7 @@ class ModalTransitionController extends NSObject implements UIViewControllerAnim
// console.log('transitionContext.containerView.subviews.count:', transitionContext.containerView.subviews.count);
if (SharedTransition.DEBUG) {
console.log(' ');
console.log(' ModalTransition: Dismiss');
console.log(
`1. Dismiss sharedTransitionTags to animate:`,
owner.sharedElements.presented.map((p) => p.view.sharedTransitionTag)

View File

@@ -38,7 +38,7 @@ export class PageTransition extends Transition {
const { sharedElements, presented } = SharedTransition.getSharedElements(state.page, state.toPage);
if (SharedTransition.DEBUG) {
console.log(' ');
console.log(' PageTransition: Push');
console.log(
`1. Found sharedTransitionTags to animate:`,
sharedElements.map((v) => v.sharedTransitionTag)
@@ -216,7 +216,7 @@ export class PageTransition extends Transition {
// console.log('transitionContext.containerView.subviews.count:', transitionContext.containerView.subviews.count);
if (SharedTransition.DEBUG) {
console.log(' ');
console.log(' PageTransition: Pop');
console.log(
`1. Dismiss sharedTransitionTags to animate:`,
this.sharedElements.presented.map((p) => p.view.sharedTransitionTag)

View File

@@ -1,6 +1,7 @@
import type { Transition } from '.';
import { querySelectorAll, ViewBase } from '../core/view-base';
import type { View } from '../core/view';
import type { PanGestureEventData } from '../gestures';
export const DEFAULT_DURATION = 0.35;
export const DEFAULT_SPRING = {
@@ -12,19 +13,40 @@ export enum SharedTransitionAnimationType {
present,
dismiss,
}
export interface SharedTransitionInteractiveOptions {
/**
* When the pan exceeds this percentage and you let go, finish the transition.
* Default 0.5
*/
finishThreshold?: number;
/**
* You can create your own percent formula used for determing the interactive value.
* By default, we handle this via a formula like this for an interactive page back transition:
* - return eventData.deltaX / (eventData.ios.view.bounds.size.width / 2);
* @param eventData PanGestureEventData
* @returns Should return a percentage value
*/
percentFormula?: (eventData: PanGestureEventData) => number;
}
export interface SharedTransitionConfig {
/**
* Page which will start the transition
* Page which will start the transition.
*/
page?: ViewBase;
/**
* Preconfigured transition or your own custom configured one
* Preconfigured transition or your own custom configured one.
*/
instance?: Transition;
/**
* Whether you want to allow interactive dismissal
* Interactive transition settings. (iOS only at the moment)
*/
interactiveDismissal?: boolean;
interactive?: {
/**
* Whether you want to allow interactive dismissal.
* Defaults to using 'pan' gesture for dismissal however you can customize your own.
*/
dismiss?: SharedTransitionInteractiveOptions;
};
/**
* View settings to start your transition.
*/