From 92a59e2480b35c3574be386fbbc87f8e05c1fe9c Mon Sep 17 00:00:00 2001 From: Joffrey JAFFEUX Date: Tue, 7 May 2024 17:43:37 +0200 Subject: [PATCH] DEV: uses swipe-events lib for swipe modifier (#26905) This commit also: uses the swipe modifier in the glimmer-site-header component changes closing condition for d-modal and toast from distance to velocity cancels toast auto close on touch --- .../discourse/app/components/d-modal.gjs | 44 +++-- .../app/components/glimmer-site-header.gjs | 61 +++---- .../discourse/app/components/site-header.js | 15 +- .../discourse/app/lib/swipe-events.js | 114 +++++++------ .../discourse/app/modifiers/swipe.js | 161 ++++++++---------- .../components/float-kit/d-toast-test.gjs | 1 + .../discourse/tests/modifiers/swipe-test.gjs | 93 ++++++---- .../addon/components/d-default-toast.gjs | 111 ++++++------ .../float-kit/addon/components/d-toast.gjs | 41 ++--- .../addon/modifiers/auto-close-toast.js | 4 + 10 files changed, 315 insertions(+), 330 deletions(-) diff --git a/app/assets/javascripts/discourse/app/components/d-modal.gjs b/app/assets/javascripts/discourse/app/components/d-modal.gjs index 018cd6c6629..ee149958af9 100644 --- a/app/assets/javascripts/discourse/app/components/d-modal.gjs +++ b/app/assets/javascripts/discourse/app/components/d-modal.gjs @@ -16,6 +16,7 @@ import { disableBodyScroll, enableBodyScroll, } from "discourse/lib/body-scroll-lock"; +import { getMaxAnimationTimeMs } from "discourse/lib/swipe-events"; import swipe from "discourse/modifiers/swipe"; import trapTab from "discourse/modifiers/trap-tab"; import { bind } from "discourse-common/utils/decorators"; @@ -28,8 +29,7 @@ export const CLOSE_INITIATED_BY_SWIPE_DOWN = "initiatedBySwipeDown"; const FLASH_TYPES = ["success", "error", "warning", "info"]; -const ANIMATE_MODAL_DURATION = 250; -const MIN_SWIPE_THRESHOLD = -5; +const SWIPE_VELOCITY_THRESHOLD = 0.7; export default class DModal extends Component { @service modal; @@ -69,7 +69,7 @@ export default class DModal extends Component { await element.animate( [{ transform: "translateY(100%)" }, { transform: "translateY(0)" }], { - duration: ANIMATE_MODAL_DURATION, + duration: getMaxAnimationTimeMs(), easing: "ease", fill: "forwards", } @@ -121,39 +121,36 @@ export default class DModal extends Component { } @action - async handleSwipe(state) { - if (!this.site.mobileView) { - return; - } - + async handleSwipe(swipeEvent) { if (this.animating) { return; } - if (state.deltaY < 0) { - await this.#animateWrapperPosition(Math.abs(state.deltaY)); - return; + if (swipeEvent.deltaY >= 0) { + return await this.#animateWrapperPosition(swipeEvent.deltaY); } } @action - handleSwipeEnded(state) { - if (!this.site.mobileView) { - return; - } - + async handleSwipeEnded(swipeEvent) { if (this.animating) { // if the modal is animating we don't want to risk resetting the position // as the user releases the swipe at the same time return; } - if (state.deltaY < MIN_SWIPE_THRESHOLD) { + if (swipeEvent.goingUp()) { + return await this.#animateWrapperPosition(0); + } + + if (swipeEvent.velocityY >= SWIPE_VELOCITY_THRESHOLD) { this.wrapperElement.querySelector( ".d-modal__container" - ).style.transform = `translateY(${Math.abs(state.deltaY)}px)`; + ).style.transform = `translateY(${swipeEvent.deltaY}px)`; this.closeModal(CLOSE_INITIATED_BY_SWIPE_DOWN); + } else { + return await this.#animateWrapperPosition(0); } } @@ -188,7 +185,7 @@ export default class DModal extends Component { { visibility: "visible", offset: 0.01 }, { transform: "translateY(100%)", offset: 1 }, ], - { duration: ANIMATE_MODAL_DURATION, fill: "forwards" } + { duration: getMaxAnimationTimeMs(), fill: "forwards" } ).finished; this.animating = false; } @@ -273,6 +270,7 @@ export default class DModal extends Component { [{ transform: `translateY(${position}px)` }], { fill: "forwards", + duration: getMaxAnimationTimeMs(), } ).finished; } @@ -319,8 +317,8 @@ export default class DModal extends Component {
@@ -417,8 +415,8 @@ export default class DModal extends Component {
0) { - durationMs = this._swipeEvents.getMaxAnimationTimeMs( + durationMs = getMaxAnimationTimeMs( this.pxClosed / Math.abs(event.velocityX) ); } @@ -294,10 +288,10 @@ export default class GlimmerSiteHeader extends Component { _animateClosing(event, panel, menuOrigin) { this._animate = true; const cloakElement = document.querySelector(".header-cloak"); - let durationMs = this._swipeEvents.getMaxAnimationTimeMs(); + let durationMs = getMaxAnimationTimeMs(); if (event && this.pxClosed > 0) { const distancePx = PANEL_WIDTH - this.pxClosed; - durationMs = this._swipeEvents.getMaxAnimationTimeMs( + durationMs = getMaxAnimationTimeMs( distancePx / Math.abs(event.velocityX) ); } @@ -328,9 +322,8 @@ export default class GlimmerSiteHeader extends Component { } @bind - onSwipeStart(event) { - const e = event.detail; - const center = e.center; + onSwipeStart(swipeEvent) { + const center = swipeEvent.center; const swipeOverValidElement = document .elementsFromPoint(center.x, center.y) .some( @@ -340,7 +333,7 @@ export default class GlimmerSiteHeader extends Component { ); if ( swipeOverValidElement && - (e.direction === "left" || e.direction === "right") + (swipeEvent.direction === "left" || swipeEvent.direction === "right") ) { scrollLock(true, document.querySelector(".panel-body")); } else { @@ -349,16 +342,15 @@ export default class GlimmerSiteHeader extends Component { } @bind - onSwipeEnd(event) { - const e = event.detail; + onSwipeEnd(swipeEvent) { const menuPanels = document.querySelectorAll(".menu-panel"); scrollLock(false, document.querySelector(".panel-body")); menuPanels.forEach((panel) => { - if (this._swipeEvents.shouldCloseMenu(e, this._swipeMenuOrigin)) { - this._animateClosing(e, panel, this._swipeMenuOrigin); + if (shouldCloseMenu(swipeEvent, this._swipeMenuOrigin)) { + this._animateClosing(swipeEvent, panel, this._swipeMenuOrigin); scrollLock(false); } else { - this._animateOpening(panel, e); + this._animateOpening(panel, swipeEvent); } }); } @@ -373,17 +365,15 @@ export default class GlimmerSiteHeader extends Component { } @bind - onSwipe(event) { - const e = event.detail; - + onSwipe(swipeEvent) { const movingElement = document.querySelector(".menu-panel"); const cloakElement = document.querySelector(".header-cloak"); //origin left - this.pxClosed = Math.max(0, -e.deltaX); + this.pxClosed = Math.max(0, -swipeEvent.deltaX); let translation = -this.pxClosed; if (this._swipeMenuOrigin === "right") { - this.pxClosed = Math.max(0, e.deltaX); + this.pxClosed = Math.max(0, swipeEvent.deltaX); translation = this.pxClosed; } @@ -421,13 +411,6 @@ export default class GlimmerSiteHeader extends Component { window.removeEventListener("scroll", this._onScroll); this._resizeObserver?.disconnect(); - if (this.site.mobileView) { - this._headerWrap.removeEventListener("swipestart", this.onSwipeStart); - this._headerWrap.removeEventListener("swipeend", this.onSwipeEnd); - this._headerWrap.removeEventListener("swipecancel", this.onSwipeCancel); - this._headerWrap.removeEventListener("swipe", this.onSwipe); - this._swipeEvents.removeTouchListeners(); - } }