Skip to content

Commit

Permalink
Simplify preview refreshing with custom hook (#11293)
Browse files Browse the repository at this point in the history
  • Loading branch information
NickM-27 authored May 8, 2024
1 parent db8c820 commit 3ed89ec
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 46 deletions.
15 changes: 10 additions & 5 deletions web/src/components/card/AnimatedEventCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { REVIEW_PADDING, ReviewSegment } from "@/types/review";
import { useNavigate } from "react-router-dom";
import { RecordingStartingPoint } from "@/types/record";
import axios from "axios";
import { Preview } from "@/types/preview";
import {
InProgressPreview,
VideoPreview,
} from "../player/PreviewThumbnailPlayer";
import { isCurrentHour } from "@/utils/dateUtil";
import { useCameraPreviews } from "@/hooks/use-camera-previews";

type AnimatedEventCardProps = {
event: ReviewSegment;
Expand All @@ -24,10 +24,15 @@ export function AnimatedEventCard({ event }: AnimatedEventCardProps) {

// preview

const { data: previews } = useSWR<Preview[]>(
currentHour
? null
: `/preview/${event.camera}/start/${Math.round(event.start_time)}/end/${Math.round(event.end_time || event.start_time + 20)}`,
const previews = useCameraPreviews(
{
after: Math.round(event.start_time),
before: Math.round(event.end_time || event.start_time + 20),
},
{
camera: event.camera,
fetchPreviews: !currentHour,
},
);

// interaction
Expand Down
57 changes: 57 additions & 0 deletions web/src/hooks/use-camera-previews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Preview } from "@/types/preview";
import { TimeRange } from "@/types/timeline";
import { useEffect, useState } from "react";
import useSWR from "swr";

type OptionalCameraPreviewProps = {
camera?: string;
autoRefresh?: boolean;
fetchPreviews?: boolean;
};

export function useCameraPreviews(
initialTimeRange: TimeRange,
{
camera = "all",
autoRefresh = true,
fetchPreviews = true,
}: OptionalCameraPreviewProps,
) {
const [timeRange, setTimeRange] = useState(initialTimeRange);

useEffect(() => {
setTimeRange(initialTimeRange);
}, [initialTimeRange]);

const { data: allPreviews } = useSWR<Preview[]>(
fetchPreviews
? `preview/${camera}/start/${timeRange.after}/end/${timeRange.before}`
: null,
{ revalidateOnFocus: false, revalidateOnReconnect: false },
);

// Set a timeout to update previews on the hour
useEffect(() => {
if (!autoRefresh || !fetchPreviews || !allPreviews) {
return;
}

const callback = () => {
const nextPreviewStart = new Date(
allPreviews[allPreviews.length - 1].end * 1000,
);
nextPreviewStart.setHours(nextPreviewStart.getHours() + 1);

if (Date.now() > nextPreviewStart.getTime()) {
setTimeRange({ after: timeRange.after, before: Date.now() / 1000 });
}
};
document.addEventListener("focusin", callback);

return () => {
document.removeEventListener("focusin", callback);
};
}, [allPreviews, autoRefresh, fetchPreviews, timeRange]);

return allPreviews;
}
53 changes: 12 additions & 41 deletions web/src/pages/Events.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import ActivityIndicator from "@/components/indicators/activity-indicator";
import useApiFilter from "@/hooks/use-api-filter";
import { useCameraPreviews } from "@/hooks/use-camera-previews";
import { useTimezone } from "@/hooks/use-date-utils";
import { useOverlayState, useSearchEffect } from "@/hooks/use-overlay-state";
import { FrigateConfig } from "@/types/frigateConfig";
import { Preview } from "@/types/preview";
import { RecordingStartingPoint } from "@/types/record";
import {
ReviewFilter,
Expand Down Expand Up @@ -161,7 +161,6 @@ export default function Events() {
}, [updateSummary]);

// preview videos
const [previewKey, setPreviewKey] = useState(0);
const previewTimes = useMemo(() => {
if (!reviews || reviews.length == 0) {
return undefined;
Expand All @@ -170,49 +169,21 @@ export default function Events() {
const startDate = new Date();
startDate.setMinutes(0, 0, 0);

let endDate;
if (previewKey == 0) {
endDate = new Date(reviews.at(-1)?.end_time || 0);
endDate.setHours(0, 0, 0, 0);
} else {
endDate = new Date();
endDate.setMilliseconds(0);
}
const endDate = new Date(reviews.at(-1)?.end_time || 0);
endDate.setHours(0, 0, 0, 0);

return {
start: startDate.getTime() / 1000,
end: endDate.getTime() / 1000,
};
}, [reviews, previewKey]);
const { data: allPreviews } = useSWR<Preview[]>(
previewTimes
? `preview/all/start/${previewTimes.start}/end/${previewTimes.end}`
: null,
{ revalidateOnFocus: false, revalidateOnReconnect: false },
);

// Set a timeout to update previews on the hour
useEffect(() => {
if (!allPreviews || allPreviews.length == 0) {
return;
}

const callback = () => {
const nextPreviewStart = new Date(
allPreviews[allPreviews.length - 1].end * 1000,
);
nextPreviewStart.setHours(nextPreviewStart.getHours() + 1);

if (Date.now() > nextPreviewStart.getTime()) {
setPreviewKey(10 * Math.random());
}
after: startDate.getTime() / 1000,
before: endDate.getTime() / 1000,
};
document.addEventListener("focusin", callback);
}, [reviews]);

return () => {
document.removeEventListener("focusin", callback);
};
}, [allPreviews]);
const allPreviews = useCameraPreviews(
previewTimes ?? { after: 0, before: 0 },
{
fetchPreviews: previewTimes != undefined,
},
);

// review status

Expand Down

0 comments on commit 3ed89ec

Please sign in to comment.