Show frigate features in bottom sheet on mobile

This commit is contained in:
Nicolas Mowen 2024-04-01 13:55:04 -06:00
parent bd70bf1c31
commit 5f25f29d7e

View File

@ -8,12 +8,15 @@ import {
import CameraFeatureToggle from "@/components/dynamic/CameraFeatureToggle";
import LivePlayer from "@/components/player/LivePlayer";
import { Button } from "@/components/ui/button";
import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { TooltipProvider } from "@/components/ui/tooltip";
import { useResizeObserver } from "@/hooks/resize-observer";
import useKeyboardListener from "@/hooks/use-keyboard-listener";
@ -39,6 +42,7 @@ import {
FaAngleLeft,
FaAngleRight,
FaAngleUp,
FaCog,
FaCompress,
FaExpand,
FaMicrophone,
@ -70,19 +74,6 @@ export default function LiveCameraView({ camera }: LiveCameraViewProps) {
const [{ width: windowWidth, height: windowHeight }] =
useResizeObserver(window);
// camera features
const { payload: detectState, send: sendDetect } = useDetectState(
camera.name,
);
const { payload: recordState, send: sendRecord } = useRecordingsState(
camera.name,
);
const { payload: snapshotState, send: sendSnapshot } = useSnapshotsState(
camera.name,
);
const { payload: audioState, send: sendAudio } = useAudioState(camera.name);
// click overlay for ptzs
const [clickOverlay, setClickOverlay] = useState(false);
@ -264,42 +255,11 @@ export default function LiveCameraView({ camera }: LiveCameraViewProps) {
title={`${audio ? "Disable" : "Enable"} Camera Audio`}
onClick={() => setAudio(!audio)}
/>
<CameraFeatureToggle
className="p-2 md:p-0"
variant={fullscreen ? "overlay" : "primary"}
Icon={detectState == "ON" ? MdPersonSearch : MdPersonOff}
isActive={detectState == "ON"}
title={`${detectState == "ON" ? "Disable" : "Enable"} Detect`}
onClick={() => sendDetect(detectState == "ON" ? "OFF" : "ON")}
<FrigateCameraFeatures
camera={camera.name}
audioDetectEnabled={camera.audio.enabled_in_config}
fullscreen={fullscreen}
/>
<CameraFeatureToggle
className="p-2 md:p-0"
variant={fullscreen ? "overlay" : "primary"}
Icon={recordState == "ON" ? LuVideo : LuVideoOff}
isActive={recordState == "ON"}
title={`${recordState == "ON" ? "Disable" : "Enable"} Recording`}
onClick={() => sendRecord(recordState == "ON" ? "OFF" : "ON")}
/>
<CameraFeatureToggle
className="p-2 md:p-0"
variant={fullscreen ? "overlay" : "primary"}
Icon={snapshotState == "ON" ? MdPhotoCamera : MdNoPhotography}
isActive={snapshotState == "ON"}
title={`${snapshotState == "ON" ? "Disable" : "Enable"} Snapshots`}
onClick={() =>
sendSnapshot(snapshotState == "ON" ? "OFF" : "ON")
}
/>
{camera.audio.enabled_in_config && (
<CameraFeatureToggle
className="p-2 md:p-0"
variant={fullscreen ? "overlay" : "primary"}
Icon={audioState == "ON" ? LuEar : LuEarOff}
isActive={audioState == "ON"}
title={`${audioState == "ON" ? "Disable" : "Enable"} Audio Detect`}
onClick={() => sendAudio(audioState == "ON" ? "OFF" : "ON")}
/>
)}
</div>
</TooltipProvider>
</div>
@ -532,3 +492,145 @@ function PtzControlPanel({
</div>
);
}
type FrigateCameraFeaturesProps = {
camera: string;
audioDetectEnabled: boolean;
fullscreen: boolean;
};
function FrigateCameraFeatures({
camera,
audioDetectEnabled,
fullscreen,
}: FrigateCameraFeaturesProps) {
const { payload: detectState, send: sendDetect } = useDetectState(camera);
const { payload: recordState, send: sendRecord } = useRecordingsState(camera);
const { payload: snapshotState, send: sendSnapshot } =
useSnapshotsState(camera);
const { payload: audioState, send: sendAudio } = useAudioState(camera);
// desktop shows icons part of row
if (isDesktop) {
return (
<>
<CameraFeatureToggle
className="p-2 md:p-0"
variant={fullscreen ? "overlay" : "primary"}
Icon={detectState == "ON" ? MdPersonSearch : MdPersonOff}
isActive={detectState == "ON"}
title={`${detectState == "ON" ? "Disable" : "Enable"} Detect`}
onClick={() => sendDetect(detectState == "ON" ? "OFF" : "ON")}
/>
<CameraFeatureToggle
className="p-2 md:p-0"
variant={fullscreen ? "overlay" : "primary"}
Icon={recordState == "ON" ? LuVideo : LuVideoOff}
isActive={recordState == "ON"}
title={`${recordState == "ON" ? "Disable" : "Enable"} Recording`}
onClick={() => sendRecord(recordState == "ON" ? "OFF" : "ON")}
/>
<CameraFeatureToggle
className="p-2 md:p-0"
variant={fullscreen ? "overlay" : "primary"}
Icon={snapshotState == "ON" ? MdPhotoCamera : MdNoPhotography}
isActive={snapshotState == "ON"}
title={`${snapshotState == "ON" ? "Disable" : "Enable"} Snapshots`}
onClick={() => sendSnapshot(snapshotState == "ON" ? "OFF" : "ON")}
/>
{audioDetectEnabled && (
<CameraFeatureToggle
className="p-2 md:p-0"
variant={fullscreen ? "overlay" : "primary"}
Icon={audioState == "ON" ? LuEar : LuEarOff}
isActive={audioState == "ON"}
title={`${audioState == "ON" ? "Disable" : "Enable"} Audio Detect`}
onClick={() => sendAudio(audioState == "ON" ? "OFF" : "ON")}
/>
)}
</>
);
}
// mobile doesn't show settings in fullscreen view
if (fullscreen) {
return;
}
return (
<Drawer>
<DrawerTrigger>
<CameraFeatureToggle
className="p-2"
variant="primary"
Icon={FaCog}
isActive={false}
title={`${camera} Settings`}
/>
</DrawerTrigger>
<DrawerContent className="px-2 py-4 flex flex-col gap-3 rounded-2xl">
<div className="flex justify-between items-center gap-1">
<Label
className="w-full mx-2 text-secondary-foreground capitalize cursor-pointer"
htmlFor={"camera-detect"}
>
Object Detection
</Label>
<Switch
id={"camera-detect"}
checked={detectState == "ON"}
onCheckedChange={() =>
sendDetect(detectState == "ON" ? "OFF" : "ON")
}
/>
</div>
<div className="flex justify-between items-center gap-1">
<Label
className="w-full mx-2 text-secondary-foreground capitalize cursor-pointer"
htmlFor={"camera-record"}
>
Recording
</Label>
<Switch
id={"camera-record"}
checked={recordState == "ON"}
onCheckedChange={() =>
sendRecord(recordState == "ON" ? "OFF" : "ON")
}
/>
</div>
<div className="flex justify-between items-center gap-1">
<Label
className="w-full mx-2 text-secondary-foreground capitalize cursor-pointer"
htmlFor={"camera-snapshot"}
>
Snapshots
</Label>
<Switch
id={"camera-snapshot"}
checked={snapshotState == "ON"}
onCheckedChange={() =>
sendSnapshot(snapshotState == "ON" ? "OFF" : "ON")
}
/>
</div>
{audioDetectEnabled && (
<div className="flex justify-between items-center gap-1">
<Label
className="w-full mx-2 text-secondary-foreground capitalize cursor-pointer"
htmlFor={"camera-audio-detect"}
>
Audio Detection
</Label>
<Switch
id={"camera-audio-detect"}
checked={audioState == "ON"}
onCheckedChange={() =>
sendAudio(audioState == "ON" ? "OFF" : "ON")
}
/>
</div>
)}
</DrawerContent>
</Drawer>
);
}