Skip to content

ios only: starting a transition animation when another transition is pending causes current page to be deleted, seems to be related to a CSS bug. #105

@cjohn001

Description

@cjohn001

Environment
Provide version numbers for the following components (information can be retrieved by running tns info in your project folder or by inspecting the package.json of the project):
tns info
✔ Getting NativeScript components versions information...
✔ Component nativescript has 8.4.0 version and is up to date.
✔ Component @nativescript/core has 8.4.3 version and is up to date.
✔ Component @nativescript/ios has 8.4.0 version and is up to date.
✔ Component @nativescript/android has 8.4.0 version and is up to date.
"@angular/animations": "15.0.4",
"@angular/common": "15.0.4",
"@angular/compiler": "15.0.4",
"@angular/core": "15.0.4",
"@angular/forms": "15.0.4",
"@angular/platform-browser": "15.0.4",
"@angular/platform-browser-dynamic": "15.0.4",
"@angular/router": "15.0.4",
"@nativescript/angular": "15.0.1",
"@nativescript/core": "8.4.3",

Describe the bug
When a transition animation is triggered during another transition animation is pending, this leads to the current page to be deleted, see example video. I suspect it to be related somehow with Animation cancel events as I am seeing the issue arising when canceled animations are present (Trace.categories.Animation)

To Reproduce
You can create a button which starts a navigation transition. If you quickly press the button 2 times, the second navigation requests deletes the current page. Seems like canceling of the pending transition brakes the ui
this.router.navigate( ['someRoute'], { transition: { name: 'slideLeft' }, clearHistory: false } );

I am seeing the issue in different places. For example on a button tap I call a dismissSoftInput followed by a router.navigate call, which, when quickly double taped, breaks the ui.
In a different place I am using a Label as a button which when tapped calls a router.navigate. Quick double tap again breaks ui. There I have the following directive attached to the label. Double tap cancels the animation and I assume therefore breaks the ui


@Directive({
	selector: '[buttonTouchAnimation]'
})
export class ButtonTouchAnimationDirective {
	private _element: ElementRef;
	private _currentAnimation: Animation;
	private _baseBackgroundColor: Color;
	//////////////////////////////////////////////////////////////////////////////////////////////////
	constructor(el: ElementRef) {
		this._element = el;
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////
	@HostListener('touch', ['$event'])
	onTouch(args: TouchGestureEventData): void {
		const view = this._element.nativeElement as View;
		if (view.isEnabled) {
			if (args.action === 'down') {
				this._baseBackgroundColor = view.backgroundColor as Color;
				view._goToVisualState('highlighted');
				this.animatePressed();
			} else if (args.action === 'up' || args.action === 'cancel') {
				view._goToVisualState('normal');
				this.animateReleased();
			}
		}
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////
	private async animatePressed(): Promise<void> {
		if (this._currentAnimation?.isPlaying) {
			this._currentAnimation.cancel();
		}
		this._currentAnimation = (this._element.nativeElement as View).createAnimation({
			backgroundColor: new Color(255, 64, 81, 97),
			curve: CoreTypes.AnimationCurve.easeIn,
			duration: TAP_ACTION_INTERVAL
		});
		this._currentAnimation.play().catch((e: any) => {});
	}
	//////////////////////////////////////////////////////////////////////////////////////////////////
	private async animateReleased(): Promise<void> {
		if (!this._currentAnimation?.isPlaying) {
			this._currentAnimation.cancel();
		}
		this._currentAnimation = this._element.nativeElement
			.animate({
				backgroundColor: this._baseBackgroundColor,
				curve: CoreTypes.AnimationCurve.easeIn,
				duration: TAP_ACTION_INTERVAL
			})
			.catch((e: any) => {});
	}
}

Expected behavior
the transition does not break even if called twice. Second transition should be canceled instead of interrupting the ongoing transition

Example.mov

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions