Improve timeline auto scrolling (#13556)

* Improve timeline auto scrolling

* touch events
This commit is contained in:
Josh Hawkins 2024-09-04 11:48:45 -05:00 committed by GitHub
parent 055f0dfc22
commit fe2fec81ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 3 deletions

View File

@ -1,4 +1,11 @@
import { ReactNode, useCallback, useEffect, useMemo, useState } from "react"; import {
ReactNode,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import scrollIntoView from "scroll-into-view-if-needed"; import scrollIntoView from "scroll-into-view-if-needed";
import { useTimelineUtils } from "./use-timeline-utils"; import { useTimelineUtils } from "./use-timeline-utils";
import { FrigateConfig } from "@/types/frigateConfig"; import { FrigateConfig } from "@/types/frigateConfig";
@ -66,6 +73,12 @@ function useDraggableElement({
timelineRef, timelineRef,
}); });
// track user interaction and adjust scrolling behavior
const [userInteracting, setUserInteracting] = useState(false);
const interactionTimeout = useRef<NodeJS.Timeout>();
const isProgrammaticScroll = useRef(false);
const draggingAtTopEdge = useMemo(() => { const draggingAtTopEdge = useMemo(() => {
if (clientYPosition && timelineRef.current && scrollEdgeSize) { if (clientYPosition && timelineRef.current && scrollEdgeSize) {
const timelineRect = timelineRef.current.getBoundingClientRect(); const timelineRect = timelineRef.current.getBoundingClientRect();
@ -179,7 +192,7 @@ function useDraggableElement({
minute: "2-digit", minute: "2-digit",
...(segmentDuration < 60 && !dense && { second: "2-digit" }), ...(segmentDuration < 60 && !dense && { second: "2-digit" }),
}); });
if (scrollTimeline) { if (scrollTimeline && !userInteracting) {
scrollIntoView(thumb, { scrollIntoView(thumb, {
block: "center", block: "center",
behavior: "smooth", behavior: "smooth",
@ -202,6 +215,7 @@ function useDraggableElement({
setDraggableElementPosition, setDraggableElementPosition,
dense, dense,
config, config,
userInteracting,
], ],
); );
@ -510,6 +524,47 @@ function useDraggableElement({
} }
}, [timelineRef, segmentsRef, segments]); }, [timelineRef, segmentsRef, segments]);
useEffect(() => {
const handleUserInteraction = () => {
if (!isProgrammaticScroll.current) {
setUserInteracting(true);
if (interactionTimeout.current) {
clearTimeout(interactionTimeout.current);
}
interactionTimeout.current = setTimeout(() => {
setUserInteracting(false);
}, 3000);
} else {
isProgrammaticScroll.current = false;
}
};
const timelineElement = timelineRef.current;
if (timelineElement) {
timelineElement.addEventListener("scroll", handleUserInteraction);
timelineElement.addEventListener("mousedown", handleUserInteraction);
timelineElement.addEventListener("mouseup", handleUserInteraction);
timelineElement.addEventListener("touchstart", handleUserInteraction);
timelineElement.addEventListener("touchmove", handleUserInteraction);
timelineElement.addEventListener("touchend", handleUserInteraction);
return () => {
timelineElement.removeEventListener("scroll", handleUserInteraction);
timelineElement.removeEventListener("mousedown", handleUserInteraction);
timelineElement.removeEventListener("mouseup", handleUserInteraction);
timelineElement.removeEventListener(
"touchstart",
handleUserInteraction,
);
timelineElement.removeEventListener("touchmove", handleUserInteraction);
timelineElement.removeEventListener("touchend", handleUserInteraction);
};
}
}, [timelineRef]);
return { handleMouseDown, handleMouseUp, handleMouseMove }; return { handleMouseDown, handleMouseUp, handleMouseMove };
} }

View File

@ -702,7 +702,6 @@ function Timeline({
setExportEndTime={setExportEndTime} setExportEndTime={setExportEndTime}
handlebarTime={currentTime} handlebarTime={currentTime}
setHandlebarTime={setCurrentTime} setHandlebarTime={setCurrentTime}
onlyInitialHandlebarScroll={true}
events={mainCameraReviewItems} events={mainCameraReviewItems}
motion_events={motionData ?? []} motion_events={motionData ?? []}
severityType="significant_motion" severityType="significant_motion"