From c6f8b621968bed020ee8feb437898ca1ac6d8658 Mon Sep 17 00:00:00 2001 From: Leonardo Pavan Rocha Date: Thu, 14 Dec 2023 17:17:59 +0100 Subject: [PATCH] [IMP] web: prevent action swiper from being triggered by fullcalendar Currently in calendar views in mobile it is possible to create events selecting the time of the event by dragging. However, in calendar we also have the action swiper responsible for moving between weeks when swiping close to the borders. The issue is that when trying to create events by dragging close to the border will cause the action swiper to trigger a swipe, therefore switching to the next week. This commit fixes this by adding a swipeInvalid prop to the action swiper that will be checked during the touch move event handler. If the swipeInvalid is executed at any move and returns true, the swipe is cancelled. task-3635841 closes odoo/odoo#148541 X-original-commit: 7772b17f226ddb99060b51d6b337e5f5106b5c25 Signed-off-by: Arnaud Joset (arj) Signed-off-by: Leonardo Pavan Rocha --- .../src/core/action_swiper/action_swiper.js | 5 ++ .../src/views/calendar/calendar_renderer.js | 1 + .../tests/mobile/core/action_swiper_tests.js | 58 +++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/addons/web/static/src/core/action_swiper/action_swiper.js b/addons/web/static/src/core/action_swiper/action_swiper.js index cda3b2c6140..582127bc122 100644 --- a/addons/web/static/src/core/action_swiper/action_swiper.js +++ b/addons/web/static/src/core/action_swiper/action_swiper.js @@ -100,6 +100,10 @@ export class ActionSwiper extends Component { */ _onTouchMoveSwipe(ev) { if (this.state.isSwiping) { + if (this.props.swipeInvalid && this.props.swipeInvalid()) { + this.state.isSwiping = false; + return; + } const { onLeftSwipe, onRightSwipe } = this.localizedProps; this.swipedDistance = clamp( ev.touches[0].clientX - this.startX, @@ -209,6 +213,7 @@ ActionSwiper.props = { animationOnMove: { type: Boolean, optional: true }, animationType: { type: String, optional: true }, swipeDistanceRatio: { type: Number, optional: true }, + swipeInvalid: { type: Function, optional: true }, }; ActionSwiper.defaultProps = { diff --git a/addons/web/static/src/views/calendar/calendar_renderer.js b/addons/web/static/src/views/calendar/calendar_renderer.js index 84a931a4d73..a6f0fc5b061 100644 --- a/addons/web/static/src/views/calendar/calendar_renderer.js +++ b/addons/web/static/src/views/calendar/calendar_renderer.js @@ -24,6 +24,7 @@ export class CalendarRenderer extends Component { animationOnMove: false, animationType: "forwards", swipeDistanceRatio: 6, + swipeInvalid: () => Boolean(document.querySelector(".o_event.fc-mirror")), }; } } diff --git a/addons/web/static/tests/mobile/core/action_swiper_tests.js b/addons/web/static/tests/mobile/core/action_swiper_tests.js index 73acd724d6b..6d073d3cf9f 100644 --- a/addons/web/static/tests/mobile/core/action_swiper_tests.js +++ b/addons/web/static/tests/mobile/core/action_swiper_tests.js @@ -863,4 +863,62 @@ QUnit.module("ActionSwiper", ({ beforeEach }) => { ); } ); + + QUnit.test("swipeInvalid prop prevents swiping", async (assert) => { + assert.expect(3); + const { execRegisteredTimeouts } = mockTimeout(); + class Parent extends Component { + onRightSwipe() { + assert.step("onRightSwipe"); + } + swipeInvalid() { + assert.step("swipeInvalid"); + return true; + } + } + Parent.components = { ActionSwiper }; + Parent.template = xml` +
+ +
Test
+
+
+ `; + await mount(Parent, target, { env }); + const swiper = target.querySelector(".o_actionswiper"); + const targetContainer = target.querySelector(".o_actionswiper_target_container"); + // Touch ends once the half of the distance has been crossed + await triggerEvent(target, ".o_actionswiper", "touchstart", { + touches: [ + { + identifier: 0, + clientX: swiper.clientWidth / 2, + clientY: 0, + target: target, + }, + ], + }); + await triggerEvent(target, ".o_actionswiper", "touchmove", { + touches: [ + { + identifier: 0, + clientX: swiper.clientWidth + 1, + clientY: 0, + target: target, + }, + ], + }); + await triggerEvent(target, ".o_actionswiper", "touchend", {}); + execRegisteredTimeouts(); + await nextTick(); + assert.ok( + !targetContainer.style.transform.includes("translateX"), + "target doesn't have translateX after action is performed" + ); + assert.verifySteps(["swipeInvalid"]); + }); });