Add a live view feature to camera cards with snapshot hover in Cameras.jsx

This commit is contained in:
Sergey Krashevich 2023-06-15 10:13:51 +03:00
parent 3efa77f302
commit 1355b6a1d5
No known key found for this signature in database
GPG Key ID: 625171324E7D3856
2 changed files with 67 additions and 2 deletions

View File

@ -0,0 +1,46 @@
import { h } from 'preact';
import { useApiHost } from '../api';
import { useMemo, useRef } from 'preact/hooks';
import { useResizeObserver } from '../hooks';
import useSWR from 'swr';
export default function CameraLiveView({ camera, stretch = false }) {
const { data: config } = useSWR('config');
const apiHost = useApiHost();
const containerRef = useRef(null);
const [{ width: containerWidth }] = useResizeObserver(containerRef);
const { name } = config ? config.cameras[camera] : '';
const enabled = config ? config.cameras[camera].enabled : 'True';
const { width, height } = config ? config.cameras[camera].detect : { width: 1, height: 1 };
const aspectRatio = width / height;
const scaledHeight = useMemo(() => {
const scaledHeight = Math.floor(containerWidth / aspectRatio);
return stretch ? scaledHeight : Math.min(scaledHeight, height);
}, [containerWidth, aspectRatio, height, stretch]);
const scaledWidth = useMemo(() => Math.ceil(scaledHeight * aspectRatio), [
scaledHeight,
aspectRatio,
]);
const liveStreamUrl = useMemo(() => {
return `${apiHost}/api/${name}`;
}, [apiHost, name]);
return (
<div className="relative w-full" ref={containerRef}>
{
(enabled) ?
<img
data-testid="cameraliveview-img"
height={scaledHeight}
width={scaledWidth}
src={liveStreamUrl}
/>
: <div class="text-center pt-6">Camera is disabled in config, no stream or snapshot available!</div>
}
</div >
);
}

View File

@ -1,12 +1,13 @@
import { h, Fragment } from 'preact';
import { useState, useMemo } from 'preact/hooks';
import ActivityIndicator from '../components/ActivityIndicator';
import Card from '../components/Card';
import CameraImage from '../components/CameraImage';
import CameraLiveView from '../components/CameraLiveView';
import ClipIcon from '../icons/Clip';
import MotionIcon from '../icons/Motion';
import SnapshotIcon from '../icons/Snapshot';
import { useDetectState, useRecordingsState, useSnapshotsState } from '../api/ws';
import { useMemo } from 'preact/hooks';
import useSWR from 'swr';
export default function Cameras() {
@ -86,7 +87,25 @@ function Camera({ name, config }) {
[config, detectValue, sendDetect, recordValue, sendRecordings, snapshotValue, sendSnapshots]
);
const [isHovered, setIsHovered] = useState(false);
return (
<Card buttons={buttons} href={href} header={cleanName} icons={icons} media={<CameraImage camera={name} stretch />} />
<Card
buttons={buttons}
href={href}
header={cleanName}
icons={icons}
media={
<div
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{isHovered
? <CameraLiveView camera={name} stretch /> // Show the live view when the mouse is over the snapshot
: <CameraImage camera={name} stretch /> // Show the snapshot when the mouse is not over it
}
</div>
}
/>
);
}