rename activity to detail

This commit is contained in:
Josh Hawkins 2025-10-16 07:16:52 -05:00
parent 64aa709888
commit ec5234f0ae
7 changed files with 48 additions and 48 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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 &&

View File

@ -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, {

View File

@ -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;

View File

@ -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";

View File

@ -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}