mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-07 05:54:10 +03:00
turn annotation settings into a popover
This commit is contained in:
parent
02c5b9a4f5
commit
78e278d5e8
@ -140,7 +140,7 @@ export function AnnotationSettingsPane({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mb-3 space-y-3 rounded-lg border border-secondary-foreground bg-background_alt p-2">
|
||||
<div className="space-y-3 p-4">
|
||||
<Heading as="h4" className="my-2">
|
||||
{t("trackingDetails.annotationSettings.title")}
|
||||
</Heading>
|
||||
|
||||
@ -32,6 +32,7 @@ import {
|
||||
FaChevronRight,
|
||||
} from "react-icons/fa";
|
||||
import { TrackingDetails } from "./TrackingDetails";
|
||||
import { AnnotationSettingsPane } from "./AnnotationSettingsPane";
|
||||
import { LuSettings } from "react-icons/lu";
|
||||
import { DetailStreamProvider } from "@/context/detail-stream-context";
|
||||
import {
|
||||
@ -74,6 +75,7 @@ import { useIsAdmin } from "@/hooks/use-is-admin";
|
||||
import { getTranslatedLabel } from "@/utils/i18n";
|
||||
import { CameraNameLabel } from "@/components/camera/CameraNameLabel";
|
||||
import { DialogPortal } from "@radix-ui/react-dialog";
|
||||
import { useDetailStream } from "@/context/detail-stream-context";
|
||||
|
||||
const SEARCH_TABS = ["snapshot", "tracking_details"] as const;
|
||||
export type SearchTab = (typeof SEARCH_TABS)[number];
|
||||
@ -147,17 +149,46 @@ function TabsWithActions({
|
||||
setSearch={setSearch}
|
||||
setSimilarity={setSimilarity}
|
||||
/>
|
||||
{pageToggle === "tracking_details" && (
|
||||
<AnnotationSettingsPopover
|
||||
search={search}
|
||||
showControls={showControls}
|
||||
setShowControls={setShowControls}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
type AnnotationSettingsPopoverProps = {
|
||||
search: SearchResult;
|
||||
showControls?: boolean;
|
||||
setShowControls?: (v: boolean) => void;
|
||||
};
|
||||
|
||||
function AnnotationSettingsPopover({
|
||||
search,
|
||||
showControls,
|
||||
setShowControls,
|
||||
}: AnnotationSettingsPopoverProps) {
|
||||
const { t } = useTranslation(["views/explore"]);
|
||||
const { annotationOffset, setAnnotationOffset } = useDetailStream();
|
||||
const [showZones, setShowZones] = useState(true);
|
||||
|
||||
return (
|
||||
<div className="ml-2">
|
||||
<Popover modal={true} open={showControls} onOpenChange={setShowControls}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant={showControls ? "select" : "default"}
|
||||
className="size-7 p-1.5"
|
||||
aria-label={t("trackingDetails.adjustAnnotationSettings")}
|
||||
onClick={() => setShowControls?.(!showControls)}
|
||||
>
|
||||
<LuSettings className="size-5" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
</TooltipTrigger>
|
||||
<TooltipPortal>
|
||||
<TooltipContent>
|
||||
@ -165,7 +196,23 @@ function TabsWithActions({
|
||||
</TooltipContent>
|
||||
</TooltipPortal>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<PopoverContent className="w-[90vw] max-w-2xl p-0" align="end">
|
||||
<AnnotationSettingsPane
|
||||
event={search as unknown as Event}
|
||||
showZones={showZones}
|
||||
setShowZones={setShowZones}
|
||||
annotationOffset={annotationOffset}
|
||||
setAnnotationOffset={(value) => {
|
||||
if (typeof value === "function") {
|
||||
const newValue = value(annotationOffset);
|
||||
setAnnotationOffset(newValue);
|
||||
} else {
|
||||
setAnnotationOffset(value);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -221,8 +268,6 @@ function DialogContentComponent({
|
||||
/>
|
||||
) : undefined
|
||||
}
|
||||
showControls={showControls}
|
||||
setShowControls={setShowControls}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -8,8 +8,6 @@ import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
|
||||
import { getIconForLabel } from "@/utils/iconUtil";
|
||||
import { LuCircle, LuFolderX } from "react-icons/lu";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { AnnotationSettingsPane } from "./AnnotationSettingsPane";
|
||||
|
||||
import HlsVideoPlayer from "@/components/player/HlsVideoPlayer";
|
||||
import { baseUrl } from "@/api/baseUrl";
|
||||
import { REVIEW_PADDING } from "@/types/review";
|
||||
@ -40,15 +38,12 @@ type TrackingDetailsProps = {
|
||||
event: Event;
|
||||
fullscreen?: boolean;
|
||||
tabs?: React.ReactNode;
|
||||
showControls?: boolean;
|
||||
setShowControls?: (v: boolean) => void;
|
||||
};
|
||||
|
||||
export function TrackingDetails({
|
||||
className,
|
||||
event,
|
||||
tabs,
|
||||
showControls = false,
|
||||
}: TrackingDetailsProps) {
|
||||
const videoRef = useRef<HTMLVideoElement | null>(null);
|
||||
const { t } = useTranslation(["views/explore"]);
|
||||
@ -58,8 +53,7 @@ export function TrackingDetails({
|
||||
const [displaySource, _setDisplaySource] = useState<"video" | "image">(
|
||||
"video",
|
||||
);
|
||||
const { setSelectedObjectIds, annotationOffset, setAnnotationOffset } =
|
||||
useDetailStream();
|
||||
const { setSelectedObjectIds, annotationOffset } = useDetailStream();
|
||||
|
||||
// manualOverride holds a record-stream timestamp explicitly chosen by the
|
||||
// user (eg, clicking a lifecycle row). When null we display `currentTime`.
|
||||
@ -90,7 +84,6 @@ export function TrackingDetails({
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [_selectedZone, setSelectedZone] = useState("");
|
||||
const [_lifecycleZones, setLifecycleZones] = useState<string[]>([]);
|
||||
const [showZones, setShowZones] = useState(true);
|
||||
const [seekToTimestamp, setSeekToTimestamp] = useState<number | null>(null);
|
||||
|
||||
const aspectRatio = useMemo(() => {
|
||||
@ -464,22 +457,6 @@ export function TrackingDetails({
|
||||
{t("trackingDetails.autoTrackingTips")}
|
||||
</div>
|
||||
)}
|
||||
{showControls && (
|
||||
<AnnotationSettingsPane
|
||||
event={event}
|
||||
showZones={showZones}
|
||||
setShowZones={setShowZones}
|
||||
annotationOffset={annotationOffset}
|
||||
setAnnotationOffset={(value) => {
|
||||
if (typeof value === "function") {
|
||||
const newValue = value(annotationOffset);
|
||||
setAnnotationOffset(newValue);
|
||||
} else {
|
||||
setAnnotationOffset(value);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="mt-4">
|
||||
<div
|
||||
|
||||
Loading…
Reference in New Issue
Block a user