NativeScript/angular

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.

cjohn001 opened this issue · 1 comments

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

Hello together,
I was able to find a workaround for the problem which may help to analyse the source of the issue. Interestingly when I provide margin-left as inline style (style="margin-left: 5;") than the transition animation works as expected. Seems like cancelation of the animation somehow breaks something CSS related.

<Label buttonTouchAnimation class="fsap icon-button" style="margin-left: 5;" text="&#xe08d;" (tap)="onTap()" horizontalAlignment="left" verticalAlignment="center"></Label>