From 0e3e2e5cccdc669ebd5dc0842411fbf4cd6726d7 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Thu, 6 Mar 2025 20:00:15 -0600 Subject: [PATCH] Add cameras filter to history view (#16995) --- .../components/filter/CamerasFilterButton.tsx | 26 +++++++++++++++++-- .../components/filter/ReviewFilterGroup.tsx | 3 +++ web/src/views/recording/RecordingView.tsx | 19 ++++++++++++-- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/web/src/components/filter/CamerasFilterButton.tsx b/web/src/components/filter/CamerasFilterButton.tsx index c584dc09d..d9deb87bd 100644 --- a/web/src/components/filter/CamerasFilterButton.tsx +++ b/web/src/components/filter/CamerasFilterButton.tsx @@ -18,6 +18,7 @@ type CameraFilterButtonProps = { groups: [string, CameraGroupConfig][]; selectedCameras: string[] | undefined; hideText?: boolean; + mainCamera?: string; updateCameraFilter: (cameras: string[] | undefined) => void; }; export function CamerasFilterButton({ @@ -25,6 +26,7 @@ export function CamerasFilterButton({ groups, selectedCameras, hideText = isMobile, + mainCamera, updateCameraFilter, }: CameraFilterButtonProps) { const [open, setOpen] = useState(false); @@ -74,6 +76,7 @@ export function CamerasFilterButton({ allCameras={allCameras} groups={groups} currentCameras={currentCameras} + mainCamera={mainCamera} setCurrentCameras={setCurrentCameras} setOpen={setOpen} updateCameraFilter={updateCameraFilter} @@ -120,6 +123,7 @@ export function CamerasFilterButton({ type CamerasFilterContentProps = { allCameras: string[]; currentCameras: string[] | undefined; + mainCamera?: string; groups: [string, CameraGroupConfig][]; setCurrentCameras: (cameras: string[] | undefined) => void; setOpen: (open: boolean) => void; @@ -128,6 +132,7 @@ type CamerasFilterContentProps = { export function CamerasFilterContent({ allCameras, currentCameras, + mainCamera, groups, setCurrentCameras, setOpen, @@ -178,12 +183,29 @@ export function CamerasFilterContent({ key={item} isChecked={currentCameras?.includes(item) ?? false} label={item.replaceAll("_", " ")} + disabled={ + mainCamera !== undefined && + currentCameras !== undefined && + item === mainCamera + } // Disable only if mainCamera exists and cameras are filtered onCheckedChange={(isChecked) => { + if ( + mainCamera !== undefined && // Only enforce if mainCamera is defined + item === mainCamera && + !isChecked && + currentCameras !== undefined + ) { + return; // Prevent deselecting mainCamera when filtered and mainCamera is defined + } if (isChecked) { const updatedCameras = currentCameras ? [...currentCameras] - : []; - updatedCameras.push(item); + : mainCamera !== undefined && item !== mainCamera // If mainCamera exists and this isn’t it + ? [mainCamera] // Start with mainCamera when transitioning from undefined + : []; // Otherwise start empty + if (!updatedCameras.includes(item)) { + updatedCameras.push(item); + } setCurrentCameras(updatedCameras); } else { const updatedCameras = currentCameras diff --git a/web/src/components/filter/ReviewFilterGroup.tsx b/web/src/components/filter/ReviewFilterGroup.tsx index dedcb06fc..09eb8092a 100644 --- a/web/src/components/filter/ReviewFilterGroup.tsx +++ b/web/src/components/filter/ReviewFilterGroup.tsx @@ -49,6 +49,7 @@ type ReviewFilterGroupProps = { motionOnly: boolean; filterList?: FilterList; showReviewed: boolean; + mainCamera?: string; setShowReviewed: (show: boolean) => void; onUpdateFilter: (filter: ReviewFilter) => void; setMotionOnly: React.Dispatch>; @@ -63,6 +64,7 @@ export default function ReviewFilterGroup({ motionOnly, filterList, showReviewed, + mainCamera, setShowReviewed, onUpdateFilter, setMotionOnly, @@ -185,6 +187,7 @@ export default function ReviewFilterGroup({ allCameras={filterValues.cameras} groups={groups} selectedCameras={filter?.cameras} + mainCamera={mainCamera} updateCameraFilter={(newCameras) => { onUpdateFilter({ ...filter, cameras: newCameras }); }} diff --git a/web/src/views/recording/RecordingView.tsx b/web/src/views/recording/RecordingView.tsx index c5e528736..0baeca994 100644 --- a/web/src/views/recording/RecordingView.tsx +++ b/web/src/views/recording/RecordingView.tsx @@ -442,7 +442,7 @@ export function RecordingView({ )} {isDesktop && ( {}} - onUpdateFilter={updateFilter} + mainCamera={mainCamera} + onUpdateFilter={(newFilter: ReviewFilter) => { + const updatedCameras = + newFilter.cameras === undefined + ? undefined // Respect undefined as "all cameras" + : newFilter.cameras + ? Array.from( + new Set([mainCamera, ...(newFilter.cameras || [])]), + ) // Include mainCamera if specific cameras are selected + : [mainCamera]; + const adjustedFilter: ReviewFilter = { + ...newFilter, + cameras: updatedCameras, + }; + updateFilter(adjustedFilter); + }} setMotionOnly={() => {}} /> )}