mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Simplify preview refreshing with custom hook (#11293)
This commit is contained in:
parent
db8c820677
commit
3ed89ec042
@ -7,12 +7,12 @@ import { REVIEW_PADDING, ReviewSegment } from "@/types/review";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { RecordingStartingPoint } from "@/types/record";
|
import { RecordingStartingPoint } from "@/types/record";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { Preview } from "@/types/preview";
|
|
||||||
import {
|
import {
|
||||||
InProgressPreview,
|
InProgressPreview,
|
||||||
VideoPreview,
|
VideoPreview,
|
||||||
} from "../player/PreviewThumbnailPlayer";
|
} from "../player/PreviewThumbnailPlayer";
|
||||||
import { isCurrentHour } from "@/utils/dateUtil";
|
import { isCurrentHour } from "@/utils/dateUtil";
|
||||||
|
import { useCameraPreviews } from "@/hooks/use-camera-previews";
|
||||||
|
|
||||||
type AnimatedEventCardProps = {
|
type AnimatedEventCardProps = {
|
||||||
event: ReviewSegment;
|
event: ReviewSegment;
|
||||||
@ -24,10 +24,15 @@ export function AnimatedEventCard({ event }: AnimatedEventCardProps) {
|
|||||||
|
|
||||||
// preview
|
// preview
|
||||||
|
|
||||||
const { data: previews } = useSWR<Preview[]>(
|
const previews = useCameraPreviews(
|
||||||
currentHour
|
{
|
||||||
? null
|
after: Math.round(event.start_time),
|
||||||
: `/preview/${event.camera}/start/${Math.round(event.start_time)}/end/${Math.round(event.end_time || event.start_time + 20)}`,
|
before: Math.round(event.end_time || event.start_time + 20),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
camera: event.camera,
|
||||||
|
fetchPreviews: !currentHour,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// interaction
|
// interaction
|
||||||
|
57
web/src/hooks/use-camera-previews.ts
Normal file
57
web/src/hooks/use-camera-previews.ts
Normal file
@ -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;
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||||
import useApiFilter from "@/hooks/use-api-filter";
|
import useApiFilter from "@/hooks/use-api-filter";
|
||||||
|
import { useCameraPreviews } from "@/hooks/use-camera-previews";
|
||||||
import { useTimezone } from "@/hooks/use-date-utils";
|
import { useTimezone } from "@/hooks/use-date-utils";
|
||||||
import { useOverlayState, useSearchEffect } from "@/hooks/use-overlay-state";
|
import { useOverlayState, useSearchEffect } from "@/hooks/use-overlay-state";
|
||||||
import { FrigateConfig } from "@/types/frigateConfig";
|
import { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { Preview } from "@/types/preview";
|
|
||||||
import { RecordingStartingPoint } from "@/types/record";
|
import { RecordingStartingPoint } from "@/types/record";
|
||||||
import {
|
import {
|
||||||
ReviewFilter,
|
ReviewFilter,
|
||||||
@ -161,7 +161,6 @@ export default function Events() {
|
|||||||
}, [updateSummary]);
|
}, [updateSummary]);
|
||||||
|
|
||||||
// preview videos
|
// preview videos
|
||||||
const [previewKey, setPreviewKey] = useState(0);
|
|
||||||
const previewTimes = useMemo(() => {
|
const previewTimes = useMemo(() => {
|
||||||
if (!reviews || reviews.length == 0) {
|
if (!reviews || reviews.length == 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -170,50 +169,22 @@ export default function Events() {
|
|||||||
const startDate = new Date();
|
const startDate = new Date();
|
||||||
startDate.setMinutes(0, 0, 0);
|
startDate.setMinutes(0, 0, 0);
|
||||||
|
|
||||||
let endDate;
|
const endDate = new Date(reviews.at(-1)?.end_time || 0);
|
||||||
if (previewKey == 0) {
|
|
||||||
endDate = new Date(reviews.at(-1)?.end_time || 0);
|
|
||||||
endDate.setHours(0, 0, 0, 0);
|
endDate.setHours(0, 0, 0, 0);
|
||||||
} else {
|
|
||||||
endDate = new Date();
|
|
||||||
endDate.setMilliseconds(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
start: startDate.getTime() / 1000,
|
after: startDate.getTime() / 1000,
|
||||||
end: endDate.getTime() / 1000,
|
before: endDate.getTime() / 1000,
|
||||||
};
|
};
|
||||||
}, [reviews, previewKey]);
|
}, [reviews]);
|
||||||
const { data: allPreviews } = useSWR<Preview[]>(
|
|
||||||
previewTimes
|
const allPreviews = useCameraPreviews(
|
||||||
? `preview/all/start/${previewTimes.start}/end/${previewTimes.end}`
|
previewTimes ?? { after: 0, before: 0 },
|
||||||
: null,
|
{
|
||||||
{ revalidateOnFocus: false, revalidateOnReconnect: false },
|
fetchPreviews: previewTimes != undefined,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
document.addEventListener("focusin", callback);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("focusin", callback);
|
|
||||||
};
|
|
||||||
}, [allPreviews]);
|
|
||||||
|
|
||||||
// review status
|
// review status
|
||||||
|
|
||||||
const markAllItemsAsReviewed = useCallback(
|
const markAllItemsAsReviewed = useCallback(
|
||||||
|
Loading…
Reference in New Issue
Block a user