mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-12 10:07:36 +03:00
rename activity to detail
This commit is contained in:
parent
64aa709888
commit
ec5234f0ae
@ -2,7 +2,7 @@ import { useMemo, useCallback } from "react";
|
||||
import { ObjectLifecycleSequence, LifecycleClassType } from "@/types/timeline";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import useSWR from "swr";
|
||||
import { useActivityStream } from "@/contexts/ActivityStreamContext";
|
||||
import { useDetailStream } from "@/context/detail-stream-context";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
@ -35,7 +35,7 @@ export default function ObjectTrackOverlay({
|
||||
}: ObjectTrackOverlayProps) {
|
||||
const { t } = useTranslation("views/events");
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
const { annotationOffset } = useActivityStream();
|
||||
const { annotationOffset } = useDetailStream();
|
||||
|
||||
const effectiveCurrentTime = currentTime - annotationOffset / 1000;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import { Slider } from "@/components/ui/slider";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useActivityStream } from "@/contexts/ActivityStreamContext";
|
||||
import { useDetailStream } from "@/context/detail-stream-context";
|
||||
import axios from "axios";
|
||||
import { useSWRConfig } from "swr";
|
||||
import { toast } from "sonner";
|
||||
@ -12,7 +12,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export default function AnnotationOffsetSlider({ className }: Props) {
|
||||
const { annotationOffset, setAnnotationOffset, camera } = useActivityStream();
|
||||
const { annotationOffset, setAnnotationOffset, camera } = useDetailStream();
|
||||
const { mutate } = useSWRConfig();
|
||||
const { t } = useTranslation(["views/explore"]);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
@ -20,7 +20,7 @@ import { cn } from "@/lib/utils";
|
||||
import { ASPECT_VERTICAL_LAYOUT, RecordingPlayerError } from "@/types/record";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ObjectTrackOverlay from "@/components/overlay/ObjectTrackOverlay";
|
||||
import { useActivityStream } from "@/contexts/ActivityStreamContext";
|
||||
import { useDetailStream } from "@/context/detail-stream-context";
|
||||
|
||||
// Android native hls does not seek correctly
|
||||
const USE_NATIVE_HLS = !isAndroid;
|
||||
@ -82,8 +82,8 @@ export default function HlsVideoPlayer({
|
||||
selectedObjectTimeline,
|
||||
currentTime,
|
||||
camera,
|
||||
isActivityMode,
|
||||
} = useActivityStream();
|
||||
isDetailMode,
|
||||
} = useDetailStream();
|
||||
|
||||
// playback
|
||||
|
||||
@ -313,7 +313,7 @@ export default function HlsVideoPlayer({
|
||||
height: isMobile ? "100%" : undefined,
|
||||
}}
|
||||
>
|
||||
{isActivityMode &&
|
||||
{isDetailMode &&
|
||||
selectedObjectId &&
|
||||
camera &&
|
||||
currentTime &&
|
||||
|
||||
@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react";
|
||||
import { ObjectLifecycleSequence } from "@/types/timeline";
|
||||
import { LifecycleIcon } from "@/components/overlay/detail/ObjectLifecycle";
|
||||
import { getLifecycleItemDescription } from "@/utils/lifecycleUtil";
|
||||
import { useActivityStream } from "@/contexts/ActivityStreamContext";
|
||||
import { useDetailStream } from "@/context/detail-stream-context";
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import useUserInteraction from "@/hooks/use-user-interaction";
|
||||
import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
|
||||
@ -25,20 +25,20 @@ import EventMenu from "@/components/timeline/EventMenu";
|
||||
import { FrigatePlusDialog } from "@/components/overlay/dialog/FrigatePlusDialog";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type ActivityStreamProps = {
|
||||
type DetailStreamProps = {
|
||||
reviewItems?: ReviewSegment[];
|
||||
currentTime: number;
|
||||
onSeek: (timestamp: number) => void;
|
||||
};
|
||||
|
||||
export default function ActivityStream({
|
||||
export default function DetailStream({
|
||||
reviewItems,
|
||||
currentTime,
|
||||
onSeek,
|
||||
}: ActivityStreamProps) {
|
||||
}: DetailStreamProps) {
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
const { t } = useTranslation("views/events");
|
||||
const { annotationOffset } = useActivityStream();
|
||||
const { annotationOffset } = useDetailStream();
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [activeReviewId, setActiveReviewId] = useState<string | undefined>(
|
||||
@ -330,7 +330,7 @@ function EventCollapsible({
|
||||
const { t } = useTranslation("views/events");
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
|
||||
const { selectedObjectId, setSelectedObjectId } = useActivityStream();
|
||||
const { selectedObjectId, setSelectedObjectId } = useDetailStream();
|
||||
|
||||
const formattedStart = config
|
||||
? formatUnixTimestampToDateTime(event.start_time ?? 0, {
|
||||
@ -3,7 +3,7 @@ import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import useSWR from "swr";
|
||||
import { ObjectLifecycleSequence } from "@/types/timeline";
|
||||
|
||||
interface ActivityStreamContextType {
|
||||
interface DetailStreamContextType {
|
||||
selectedObjectId: string | undefined;
|
||||
selectedObjectTimeline?: ObjectLifecycleSequence[];
|
||||
currentTime: number;
|
||||
@ -11,26 +11,26 @@ interface ActivityStreamContextType {
|
||||
annotationOffset: number; // milliseconds
|
||||
setAnnotationOffset: (ms: number) => void;
|
||||
setSelectedObjectId: (id: string | undefined) => void;
|
||||
isActivityMode: boolean;
|
||||
isDetailMode: boolean;
|
||||
}
|
||||
|
||||
const ActivityStreamContext = createContext<
|
||||
ActivityStreamContextType | undefined
|
||||
>(undefined);
|
||||
const DetailStreamContext = createContext<DetailStreamContextType | undefined>(
|
||||
undefined,
|
||||
);
|
||||
|
||||
interface ActivityStreamProviderProps {
|
||||
interface DetailStreamProviderProps {
|
||||
children: React.ReactNode;
|
||||
isActivityMode: boolean;
|
||||
isDetailMode: boolean;
|
||||
currentTime: number;
|
||||
camera: string;
|
||||
}
|
||||
|
||||
export function ActivityStreamProvider({
|
||||
export function DetailStreamProvider({
|
||||
children,
|
||||
isActivityMode,
|
||||
isDetailMode,
|
||||
currentTime,
|
||||
camera,
|
||||
}: ActivityStreamProviderProps) {
|
||||
}: DetailStreamProviderProps) {
|
||||
const [selectedObjectId, setSelectedObjectId] = useState<
|
||||
string | undefined
|
||||
>();
|
||||
@ -52,7 +52,7 @@ export function ActivityStreamProvider({
|
||||
setAnnotationOffset(cfgOffset);
|
||||
}, [config, camera]);
|
||||
|
||||
const value: ActivityStreamContextType = {
|
||||
const value: DetailStreamContextType = {
|
||||
selectedObjectId,
|
||||
selectedObjectTimeline,
|
||||
currentTime,
|
||||
@ -60,22 +60,22 @@ export function ActivityStreamProvider({
|
||||
annotationOffset,
|
||||
setAnnotationOffset,
|
||||
setSelectedObjectId,
|
||||
isActivityMode,
|
||||
isDetailMode,
|
||||
};
|
||||
|
||||
return (
|
||||
<ActivityStreamContext.Provider value={value}>
|
||||
<DetailStreamContext.Provider value={value}>
|
||||
{children}
|
||||
</ActivityStreamContext.Provider>
|
||||
</DetailStreamContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export function useActivityStream() {
|
||||
const context = useContext(ActivityStreamContext);
|
||||
export function useDetailStream() {
|
||||
const context = useContext(DetailStreamContext);
|
||||
if (context === undefined) {
|
||||
throw new Error(
|
||||
"useActivityStream must be used within an ActivityStreamProvider",
|
||||
"useDetailStream must be used within an DetailStreamProvider",
|
||||
);
|
||||
}
|
||||
return context;
|
||||
@ -29,7 +29,7 @@ export type ObjectLifecycleSequence = {
|
||||
|
||||
export type TimeRange = { before: number; after: number };
|
||||
|
||||
export type TimelineType = "timeline" | "events" | "activity";
|
||||
export type TimelineType = "timeline" | "events" | "detail";
|
||||
|
||||
export type TimelineScrubMode = "auto" | "drag" | "hover" | "compat";
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import PreviewPlayer, {
|
||||
import { DynamicVideoController } from "@/components/player/dynamic/DynamicVideoController";
|
||||
import DynamicVideoPlayer from "@/components/player/dynamic/DynamicVideoPlayer";
|
||||
import MotionReviewTimeline from "@/components/timeline/MotionReviewTimeline";
|
||||
import ActivityStream from "@/components/timeline/ActivityStream";
|
||||
import DetailStream from "@/components/timeline/DetailStream";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||
import { useOverlayState } from "@/hooks/use-overlay-state";
|
||||
@ -67,7 +67,7 @@ import {
|
||||
} from "@/components/ui/tooltip";
|
||||
import { CameraNameLabel } from "@/components/camera/CameraNameLabel";
|
||||
import { useAllowedCameras } from "@/hooks/use-allowed-cameras";
|
||||
import { ActivityStreamProvider } from "@/contexts/ActivityStreamContext";
|
||||
import { DetailStreamProvider } from "@/context/detail-stream-context";
|
||||
import { GenAISummaryDialog } from "@/components/overlay/chip/GenAISummaryChip";
|
||||
|
||||
const DATA_REFRESH_TIME = 600000; // 10 minutes
|
||||
@ -524,8 +524,8 @@ export function RecordingView({
|
||||
);
|
||||
|
||||
return (
|
||||
<ActivityStreamProvider
|
||||
isActivityMode={timelineType === "activity"}
|
||||
<DetailStreamProvider
|
||||
isDetailMode={timelineType === "detail"}
|
||||
currentTime={currentTime}
|
||||
camera={mainCamera}
|
||||
>
|
||||
@ -644,11 +644,11 @@ export function RecordingView({
|
||||
<div className="">{t("events.label")}</div>
|
||||
</ToggleGroupItem>
|
||||
<ToggleGroupItem
|
||||
className={`${timelineType == "activity" ? "" : "text-muted-foreground"}`}
|
||||
value="activity"
|
||||
aria-label="Activity Stream"
|
||||
className={`${timelineType == "detail" ? "" : "text-muted-foreground"}`}
|
||||
value="detail"
|
||||
aria-label="Detail Stream"
|
||||
>
|
||||
<div className="">Activity</div>
|
||||
<div className="">Detail</div>
|
||||
</ToggleGroupItem>
|
||||
</ToggleGroup>
|
||||
) : (
|
||||
@ -688,7 +688,7 @@ export function RecordingView({
|
||||
className={cn(
|
||||
"flex flex-1 flex-wrap",
|
||||
isDesktop
|
||||
? timelineType === "activity"
|
||||
? timelineType === "detail"
|
||||
? "w-full"
|
||||
: "w-[80%]"
|
||||
: "",
|
||||
@ -697,7 +697,7 @@ export function RecordingView({
|
||||
<div
|
||||
className={cn(
|
||||
"flex size-full items-center",
|
||||
timelineType === "activity"
|
||||
timelineType === "detail"
|
||||
? "flex-col"
|
||||
: mainCameraAspect == "tall"
|
||||
? "flex-row justify-evenly"
|
||||
@ -776,7 +776,7 @@ export function RecordingView({
|
||||
</div>
|
||||
{isDesktop &&
|
||||
effectiveCameras.length > 1 &&
|
||||
timelineType !== "activity" && (
|
||||
timelineType !== "detail" && (
|
||||
<div
|
||||
ref={previewRowRef}
|
||||
className={cn(
|
||||
@ -852,7 +852,7 @@ export function RecordingView({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</ActivityStreamProvider>
|
||||
</DetailStreamProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -967,8 +967,8 @@ function Timeline({
|
||||
className={cn(
|
||||
"relative",
|
||||
isDesktop
|
||||
? `${timelineType == "timeline" ? "w-[100px]" : timelineType == "activity" ? "w-[30%]" : "w-60"} no-scrollbar overflow-y-auto`
|
||||
: `overflow-hidden portrait:flex-grow ${timelineType == "timeline" ? "landscape:w-[100px]" : timelineType == "activity" ? "flex-1" : "landscape:w-[175px]"} `
|
||||
? `${timelineType == "timeline" ? "w-[100px]" : timelineType == "detail" ? "w-[30%]" : "w-60"} no-scrollbar overflow-y-auto`
|
||||
: `overflow-hidden portrait:flex-grow ${timelineType == "timeline" ? "landscape:w-[100px]" : timelineType == "detail" ? "flex-1" : "landscape:w-[175px]"} `
|
||||
} relative`}
|
||||
>
|
||||
{isMobile && (
|
||||
@ -1004,8 +1004,8 @@ function Timeline({
|
||||
) : (
|
||||
<Skeleton className="size-full" />
|
||||
)
|
||||
) : timelineType == "activity" ? (
|
||||
<ActivityStream
|
||||
) : timelineType == "detail" ? (
|
||||
<DetailStream
|
||||
currentTime={currentTime}
|
||||
onSeek={(timestamp) => manuallySetCurrentTime(timestamp, true)}
|
||||
reviewItems={mainCameraReviewItems}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user