diff --git a/web/package-lock.json b/web/package-lock.json index 13be9ab59..f6e1f95af 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -46,6 +46,7 @@ "react-hook-form": "^7.48.2", "react-icons": "^4.12.0", "react-router-dom": "^6.20.1", + "react-swipeable": "^7.0.1", "react-tracked": "^1.7.11", "react-transition-group": "^4.4.5", "react-use-websocket": "^4.5.0", @@ -6735,6 +6736,14 @@ } } }, + "node_modules/react-swipeable": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/react-swipeable/-/react-swipeable-7.0.1.tgz", + "integrity": "sha512-RKB17JdQzvECfnVj9yDZsiYn3vH0eyva/ZbrCZXZR0qp66PBRhtg4F9yJcJTWYT5Adadi+x4NoG53BxKHwIYLQ==", + "peerDependencies": { + "react": "^16.8.3 || ^17 || ^18" + } + }, "node_modules/react-tracked": { "version": "1.7.11", "resolved": "https://registry.npmjs.org/react-tracked/-/react-tracked-1.7.11.tgz", diff --git a/web/package.json b/web/package.json index 953a4b875..ec25de04f 100644 --- a/web/package.json +++ b/web/package.json @@ -51,6 +51,7 @@ "react-hook-form": "^7.48.2", "react-icons": "^4.12.0", "react-router-dom": "^6.20.1", + "react-swipeable": "^7.0.1", "react-tracked": "^1.7.11", "react-transition-group": "^4.4.5", "react-use-websocket": "^4.5.0", diff --git a/web/src/components/player/PreviewThumbnailPlayer.tsx b/web/src/components/player/PreviewThumbnailPlayer.tsx index dce5c0612..2e37901d6 100644 --- a/web/src/components/player/PreviewThumbnailPlayer.tsx +++ b/web/src/components/player/PreviewThumbnailPlayer.tsx @@ -21,6 +21,7 @@ import axios from "axios"; import { useFormattedTimestamp } from "@/hooks/use-date-utils"; import useImageLoaded from "@/hooks/use-image-loaded"; import { Skeleton } from "../ui/skeleton"; +import { useSwipeable } from "react-swipeable"; type PreviewPlayerProps = { review: ReviewSegment; @@ -41,7 +42,6 @@ type Preview = { export default function PreviewThumbnailPlayer({ review, relevantPreview, - autoPlayback = false, setReviewed, onClick, }: PreviewPlayerProps) { @@ -61,6 +61,13 @@ export default function PreviewThumbnailPlayer({ } }, [review, onClick]); + const swipeHandlers = useSwipeable({ + onSwipedLeft: () => setPlayback(false), + onSwipedRight: () => setPlayback(true), + preventScrollOnSwipe: true, + + }); + const handleSetReviewed = useCallback(() => { if (setReviewed) { setReviewed(review.id); @@ -69,27 +76,7 @@ export default function PreviewThumbnailPlayer({ // playback - const playingBack = useMemo(() => playback, [playback, autoPlayback]); - - useEffect(() => { - if (!autoPlayback) { - setPlayback(false); - - if (hoverTimeout) { - clearTimeout(hoverTimeout); - } - return; - } - - const timeout = setTimeout(() => { - setPlayback(true); - setHoverTimeout(null); - }, 500); - - return () => { - clearTimeout(timeout); - }; - }, [autoPlayback]); + const playingBack = useMemo(() => playback, [playback]); const onPlayback = useCallback( (isHovered: Boolean) => { @@ -127,6 +114,7 @@ export default function PreviewThumbnailPlayer({ onMouseEnter={isMobile ? undefined : () => onPlayback(true)} onMouseLeave={isMobile ? undefined : () => onPlayback(false)} onClick={handleOnClick} + {...swipeHandlers} > {playingBack && (