mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
stay in fullscreen when navigating to a camera (#11666)
This commit is contained in:
parent
8c325801ef
commit
a3d116e70e
@ -39,7 +39,7 @@ type HlsVideoPlayerProps = {
|
|||||||
onPlaying?: () => void;
|
onPlaying?: () => void;
|
||||||
setFullResolution?: React.Dispatch<React.SetStateAction<VideoResolutionType>>;
|
setFullResolution?: React.Dispatch<React.SetStateAction<VideoResolutionType>>;
|
||||||
onUploadFrame?: (playTime: number) => Promise<AxiosResponse> | undefined;
|
onUploadFrame?: (playTime: number) => Promise<AxiosResponse> | undefined;
|
||||||
setFullscreen?: (full: boolean) => void;
|
toggleFullscreen?: () => void;
|
||||||
};
|
};
|
||||||
export default function HlsVideoPlayer({
|
export default function HlsVideoPlayer({
|
||||||
videoRef,
|
videoRef,
|
||||||
@ -53,7 +53,7 @@ export default function HlsVideoPlayer({
|
|||||||
onPlaying,
|
onPlaying,
|
||||||
setFullResolution,
|
setFullResolution,
|
||||||
onUploadFrame,
|
onUploadFrame,
|
||||||
setFullscreen,
|
toggleFullscreen,
|
||||||
}: HlsVideoPlayerProps) {
|
}: HlsVideoPlayerProps) {
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ export default function HlsVideoPlayer({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
fullscreen={fullscreen}
|
fullscreen={fullscreen}
|
||||||
setFullscreen={setFullscreen}
|
toggleFullscreen={toggleFullscreen}
|
||||||
/>
|
/>
|
||||||
<TransformComponent
|
<TransformComponent
|
||||||
wrapperStyle={{
|
wrapperStyle={{
|
||||||
|
@ -68,7 +68,7 @@ type VideoControlsProps = {
|
|||||||
onSeek: (diff: number) => void;
|
onSeek: (diff: number) => void;
|
||||||
onSetPlaybackRate: (rate: number) => void;
|
onSetPlaybackRate: (rate: number) => void;
|
||||||
onUploadFrame?: () => void;
|
onUploadFrame?: () => void;
|
||||||
setFullscreen?: (full: boolean) => void;
|
toggleFullscreen?: () => void;
|
||||||
};
|
};
|
||||||
export default function VideoControls({
|
export default function VideoControls({
|
||||||
className,
|
className,
|
||||||
@ -88,7 +88,7 @@ export default function VideoControls({
|
|||||||
onSeek,
|
onSeek,
|
||||||
onSetPlaybackRate,
|
onSetPlaybackRate,
|
||||||
onUploadFrame,
|
onUploadFrame,
|
||||||
setFullscreen,
|
toggleFullscreen,
|
||||||
}: VideoControlsProps) {
|
}: VideoControlsProps) {
|
||||||
// layout
|
// layout
|
||||||
|
|
||||||
@ -160,8 +160,8 @@ export default function VideoControls({
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "f":
|
case "f":
|
||||||
if (setFullscreen && down && !repeat) {
|
if (toggleFullscreen && down && !repeat) {
|
||||||
setFullscreen(!fullscreen);
|
toggleFullscreen();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "m":
|
case "m":
|
||||||
@ -178,7 +178,7 @@ export default function VideoControls({
|
|||||||
},
|
},
|
||||||
// only update when preview only changes
|
// only update when preview only changes
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
[video, isPlaying, fullscreen, setFullscreen, onSeek],
|
[video, isPlaying, fullscreen, toggleFullscreen, onSeek],
|
||||||
);
|
);
|
||||||
useKeyboardListener(
|
useKeyboardListener(
|
||||||
hotKeys
|
hotKeys
|
||||||
@ -287,11 +287,8 @@ export default function VideoControls({
|
|||||||
onUploadFrame={onUploadFrame}
|
onUploadFrame={onUploadFrame}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{features.fullscreen && setFullscreen && (
|
{features.fullscreen && toggleFullscreen && (
|
||||||
<div
|
<div className="cursor-pointer" onClick={toggleFullscreen}>
|
||||||
className="cursor-pointer"
|
|
||||||
onClick={() => setFullscreen(!fullscreen)}
|
|
||||||
>
|
|
||||||
{fullscreen ? <FaCompress /> : <FaExpand />}
|
{fullscreen ? <FaCompress /> : <FaExpand />}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -29,7 +29,7 @@ type DynamicVideoPlayerProps = {
|
|||||||
onTimestampUpdate?: (timestamp: number) => void;
|
onTimestampUpdate?: (timestamp: number) => void;
|
||||||
onClipEnded?: () => void;
|
onClipEnded?: () => void;
|
||||||
setFullResolution: React.Dispatch<React.SetStateAction<VideoResolutionType>>;
|
setFullResolution: React.Dispatch<React.SetStateAction<VideoResolutionType>>;
|
||||||
setFullscreen: (full: boolean) => void;
|
toggleFullscreen: () => void;
|
||||||
};
|
};
|
||||||
export default function DynamicVideoPlayer({
|
export default function DynamicVideoPlayer({
|
||||||
className,
|
className,
|
||||||
@ -44,7 +44,7 @@ export default function DynamicVideoPlayer({
|
|||||||
onTimestampUpdate,
|
onTimestampUpdate,
|
||||||
onClipEnded,
|
onClipEnded,
|
||||||
setFullResolution,
|
setFullResolution,
|
||||||
setFullscreen,
|
toggleFullscreen,
|
||||||
}: DynamicVideoPlayerProps) {
|
}: DynamicVideoPlayerProps) {
|
||||||
const apiHost = useApiHost();
|
const apiHost = useApiHost();
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
@ -207,7 +207,7 @@ export default function DynamicVideoPlayer({
|
|||||||
}}
|
}}
|
||||||
setFullResolution={setFullResolution}
|
setFullResolution={setFullResolution}
|
||||||
onUploadFrame={onUploadFrameToPlus}
|
onUploadFrame={onUploadFrameToPlus}
|
||||||
setFullscreen={setFullscreen}
|
toggleFullscreen={toggleFullscreen}
|
||||||
/>
|
/>
|
||||||
<PreviewPlayer
|
<PreviewPlayer
|
||||||
className={cn(
|
className={cn(
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { useFullscreen } from "@/hooks/use-fullscreen";
|
||||||
import {
|
import {
|
||||||
useHashState,
|
useHashState,
|
||||||
usePersistedOverlayState,
|
usePersistedOverlayState,
|
||||||
@ -6,7 +7,7 @@ import { FrigateConfig } from "@/types/frigateConfig";
|
|||||||
import LiveBirdseyeView from "@/views/live/LiveBirdseyeView";
|
import LiveBirdseyeView from "@/views/live/LiveBirdseyeView";
|
||||||
import LiveCameraView from "@/views/live/LiveCameraView";
|
import LiveCameraView from "@/views/live/LiveCameraView";
|
||||||
import LiveDashboardView from "@/views/live/LiveDashboardView";
|
import LiveDashboardView from "@/views/live/LiveDashboardView";
|
||||||
import { useEffect, useMemo } from "react";
|
import { useEffect, useMemo, useRef } from "react";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
function Live() {
|
function Live() {
|
||||||
@ -20,6 +21,12 @@ function Live() {
|
|||||||
"default" as string,
|
"default" as string,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// fullscreen
|
||||||
|
|
||||||
|
const mainRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
|
const { fullscreen, toggleFullscreen } = useFullscreen(mainRef);
|
||||||
|
|
||||||
// document title
|
// document title
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -78,21 +85,31 @@ function Live() {
|
|||||||
[cameras, selectedCameraName],
|
[cameras, selectedCameraName],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (selectedCameraName == "birdseye") {
|
|
||||||
return <LiveBirdseyeView />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedCamera) {
|
|
||||||
return <LiveCameraView config={config} camera={selectedCamera} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LiveDashboardView
|
<div className="size-full" ref={mainRef}>
|
||||||
cameras={cameras}
|
{selectedCameraName === "birdseye" ? (
|
||||||
cameraGroup={cameraGroup}
|
<LiveBirdseyeView
|
||||||
includeBirdseye={includesBirdseye}
|
fullscreen={fullscreen}
|
||||||
onSelectCamera={setSelectedCameraName}
|
toggleFullscreen={toggleFullscreen}
|
||||||
/>
|
/>
|
||||||
|
) : selectedCamera ? (
|
||||||
|
<LiveCameraView
|
||||||
|
config={config}
|
||||||
|
camera={selectedCamera}
|
||||||
|
fullscreen={fullscreen}
|
||||||
|
toggleFullscreen={toggleFullscreen}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<LiveDashboardView
|
||||||
|
cameras={cameras}
|
||||||
|
cameraGroup={cameraGroup}
|
||||||
|
includeBirdseye={includesBirdseye}
|
||||||
|
onSelectCamera={setSelectedCameraName}
|
||||||
|
fullscreen={fullscreen}
|
||||||
|
toggleFullscreen={toggleFullscreen}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ import { VideoResolutionType } from "@/types/live";
|
|||||||
import { ASPECT_VERTICAL_LAYOUT, ASPECT_WIDE_LAYOUT } from "@/types/record";
|
import { ASPECT_VERTICAL_LAYOUT, ASPECT_WIDE_LAYOUT } from "@/types/record";
|
||||||
import { useResizeObserver } from "@/hooks/resize-observer";
|
import { useResizeObserver } from "@/hooks/resize-observer";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { useFullscreen } from "@/hooks/use-fullscreen";
|
||||||
|
|
||||||
const SEGMENT_DURATION = 30;
|
const SEGMENT_DURATION = 30;
|
||||||
|
|
||||||
@ -227,32 +228,7 @@ export function RecordingView({
|
|||||||
|
|
||||||
// fullscreen
|
// fullscreen
|
||||||
|
|
||||||
const [fullscreen, setFullscreen] = useState(false);
|
const { fullscreen, toggleFullscreen } = useFullscreen(mainLayoutRef);
|
||||||
|
|
||||||
const onToggleFullscreen = useCallback(
|
|
||||||
(full: boolean) => {
|
|
||||||
if (full) {
|
|
||||||
mainLayoutRef.current?.requestFullscreen();
|
|
||||||
} else {
|
|
||||||
document.exitFullscreen();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[mainLayoutRef],
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (mainLayoutRef.current == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const fsListener = () => {
|
|
||||||
setFullscreen(document.fullscreenElement != null);
|
|
||||||
};
|
|
||||||
document.addEventListener("fullscreenchange", fsListener);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("fullscreenchange", fsListener);
|
|
||||||
};
|
|
||||||
}, [mainLayoutRef]);
|
|
||||||
|
|
||||||
// layout
|
// layout
|
||||||
|
|
||||||
@ -535,7 +511,7 @@ export function RecordingView({
|
|||||||
}}
|
}}
|
||||||
isScrubbing={scrubbing || exportMode == "timeline"}
|
isScrubbing={scrubbing || exportMode == "timeline"}
|
||||||
setFullResolution={setFullResolution}
|
setFullResolution={setFullResolution}
|
||||||
setFullscreen={onToggleFullscreen}
|
toggleFullscreen={toggleFullscreen}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{isDesktop && (
|
{isDesktop && (
|
||||||
|
@ -40,8 +40,6 @@ import {
|
|||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { useFullscreen } from "@/hooks/use-fullscreen";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { Toaster } from "@/components/ui/sonner";
|
import { Toaster } from "@/components/ui/sonner";
|
||||||
|
|
||||||
type DraggableGridLayoutProps = {
|
type DraggableGridLayoutProps = {
|
||||||
@ -55,6 +53,8 @@ type DraggableGridLayoutProps = {
|
|||||||
visibleCameras: string[];
|
visibleCameras: string[];
|
||||||
isEditMode: boolean;
|
isEditMode: boolean;
|
||||||
setIsEditMode: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsEditMode: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
fullscreen: boolean;
|
||||||
|
toggleFullscreen: () => void;
|
||||||
};
|
};
|
||||||
export default function DraggableGridLayout({
|
export default function DraggableGridLayout({
|
||||||
cameras,
|
cameras,
|
||||||
@ -67,6 +67,8 @@ export default function DraggableGridLayout({
|
|||||||
visibleCameras,
|
visibleCameras,
|
||||||
isEditMode,
|
isEditMode,
|
||||||
setIsEditMode,
|
setIsEditMode,
|
||||||
|
fullscreen,
|
||||||
|
toggleFullscreen,
|
||||||
}: DraggableGridLayoutProps) {
|
}: DraggableGridLayoutProps) {
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
const birdseyeConfig = useMemo(() => config?.birdseye, [config]);
|
const birdseyeConfig = useMemo(() => config?.birdseye, [config]);
|
||||||
@ -289,20 +291,6 @@ export default function DraggableGridLayout({
|
|||||||
}
|
}
|
||||||
}, [containerRef, containerHeight]);
|
}, [containerRef, containerHeight]);
|
||||||
|
|
||||||
// fullscreen state
|
|
||||||
|
|
||||||
const { fullscreen, toggleFullscreen, error, clearError } =
|
|
||||||
useFullscreen(gridContainerRef);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (error !== null) {
|
|
||||||
toast.error(`Error attempting fullscreen mode: ${error}`, {
|
|
||||||
position: "top-center",
|
|
||||||
});
|
|
||||||
clearError();
|
|
||||||
}
|
|
||||||
}, [error, clearError]);
|
|
||||||
|
|
||||||
const cellHeight = useMemo(() => {
|
const cellHeight = useMemo(() => {
|
||||||
const aspectRatio = 16 / 9;
|
const aspectRatio = 16 / 9;
|
||||||
// subtract container margin, 1 camera takes up at least 4 rows
|
// subtract container margin, 1 camera takes up at least 4 rows
|
||||||
@ -463,21 +451,23 @@ export default function DraggableGridLayout({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
{!isEditMode && (
|
{!isEditMode && (
|
||||||
<>
|
<>
|
||||||
<Tooltip>
|
{!fullscreen && (
|
||||||
<TooltipTrigger asChild>
|
<Tooltip>
|
||||||
<div
|
<TooltipTrigger asChild>
|
||||||
className="cursor-pointer rounded-lg bg-secondary text-secondary-foreground opacity-60 transition-all duration-300 hover:bg-muted hover:opacity-100"
|
<div
|
||||||
onClick={() =>
|
className="cursor-pointer rounded-lg bg-secondary text-secondary-foreground opacity-60 transition-all duration-300 hover:bg-muted hover:opacity-100"
|
||||||
setEditGroup((prevEditGroup) => !prevEditGroup)
|
onClick={() =>
|
||||||
}
|
setEditGroup((prevEditGroup) => !prevEditGroup)
|
||||||
>
|
}
|
||||||
<LuPencil className="size-5 md:m-[6px]" />
|
>
|
||||||
</div>
|
<LuPencil className="size-5 md:m-[6px]" />
|
||||||
</TooltipTrigger>
|
</div>
|
||||||
<TooltipContent>
|
</TooltipTrigger>
|
||||||
{isEditMode ? "Exit Editing" : "Edit Camera Group"}
|
<TooltipContent>
|
||||||
</TooltipContent>
|
{isEditMode ? "Exit Editing" : "Edit Camera Group"}
|
||||||
</Tooltip>
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<div
|
<div
|
||||||
|
@ -4,7 +4,6 @@ import BirdseyeLivePlayer from "@/components/player/BirdseyeLivePlayer";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||||
import { useResizeObserver } from "@/hooks/resize-observer";
|
import { useResizeObserver } from "@/hooks/resize-observer";
|
||||||
import { useFullscreen } from "@/hooks/use-fullscreen";
|
|
||||||
import { FrigateConfig } from "@/types/frigateConfig";
|
import { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { useMemo, useRef } from "react";
|
import { useMemo, useRef } from "react";
|
||||||
import {
|
import {
|
||||||
@ -19,7 +18,15 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
|
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
|
|
||||||
export default function LiveBirdseyeView() {
|
type LiveBirdseyeViewProps = {
|
||||||
|
fullscreen: boolean;
|
||||||
|
toggleFullscreen: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function LiveBirdseyeView({
|
||||||
|
fullscreen,
|
||||||
|
toggleFullscreen,
|
||||||
|
}: LiveBirdseyeViewProps) {
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { isPortrait } = useMobileOrientation();
|
const { isPortrait } = useMobileOrientation();
|
||||||
@ -28,10 +35,6 @@ export default function LiveBirdseyeView() {
|
|||||||
const [{ width: windowWidth, height: windowHeight }] =
|
const [{ width: windowWidth, height: windowHeight }] =
|
||||||
useResizeObserver(window);
|
useResizeObserver(window);
|
||||||
|
|
||||||
// fullscreen state
|
|
||||||
|
|
||||||
const { fullscreen, toggleFullscreen } = useFullscreen(mainRef);
|
|
||||||
|
|
||||||
// playback state
|
// playback state
|
||||||
|
|
||||||
const cameraAspectRatio = useMemo(() => {
|
const cameraAspectRatio = useMemo(() => {
|
||||||
|
@ -72,15 +72,18 @@ import {
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
|
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { useFullscreen } from "@/hooks/use-fullscreen";
|
|
||||||
|
|
||||||
type LiveCameraViewProps = {
|
type LiveCameraViewProps = {
|
||||||
config?: FrigateConfig;
|
config?: FrigateConfig;
|
||||||
camera: CameraConfig;
|
camera: CameraConfig;
|
||||||
|
fullscreen: boolean;
|
||||||
|
toggleFullscreen: () => void;
|
||||||
};
|
};
|
||||||
export default function LiveCameraView({
|
export default function LiveCameraView({
|
||||||
config,
|
config,
|
||||||
camera,
|
camera,
|
||||||
|
fullscreen,
|
||||||
|
toggleFullscreen,
|
||||||
}: LiveCameraViewProps) {
|
}: LiveCameraViewProps) {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { isPortrait } = useMobileOrientation();
|
const { isPortrait } = useMobileOrientation();
|
||||||
@ -175,9 +178,7 @@ export default function LiveCameraView({
|
|||||||
[clickOverlayRef, clickOverlay, sendPtz],
|
[clickOverlayRef, clickOverlay, sendPtz],
|
||||||
);
|
);
|
||||||
|
|
||||||
// fullscreen / pip state
|
// pip state
|
||||||
|
|
||||||
const { fullscreen, toggleFullscreen } = useFullscreen(mainRef);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setPip(document.pictureInPictureElement != null);
|
setPip(document.pictureInPictureElement != null);
|
||||||
@ -314,6 +315,18 @@ export default function LiveCameraView({
|
|||||||
<div
|
<div
|
||||||
className={`flex flex-row items-center gap-2 *:rounded-lg ${isMobile ? "landscape:flex-col" : ""}`}
|
className={`flex flex-row items-center gap-2 *:rounded-lg ${isMobile ? "landscape:flex-col" : ""}`}
|
||||||
>
|
>
|
||||||
|
{fullscreen && (
|
||||||
|
<Button
|
||||||
|
className="bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500 text-primary"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => navigate(-1)}
|
||||||
|
>
|
||||||
|
<IoMdArrowRoundBack className="size-5 text-secondary-foreground" />
|
||||||
|
{isDesktop && (
|
||||||
|
<div className="text-secondary-foreground">Back</div>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
{!isIOS && (
|
{!isIOS && (
|
||||||
<CameraFeatureToggle
|
<CameraFeatureToggle
|
||||||
className="p-2 md:p-0"
|
className="p-2 md:p-0"
|
||||||
|
@ -30,12 +30,16 @@ type LiveDashboardViewProps = {
|
|||||||
cameraGroup?: string;
|
cameraGroup?: string;
|
||||||
includeBirdseye: boolean;
|
includeBirdseye: boolean;
|
||||||
onSelectCamera: (camera: string) => void;
|
onSelectCamera: (camera: string) => void;
|
||||||
|
fullscreen: boolean;
|
||||||
|
toggleFullscreen: () => void;
|
||||||
};
|
};
|
||||||
export default function LiveDashboardView({
|
export default function LiveDashboardView({
|
||||||
cameras,
|
cameras,
|
||||||
cameraGroup,
|
cameraGroup,
|
||||||
includeBirdseye,
|
includeBirdseye,
|
||||||
onSelectCamera,
|
onSelectCamera,
|
||||||
|
fullscreen,
|
||||||
|
toggleFullscreen,
|
||||||
}: LiveDashboardViewProps) {
|
}: LiveDashboardViewProps) {
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
|
|
||||||
@ -214,7 +218,7 @@ export default function LiveDashboardView({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{events && events.length > 0 && (
|
{!fullscreen && events && events.length > 0 && (
|
||||||
<ScrollArea>
|
<ScrollArea>
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<div className="flex items-center gap-2 px-1">
|
<div className="flex items-center gap-2 px-1">
|
||||||
@ -281,6 +285,8 @@ export default function LiveDashboardView({
|
|||||||
visibleCameras={visibleCameras}
|
visibleCameras={visibleCameras}
|
||||||
isEditMode={isEditMode}
|
isEditMode={isEditMode}
|
||||||
setIsEditMode={setIsEditMode}
|
setIsEditMode={setIsEditMode}
|
||||||
|
fullscreen={fullscreen}
|
||||||
|
toggleFullscreen={toggleFullscreen}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user