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 && (
diff --git a/web/src/views/events/EventView.tsx b/web/src/views/events/EventView.tsx index 87d56bc10..19efd9033 100644 --- a/web/src/views/events/EventView.tsx +++ b/web/src/views/events/EventView.tsx @@ -9,7 +9,7 @@ import { useEventUtils } from "@/hooks/use-event-utils"; import { FrigateConfig } from "@/types/frigateConfig"; import { ReviewFilter, ReviewSegment, ReviewSeverity } from "@/types/review"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { isDesktop, isMobile } from "react-device-detect"; +import { isDesktop } from "react-device-detect"; import { LuFolderCheck } from "react-icons/lu"; import { MdCircle } from "react-icons/md"; import useSWR from "swr"; @@ -283,9 +283,6 @@ export default function EventView({ relevantPreview={relevantPreview} setReviewed={markItemAsReviewed} onClick={onSelectReview} - autoPlayback={ - isMobile && minimapBounds.end == value.start_time - } />
{lastRow && !reachedEnd && }