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"]); + }); });