mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Timeline tweaks (#10816)
* limit handles from overdragging when segments don't fill up timeline * use separate state for switch * add key
This commit is contained in:
parent
483d64e419
commit
427c6a6afb
@ -2,7 +2,7 @@ import { Button } from "../ui/button";
|
|||||||
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
|
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { CameraGroupConfig, FrigateConfig } from "@/types/frigateConfig";
|
import { CameraGroupConfig, FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { useCallback, useMemo, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@ -631,16 +631,21 @@ function ShowMotionOnlyButton({
|
|||||||
motionOnly,
|
motionOnly,
|
||||||
setMotionOnly,
|
setMotionOnly,
|
||||||
}: ShowMotionOnlyButtonProps) {
|
}: ShowMotionOnlyButtonProps) {
|
||||||
|
const [motionOnlyButton, setMotionOnlyButton] = useState(motionOnly);
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => setMotionOnly(motionOnlyButton),
|
||||||
|
[motionOnlyButton, setMotionOnly],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="hidden md:inline-flex items-center justify-center whitespace-nowrap text-sm bg-secondary hover:bg-secondary/80 text-secondary-foreground h-9 rounded-md px-3 mx-1 cursor-pointer">
|
<div className="hidden md:inline-flex items-center justify-center whitespace-nowrap text-sm bg-secondary hover:bg-secondary/80 text-secondary-foreground h-9 rounded-md px-3 mx-1 cursor-pointer">
|
||||||
<Switch
|
<Switch
|
||||||
className="ml-1"
|
className="ml-1"
|
||||||
id="collapse-motion"
|
id="collapse-motion"
|
||||||
checked={motionOnly}
|
checked={motionOnlyButton}
|
||||||
onCheckedChange={() => {
|
onCheckedChange={setMotionOnlyButton}
|
||||||
setMotionOnly(!motionOnly);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Label
|
<Label
|
||||||
className="mx-2 text-secondary-foreground cursor-pointer"
|
className="mx-2 text-secondary-foreground cursor-pointer"
|
||||||
|
@ -58,6 +58,7 @@ export function ReviewTimeline({
|
|||||||
const [isDraggingExportEnd, setIsDraggingExportEnd] = useState(false);
|
const [isDraggingExportEnd, setIsDraggingExportEnd] = useState(false);
|
||||||
const [exportStartPosition, setExportStartPosition] = useState(0);
|
const [exportStartPosition, setExportStartPosition] = useState(0);
|
||||||
const [exportEndPosition, setExportEndPosition] = useState(0);
|
const [exportEndPosition, setExportEndPosition] = useState(0);
|
||||||
|
const segmentsRef = useRef<HTMLDivElement>(null);
|
||||||
const handlebarRef = useRef<HTMLDivElement>(null);
|
const handlebarRef = useRef<HTMLDivElement>(null);
|
||||||
const handlebarTimeRef = useRef<HTMLDivElement>(null);
|
const handlebarTimeRef = useRef<HTMLDivElement>(null);
|
||||||
const exportStartRef = useRef<HTMLDivElement>(null);
|
const exportStartRef = useRef<HTMLDivElement>(null);
|
||||||
@ -100,6 +101,7 @@ export function ReviewTimeline({
|
|||||||
} = useDraggableElement({
|
} = useDraggableElement({
|
||||||
contentRef,
|
contentRef,
|
||||||
timelineRef,
|
timelineRef,
|
||||||
|
segmentsRef,
|
||||||
draggableElementRef: handlebarRef,
|
draggableElementRef: handlebarRef,
|
||||||
segmentDuration,
|
segmentDuration,
|
||||||
showDraggableElement: showHandlebar,
|
showDraggableElement: showHandlebar,
|
||||||
@ -123,6 +125,7 @@ export function ReviewTimeline({
|
|||||||
} = useDraggableElement({
|
} = useDraggableElement({
|
||||||
contentRef,
|
contentRef,
|
||||||
timelineRef,
|
timelineRef,
|
||||||
|
segmentsRef,
|
||||||
draggableElementRef: exportStartRef,
|
draggableElementRef: exportStartRef,
|
||||||
segmentDuration,
|
segmentDuration,
|
||||||
showDraggableElement: showExportHandles,
|
showDraggableElement: showExportHandles,
|
||||||
@ -147,6 +150,7 @@ export function ReviewTimeline({
|
|||||||
} = useDraggableElement({
|
} = useDraggableElement({
|
||||||
contentRef,
|
contentRef,
|
||||||
timelineRef,
|
timelineRef,
|
||||||
|
segmentsRef,
|
||||||
draggableElementRef: exportEndRef,
|
draggableElementRef: exportEndRef,
|
||||||
segmentDuration,
|
segmentDuration,
|
||||||
showDraggableElement: showExportHandles,
|
showDraggableElement: showExportHandles,
|
||||||
@ -319,7 +323,7 @@ export function ReviewTimeline({
|
|||||||
: "cursor-auto"
|
: "cursor-auto"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col relative">
|
<div ref={segmentsRef} className="flex flex-col relative">
|
||||||
<div className="absolute top-0 inset-x-0 z-20 w-full h-[30px] bg-gradient-to-b from-secondary to-transparent pointer-events-none"></div>
|
<div className="absolute top-0 inset-x-0 z-20 w-full h-[30px] bg-gradient-to-b from-secondary to-transparent pointer-events-none"></div>
|
||||||
<div className="absolute bottom-0 inset-x-0 z-20 w-full h-[30px] bg-gradient-to-t from-secondary to-transparent pointer-events-none"></div>
|
<div className="absolute bottom-0 inset-x-0 z-20 w-full h-[30px] bg-gradient-to-t from-secondary to-transparent pointer-events-none"></div>
|
||||||
{children}
|
{children}
|
||||||
|
@ -6,6 +6,7 @@ import { useTimelineUtils } from "./use-timeline-utils";
|
|||||||
type DraggableElementProps = {
|
type DraggableElementProps = {
|
||||||
contentRef: React.RefObject<HTMLElement>;
|
contentRef: React.RefObject<HTMLElement>;
|
||||||
timelineRef: React.RefObject<HTMLDivElement>;
|
timelineRef: React.RefObject<HTMLDivElement>;
|
||||||
|
segmentsRef: React.RefObject<HTMLDivElement>;
|
||||||
draggableElementRef: React.RefObject<HTMLDivElement>;
|
draggableElementRef: React.RefObject<HTMLDivElement>;
|
||||||
segmentDuration: number;
|
segmentDuration: number;
|
||||||
showDraggableElement: boolean;
|
showDraggableElement: boolean;
|
||||||
@ -29,6 +30,7 @@ type DraggableElementProps = {
|
|||||||
function useDraggableElement({
|
function useDraggableElement({
|
||||||
contentRef,
|
contentRef,
|
||||||
timelineRef,
|
timelineRef,
|
||||||
|
segmentsRef,
|
||||||
draggableElementRef,
|
draggableElementRef,
|
||||||
segmentDuration,
|
segmentDuration,
|
||||||
showDraggableElement,
|
showDraggableElement,
|
||||||
@ -430,12 +432,18 @@ function useDraggableElement({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
timelineRef.current &&
|
timelineRef.current &&
|
||||||
|
segmentsRef.current &&
|
||||||
draggableElementTime &&
|
draggableElementTime &&
|
||||||
timelineCollapsed &&
|
timelineCollapsed &&
|
||||||
timelineSegments &&
|
timelineSegments &&
|
||||||
segments
|
segments
|
||||||
) {
|
) {
|
||||||
setFullTimelineHeight(timelineRef.current.scrollHeight);
|
setFullTimelineHeight(
|
||||||
|
Math.min(
|
||||||
|
timelineRef.current.scrollHeight,
|
||||||
|
segmentsRef.current.scrollHeight,
|
||||||
|
),
|
||||||
|
);
|
||||||
const alignedSegmentTime = alignStartDateToTimeline(draggableElementTime);
|
const alignedSegmentTime = alignStartDateToTimeline(draggableElementTime);
|
||||||
|
|
||||||
let segmentElement = timelineRef.current.querySelector(
|
let segmentElement = timelineRef.current.querySelector(
|
||||||
@ -486,11 +494,16 @@ function useDraggableElement({
|
|||||||
}, [timelineCollapsed, segments]);
|
}, [timelineCollapsed, segments]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (timelineRef.current && segments) {
|
if (timelineRef.current && segments && segmentsRef.current) {
|
||||||
setScrollEdgeSize(timelineRef.current.clientHeight * 0.03);
|
setScrollEdgeSize(timelineRef.current.clientHeight * 0.03);
|
||||||
setFullTimelineHeight(timelineRef.current.scrollHeight);
|
setFullTimelineHeight(
|
||||||
|
Math.min(
|
||||||
|
timelineRef.current.scrollHeight,
|
||||||
|
segmentsRef.current.scrollHeight,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}, [timelineRef, segments]);
|
}, [timelineRef, segmentsRef, segments]);
|
||||||
|
|
||||||
return { handleMouseDown, handleMouseUp, handleMouseMove };
|
return { handleMouseDown, handleMouseUp, handleMouseMove };
|
||||||
}
|
}
|
||||||
|
@ -830,7 +830,7 @@ function MotionReview({
|
|||||||
}
|
}
|
||||||
const detectionType = getDetectionType(camera.name);
|
const detectionType = getDetectionType(camera.name);
|
||||||
return (
|
return (
|
||||||
<div className={`relative ${spans}`}>
|
<div key={camera.name} className={`relative ${spans}`}>
|
||||||
<PreviewPlayer
|
<PreviewPlayer
|
||||||
key={camera.name}
|
key={camera.name}
|
||||||
className={`rounded-2xl ${spans} ${grow}`}
|
className={`rounded-2xl ${spans} ${grow}`}
|
||||||
|
Loading…
Reference in New Issue
Block a user