diff --git a/packages/client/src/components/AppContainer.js b/packages/client/src/components/AppContainer.js index a7c4d7015..ae2a84080 100644 --- a/packages/client/src/components/AppContainer.js +++ b/packages/client/src/components/AppContainer.js @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { MdMenu } from 'react-icons/md'; import { useCurrentIndex } from '../hooks/useCurrentIndex'; import { useMode } from '../hooks/useMode'; @@ -6,6 +6,7 @@ import { useSlidesProps } from '../hooks/useSlides'; import { useContentComponent } from '../hooks/useContentComponent'; import { useSidebarComponent } from '../hooks/useSidebarComponent'; import { useCommentsListComponent } from '../hooks/useCommentsListComponent'; +import { swipeEvent } from '../utils/swipeEvent'; const slideWrapperClassName = '.swiper-container'; @@ -19,8 +20,18 @@ export const AppContainer = ({ slides: originalSlides, hash }) => { const CommentsListComponent = useCommentsListComponent(mode); const goTo = (num) => { - document.querySelector(slideWrapperClassName)?.swiper?.slideTo(num); - setCurrentIndex(num); + let nextIndex = num; + const { swiper } = document.querySelector(slideWrapperClassName); + const { realIndex } = swiper; + + if (num === '+') { + nextIndex = Math.min(realIndex + 1, slides.length); + } else if (num === '-') { + nextIndex = Math.max(realIndex - 1, 0); + } + + swiper?.slideTo(nextIndex); + setCurrentIndex(nextIndex); }; const runPresentationMode = (type) => { @@ -28,6 +39,13 @@ export const AppContainer = ({ slides: originalSlides, hash }) => { setMode(type === 'start' ? 'host' : 'common'); }; + useEffect(() => { + // for mobiles and tablets + if (window.innerWidth <= 768) { + swipeEvent(goTo); + } + }, []); + return ( <> {SidebarComponent && ( diff --git a/packages/client/src/components/ContentView/Base.js b/packages/client/src/components/ContentView/Base.js index 53ca803db..fc93ee2c0 100644 --- a/packages/client/src/components/ContentView/Base.js +++ b/packages/client/src/components/ContentView/Base.js @@ -10,12 +10,13 @@ export const Base = memo( if (import.meta.webpackHot) { useEffect(() => { + if (process.env.CHART) { + mermaid?.reload(); + } + (async () => { const { Prism } = await import('../../setup/prism'); - if (process.env.CHART) { - mermaid?.reload(); - } Prism.highlightAll(); })(); }, [hash]); diff --git a/packages/client/src/components/SlideCore.js b/packages/client/src/components/SlideCore.js index 20b8c5c54..52bba6627 100644 --- a/packages/client/src/components/SlideCore.js +++ b/packages/client/src/components/SlideCore.js @@ -45,7 +45,7 @@ export const SlideCore = ({ slides, onChangeSlideIndex }) => ( direction={process.env.UI.VERTICAL === 'true' ? 'vertical' : 'horizontal'} loop={/*TODO: respect to params to generate pdf */ process.env.LOOP} speed={350} - allowTouchMove={/* TODO: only for mobile */ false} + allowTouchMove={false} slidesPerView={1} keyboard={{ enabled: true }} hashNavigation={{ diff --git a/packages/client/src/utils/swipeEvent.js b/packages/client/src/utils/swipeEvent.js new file mode 100644 index 000000000..0f6c80708 --- /dev/null +++ b/packages/client/src/utils/swipeEvent.js @@ -0,0 +1,42 @@ +// https://stackoverflow.com/questions/2264072/detect-a-finger-swipe-through-javascript-on-the-iphone-and-android + +export function swipeEvent(goTo) { + let xDown = null; + let yDown = null; + + document.addEventListener( + 'touchstart', + (e) => { + const { clientX, clientY } = e.touches[0]; + + xDown = clientX; + yDown = clientY; + }, + false + ); + document.addEventListener( + 'touchmove', + (e) => { + if (!xDown || !yDown) { + return; + } + + const firstTouch = e.touches[0]; + let xDiff = xDown - firstTouch.clientX; + let yDiff = yDown - firstTouch.clientY; + + if (Math.abs(xDiff) > Math.abs(yDiff)) { + if (xDiff > 0) { + // right + goTo('+'); + } else { + // left + goTo('-'); + } + } + xDown = null; + yDown = null; + }, + false + ); +}