-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
CameraImage.tsx
88 lines (77 loc) · 2.58 KB
/
CameraImage.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { useApiHost } from "@/api";
import { useEffect, useMemo, useRef, useState } from "react";
import useSWR from "swr";
import ActivityIndicator from "../indicators/activity-indicator";
import { useResizeObserver } from "@/hooks/resize-observer";
import { isDesktop } from "react-device-detect";
type CameraImageProps = {
className?: string;
camera: string;
onload?: () => void;
searchParams?: string;
};
export default function CameraImage({
className,
camera,
onload,
searchParams = "",
}: CameraImageProps) {
const { data: config } = useSWR("config");
const apiHost = useApiHost();
const [hasLoaded, setHasLoaded] = useState(false);
const containerRef = useRef<HTMLDivElement | null>(null);
const imgRef = useRef<HTMLImageElement | null>(null);
const { name } = config ? config.cameras[camera] : "";
const enabled = config ? config.cameras[camera].enabled : "True";
const [isPortraitImage, setIsPortraitImage] = useState(false);
const [{ width: containerWidth, height: containerHeight }] =
useResizeObserver(containerRef);
const requestHeight = useMemo(() => {
if (!config || containerHeight == 0) {
return 360;
}
return Math.min(
config.cameras[camera].detect.height,
Math.round(containerHeight * (isDesktop ? 1.1 : 1.25)),
);
}, [config, camera, containerHeight]);
useEffect(() => {
if (!config || !imgRef.current) {
return;
}
imgRef.current.src = `${apiHost}api/${name}/latest.webp?h=${requestHeight}${
searchParams ? `&${searchParams}` : ""
}`;
}, [apiHost, name, imgRef, searchParams, requestHeight, config]);
return (
<div className={className} ref={containerRef}>
{enabled ? (
<img
ref={imgRef}
className={`object-contain ${isPortraitImage ? "h-full w-auto" : "h-auto w-full"} rounded-lg md:rounded-2xl`}
onLoad={() => {
setHasLoaded(true);
if (imgRef.current) {
const { naturalHeight, naturalWidth } = imgRef.current;
setIsPortraitImage(
naturalWidth / naturalHeight < containerWidth / containerHeight,
);
}
if (onload) {
onload();
}
}}
/>
) : (
<div className="pt-6 text-center">
Camera is disabled in config, no stream or snapshot available!
</div>
)}
{!hasLoaded && enabled ? (
<div className="absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center">
<ActivityIndicator />
</div>
) : null}
</div>
);
}