Commit 948bf834 authored by John Lee's avatar John Lee Committed by Commit Bot

WebUI Tab Strip: Update swipe animation to only happen after tab closes

Previously, the swipe animation was mapped to where the user's pointer
would be and would make the tab element disappear before the close event
was confirmed. This CL sets it up such that the animation does not
progress and only detects when a swipe happens.

This is to address a bug where the front-end is not able to confirm
whether the tab was successfully closed, due to an unload dialog.

Bug: 1050747
Change-Id: Ia0a4658260ebd73a05bd616b4a8df5d4c4e2525e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2083403Reviewed-by: default avatardpapad <dpapad@chromium.org>
Commit-Queue: John Lee <johntlee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#746452}
parent 771857fe
...@@ -236,8 +236,6 @@ export class TabElement extends CustomElement { ...@@ -236,8 +236,6 @@ export class TabElement extends CustomElement {
/** @private */ /** @private */
onSwipe_() { onSwipe_() {
// Prevent slideOut animation from playing.
this.remove();
this.tabsApi_.closeTab(this.tab_.id, CloseTabAction.SWIPED_TO_CLOSE); this.tabsApi_.closeTab(this.tab_.id, CloseTabAction.SWIPED_TO_CLOSE);
} }
......
...@@ -161,10 +161,6 @@ export class TabSwiper { ...@@ -161,10 +161,6 @@ export class TabSwiper {
} }
const yDiff = this.currentPointerDownEvent_.clientY - event.clientY; const yDiff = this.currentPointerDownEvent_.clientY - event.clientY;
const animationTime = yDiff;
this.animation_.currentTime =
Math.max(0, Math.min(SWIPE_FINISH_THRESHOLD_PX, animationTime));
if (!this.animationInitiated_ && if (!this.animationInitiated_ &&
Math.abs(yDiff) > TRANSLATE_ANIMATION_THRESHOLD_PX) { Math.abs(yDiff) > TRANSLATE_ANIMATION_THRESHOLD_PX) {
this.animationInitiated_ = true; this.animationInitiated_ = true;
...@@ -181,22 +177,17 @@ export class TabSwiper { ...@@ -181,22 +177,17 @@ export class TabSwiper {
return; return;
} }
const pixelsSwiped = this.animation_.currentTime; const yDiff = this.currentPointerDownEvent_.clientY - event.clientY;
const pixelsSwiped =
Math.max(0, Math.min(SWIPE_FINISH_THRESHOLD_PX, yDiff));
const swipedEnoughToClose = pixelsSwiped > SWIPE_START_THRESHOLD_PX; const swipedEnoughToClose = pixelsSwiped > SWIPE_START_THRESHOLD_PX;
const wasHighVelocity = pixelsSwiped / const wasHighVelocity = pixelsSwiped /
(event.timeStamp - this.currentPointerDownEvent_.timeStamp) > (event.timeStamp - this.currentPointerDownEvent_.timeStamp) >
SWIPE_VELOCITY_THRESHOLD; SWIPE_VELOCITY_THRESHOLD;
if (pixelsSwiped === SWIPE_FINISH_THRESHOLD_PX) { if (pixelsSwiped === SWIPE_FINISH_THRESHOLD_PX || swipedEnoughToClose ||
// The user has swiped the max amount of pixels to swipe and the animation wasHighVelocity) {
// has already completed all its keyframes, so just fire the onfinish this.element_.dispatchEvent(new CustomEvent('swipe'));
// events on the animation.
this.animation_.finish();
} else if (swipedEnoughToClose || wasHighVelocity) {
this.animation_.play();
} else {
this.animation_.cancel();
this.animation_.currentTime = 0;
} }
this.clearPointerEvents_(); this.clearPointerEvents_();
......
...@@ -25,7 +25,7 @@ suite('TabSwiper', () => { ...@@ -25,7 +25,7 @@ suite('TabSwiper', () => {
tabSwiper.startObserving(); tabSwiper.startObserving();
}); });
test('swiping progresses the animation', () => { test('swiping does not progress the animation', () => {
// Set margin top 0 to avoid offsetting the bounding client rect. // Set margin top 0 to avoid offsetting the bounding client rect.
document.body.style.margin = 0; document.body.style.margin = 0;
...@@ -47,30 +47,24 @@ suite('TabSwiper', () => { ...@@ -47,30 +47,24 @@ suite('TabSwiper', () => {
let startTop = tabElement.getBoundingClientRect().top; let startTop = tabElement.getBoundingClientRect().top;
assertEquals(startTop, 0); assertEquals(startTop, 0);
// Swipe was enough to start animating the position. // Swiping did not start the animation.
pointerState.clientY = startY - (TRANSLATE_ANIMATION_THRESHOLD_PX + 1); pointerState.clientY = startY - (TRANSLATE_ANIMATION_THRESHOLD_PX + 1);
tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState)); tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState));
assertEquals(tabElStyle.maxWidth, `${tabWidth}px`); assertEquals(tabElStyle.maxWidth, `${tabWidth}px`);
let top = tabElement.getBoundingClientRect().top; assertEquals(startTop, tabElement.getBoundingClientRect().top);
assertTrue(top < startTop && top > -1 * SWIPE_FINISH_THRESHOLD_PX);
// Swipe was enough to start animating max width and opacity. // Swipe was enough to close but did not yet animate.
pointerState.clientY = startY - (SWIPE_START_THRESHOLD_PX + 1); pointerState.clientY = startY - (SWIPE_START_THRESHOLD_PX + 1);
tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState)); tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState));
assertTrue( assertEquals(tabWidth, parseInt(tabElStyle.maxWidth, 10));
parseInt(tabElStyle.maxWidth) > 0 && assertEquals('1', tabElStyle.opacity);
parseInt(tabElStyle.maxWidth) < tabWidth);
assertTrue( // Verify animation still not progressed.
parseFloat(tabElStyle.opacity) > 0 &&
parseFloat(tabElStyle.opacity) < 1);
// Swipe was enough to finish animating.
pointerState.clientY = startY - (SWIPE_FINISH_THRESHOLD_PX + 1); pointerState.clientY = startY - (SWIPE_FINISH_THRESHOLD_PX + 1);
tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState)); tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState));
assertEquals(tabElStyle.maxWidth, '0px'); assertEquals(tabWidth, parseInt(tabElStyle.maxWidth, 10));
assertEquals(tabElStyle.opacity, '0'); assertEquals('1', tabElStyle.opacity);
assertEquals( assertEquals(startTop, tabElement.getBoundingClientRect().top);
tabElement.getBoundingClientRect().top, -SWIPE_FINISH_THRESHOLD_PX);
}); });
test('finishing the swipe animation fires an event', async () => { test('finishing the swipe animation fires an event', async () => {
...@@ -86,24 +80,6 @@ suite('TabSwiper', () => { ...@@ -86,24 +80,6 @@ suite('TabSwiper', () => {
await firedEventPromise; await firedEventPromise;
}); });
test('swiping enough and releasing finishes the animation', async () => {
const firedEventPromise = eventToPromise('swipe', tabElement);
const tabElStyle = window.getComputedStyle(tabElement);
const startY = 50;
const pointerState = {clientY: 50, pointerId: 1};
tabElement.dispatchEvent(new PointerEvent('pointerdown', pointerState));
pointerState.clientY = startY - (SWIPE_START_THRESHOLD_PX + 1);
pointerState.movementY = 1; /* Any non-0 value here is fine. */
tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState));
tabElement.dispatchEvent(new PointerEvent('pointerup', pointerState));
await firedEventPromise;
assertEquals(tabElStyle.maxWidth, '0px');
assertEquals(tabElStyle.opacity, '0');
});
test('swiping and letting go before resets animation', () => { test('swiping and letting go before resets animation', () => {
tabElement.style.setProperty('--tabstrip-tab-width', '100px'); tabElement.style.setProperty('--tabstrip-tab-width', '100px');
const tabElStyle = window.getComputedStyle(tabElement); const tabElStyle = window.getComputedStyle(tabElement);
...@@ -121,7 +97,7 @@ suite('TabSwiper', () => { ...@@ -121,7 +97,7 @@ suite('TabSwiper', () => {
assertEquals(tabElStyle.opacity, '1'); assertEquals(tabElStyle.opacity, '1');
}); });
test('swiping fast enough finishes playing the animation', async () => { test('swiping fast enough fires an event', async () => {
const tabElStyle = window.getComputedStyle(tabElement); const tabElStyle = window.getComputedStyle(tabElement);
const firedEventPromise = eventToPromise('swipe', tabElement); const firedEventPromise = eventToPromise('swipe', tabElement);
const startY = 50; const startY = 50;
...@@ -136,8 +112,6 @@ suite('TabSwiper', () => { ...@@ -136,8 +112,6 @@ suite('TabSwiper', () => {
tabElement.dispatchEvent(new PointerEvent('pointerup', pointerState)); tabElement.dispatchEvent(new PointerEvent('pointerup', pointerState));
await firedEventPromise; await firedEventPromise;
assertEquals(tabElStyle.maxWidth, '0px');
assertEquals(tabElStyle.opacity, '0');
}); });
test('pointerdown should reset the animation time', async () => { test('pointerdown should reset the animation time', async () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment