Persist show reviewed locally so it maintains state (#12560)

* Persist show reviewed locally so it maintains state

* fix

* Theming fixes
This commit is contained in:
Nicolas Mowen 2024-07-22 16:55:39 -06:00 committed by GitHub
parent 68e6ffdfef
commit 524f03a650
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 36 additions and 20 deletions

View File

@ -55,6 +55,8 @@ type ReviewFilterGroupProps = {
filter?: ReviewFilter; filter?: ReviewFilter;
motionOnly: boolean; motionOnly: boolean;
filterList?: FilterList; filterList?: FilterList;
showReviewed: boolean;
setShowReviewed: (show: boolean) => void;
onUpdateFilter: (filter: ReviewFilter) => void; onUpdateFilter: (filter: ReviewFilter) => void;
setMotionOnly: React.Dispatch<React.SetStateAction<boolean>>; setMotionOnly: React.Dispatch<React.SetStateAction<boolean>>;
}; };
@ -66,6 +68,8 @@ export default function ReviewFilterGroup({
filter, filter,
motionOnly, motionOnly,
filterList, filterList,
showReviewed,
setShowReviewed,
onUpdateFilter, onUpdateFilter,
setMotionOnly, setMotionOnly,
}: ReviewFilterGroupProps) { }: ReviewFilterGroupProps) {
@ -190,10 +194,8 @@ export default function ReviewFilterGroup({
)} )}
{filters.includes("reviewed") && ( {filters.includes("reviewed") && (
<ShowReviewFilter <ShowReviewFilter
showReviewed={filter?.showReviewed || 0} showReviewed={showReviewed}
setShowReviewed={(reviewed) => setShowReviewed={setShowReviewed}
onUpdateFilter({ ...filter, showReviewed: reviewed })
}
/> />
)} )}
{isDesktop && filters.includes("date") && ( {isDesktop && filters.includes("date") && (
@ -418,8 +420,8 @@ export function CamerasFilterButton({
} }
type ShowReviewedFilterProps = { type ShowReviewedFilterProps = {
showReviewed?: 0 | 1; showReviewed: boolean;
setShowReviewed: (reviewed?: 0 | 1) => void; setShowReviewed: (reviewed: boolean) => void;
}; };
function ShowReviewFilter({ function ShowReviewFilter({
showReviewed, showReviewed,
@ -434,9 +436,9 @@ function ShowReviewFilter({
<div className="hidden h-9 cursor-pointer items-center justify-start rounded-md bg-secondary p-2 text-sm hover:bg-secondary/80 md:flex"> <div className="hidden h-9 cursor-pointer items-center justify-start rounded-md bg-secondary p-2 text-sm hover:bg-secondary/80 md:flex">
<Switch <Switch
id="reviewed" id="reviewed"
checked={showReviewedSwitch == 1} checked={showReviewedSwitch}
onCheckedChange={() => onCheckedChange={() =>
setShowReviewedSwitch(showReviewedSwitch == 0 ? 1 : 0) setShowReviewedSwitch(showReviewedSwitch == false ? true : false)
} }
/> />
<Label className="ml-2 cursor-pointer text-primary" htmlFor="reviewed"> <Label className="ml-2 cursor-pointer text-primary" htmlFor="reviewed">
@ -446,12 +448,14 @@ function ShowReviewFilter({
<Button <Button
className="block duration-0 md:hidden" className="block duration-0 md:hidden"
variant={showReviewedSwitch == 1 ? "select" : "default"} variant={showReviewedSwitch ? "select" : "default"}
size="sm" size="sm"
onClick={() => setShowReviewedSwitch(showReviewedSwitch == 0 ? 1 : 0)} onClick={() =>
setShowReviewedSwitch(showReviewedSwitch == false ? true : false)
}
> >
<FaCheckCircle <FaCheckCircle
className={`${showReviewedSwitch == 1 ? "text-selected-foreground" : "text-secondary-foreground"}`} className={`${showReviewedSwitch ? "text-selected-foreground" : "text-secondary-foreground"}`}
/> />
</Button> </Button>
</> </>

View File

@ -328,7 +328,7 @@ function PreviewVideoPlayer({
)} )}
</video> </video>
{cameraPreviews && !currentPreview && ( {cameraPreviews && !currentPreview && (
<div className="absolute inset-0 flex items-center justify-center rounded-lg bg-background_alt text-primary md:rounded-2xl"> <div className="absolute inset-0 flex items-center justify-center rounded-lg bg-background_alt text-primary dark:bg-black md:rounded-2xl">
No Preview Found for {camera.replaceAll("_", " ")} No Preview Found for {camera.replaceAll("_", " ")}
</div> </div>
)} )}
@ -547,7 +547,7 @@ function PreviewFramesPlayer({
onLoad={onImageLoaded} onLoad={onImageLoaded}
/> />
{previewFrames?.length === 0 && ( {previewFrames?.length === 0 && (
<div className="-y-translate-1/2 align-center absolute inset-x-0 top-1/2 rounded-lg bg-background_alt text-center text-primary md:rounded-2xl"> <div className="-y-translate-1/2 align-center absolute inset-x-0 top-1/2 rounded-lg bg-background_alt text-center text-primary dark:bg-black md:rounded-2xl">
No Preview Found for {camera.replaceAll("_", " ")} No Preview Found for {camera.replaceAll("_", " ")}
</div> </div>
)} )}

View File

@ -3,6 +3,7 @@ import useApiFilter from "@/hooks/use-api-filter";
import { useCameraPreviews } from "@/hooks/use-camera-previews"; 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 { usePersistence } from "@/hooks/use-persistence";
import { FrigateConfig } from "@/types/frigateConfig"; import { FrigateConfig } from "@/types/frigateConfig";
import { RecordingStartingPoint } from "@/types/record"; import { RecordingStartingPoint } from "@/types/record";
import { import {
@ -32,6 +33,8 @@ export default function Events() {
"alert", "alert",
); );
const [showReviewed, setShowReviewed] = usePersistence("showReviewed", false);
const [recording, setRecording] = const [recording, setRecording] =
useOverlayState<RecordingStartingPoint>("recording"); useOverlayState<RecordingStartingPoint>("recording");
@ -206,14 +209,14 @@ export default function Events() {
return []; return [];
} }
if (reviewFilter?.showReviewed != 1) { if (!showReviewed) {
return current.filter((seg) => !seg.has_been_reviewed); return current.filter((seg) => !seg.has_been_reviewed);
} else { } else {
return current; return current;
} }
// only refresh when severity or filter changes // only refresh when severity or filter changes
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [severity, reviewFilter, reviewItems?.all.length]); }, [severity, reviewFilter, showReviewed, reviewItems?.all.length]);
// review summary // review summary
@ -436,6 +439,8 @@ export default function Events() {
filter={reviewFilter} filter={reviewFilter}
severity={severity ?? "alert"} severity={severity ?? "alert"}
startTime={startTime} startTime={startTime}
showReviewed={showReviewed ?? false}
setShowReviewed={setShowReviewed}
setSeverity={setSeverity} setSeverity={setSeverity}
markItemAsReviewed={markItemAsReviewed} markItemAsReviewed={markItemAsReviewed}
markAllItemsAsReviewed={markAllItemsAsReviewed} markAllItemsAsReviewed={markAllItemsAsReviewed}

View File

@ -35,7 +35,6 @@ export type ReviewFilter = {
zones?: string[]; zones?: string[];
before?: number; before?: number;
after?: number; after?: number;
showReviewed?: 0 | 1;
showAll?: boolean; showAll?: boolean;
}; };

View File

@ -62,6 +62,8 @@ type EventViewProps = {
filter?: ReviewFilter; filter?: ReviewFilter;
severity: ReviewSeverity; severity: ReviewSeverity;
startTime?: number; startTime?: number;
showReviewed: boolean;
setShowReviewed: (show: boolean) => void;
setSeverity: (severity: ReviewSeverity) => void; setSeverity: (severity: ReviewSeverity) => void;
markItemAsReviewed: (review: ReviewSegment) => void; markItemAsReviewed: (review: ReviewSegment) => void;
markAllItemsAsReviewed: (currentItems: ReviewSegment[]) => void; markAllItemsAsReviewed: (currentItems: ReviewSegment[]) => void;
@ -78,6 +80,8 @@ export default function EventView({
filter, filter,
severity, severity,
startTime, startTime,
showReviewed,
setShowReviewed,
setSeverity, setSeverity,
markItemAsReviewed, markItemAsReviewed,
markAllItemsAsReviewed, markAllItemsAsReviewed,
@ -108,7 +112,7 @@ export default function EventView({
return { alert: 0, detection: 0, significant_motion: 0 }; return { alert: 0, detection: 0, significant_motion: 0 };
} }
if (filter?.showReviewed == 1) { if (showReviewed) {
return { return {
alert: summary.total_alert ?? 0, alert: summary.total_alert ?? 0,
detection: summary.total_detection ?? 0, detection: summary.total_detection ?? 0,
@ -121,7 +125,7 @@ export default function EventView({
significant_motion: summary.total_motion - summary.reviewed_motion, significant_motion: summary.total_motion - summary.reviewed_motion,
}; };
} }
}, [filter, reviewSummary]); }, [filter, showReviewed, reviewSummary]);
// review interaction // review interaction
@ -358,6 +362,8 @@ export default function EventView({
filter={filter} filter={filter}
motionOnly={motionOnly} motionOnly={motionOnly}
filterList={reviewFilterList} filterList={reviewFilterList}
showReviewed={showReviewed}
setShowReviewed={setShowReviewed}
onUpdateFilter={updateFilter} onUpdateFilter={updateFilter}
setMotionOnly={setMotionOnly} setMotionOnly={setMotionOnly}
/> />

View File

@ -418,6 +418,8 @@ export function RecordingView({
filter={filter} filter={filter}
motionOnly={false} motionOnly={false}
filterList={reviewFilterList} filterList={reviewFilterList}
showReviewed
setShowReviewed={() => {}}
onUpdateFilter={updateFilter} onUpdateFilter={updateFilter}
setMotionOnly={() => {}} setMotionOnly={() => {}}
/> />
@ -699,10 +701,10 @@ function Timeline({
<Skeleton className="size-full" /> <Skeleton className="size-full" />
) )
) : ( ) : (
<div className="h-full overflow-auto bg-secondary"> <div className="scrollbar-container h-full overflow-auto bg-secondary">
<div <div
className={cn( className={cn(
"grid h-auto grid-cols-1 gap-4 overflow-auto p-4", "scrollbar-container grid h-auto grid-cols-1 gap-4 overflow-auto p-4",
isMobile && "sm:grid-cols-2", isMobile && "sm:grid-cols-2",
)} )}
> >