Compare commits
3 Commits
feature/mo
...
feature/se
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a99a15342 | |||
| 8dac436831 | |||
| 73c67ad992 |
@@ -12,7 +12,7 @@ const Dashboard = () => {
|
|||||||
const mostRecent = sightingList[0];
|
const mostRecent = sightingList[0];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid gird-cols-1 md:grid-cols-2 gap-2 md:gap-5">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 md:gap-5">
|
||||||
<div>
|
<div>
|
||||||
<VideoFeed mostRecentSighting={mostRecent} isLoading={isLoading} size={size} />
|
<VideoFeed mostRecentSighting={mostRecent} isLoading={isLoading} size={size} />
|
||||||
<PlateRead sighting={mostRecent} />
|
<PlateRead sighting={mostRecent} />
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ type VideoFeedProps = {
|
|||||||
mostRecentSighting: SightingType;
|
mostRecentSighting: SightingType;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
size: { width: number; height: number };
|
size: { width: number; height: number };
|
||||||
|
|
||||||
modeSetting?: number;
|
modeSetting?: number;
|
||||||
isModal?: boolean;
|
isModal?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const VideoFeed = ({ mostRecentSighting, isLoading, size, modeSetting, isModal = false }: VideoFeedProps) => {
|
const VideoFeed = ({ mostRecentSighting, isLoading, size, modeSetting, isModal = false }: VideoFeedProps) => {
|
||||||
|
console.log(size);
|
||||||
const { state: cameraSettings, dispatch } = useCameraSettingsContext();
|
const { state: cameraSettings, dispatch } = useCameraSettingsContext();
|
||||||
const contextMode = cameraSettings.mode;
|
const contextMode = cameraSettings.mode;
|
||||||
const [localMode, setLocalMode] = useState(0);
|
const [localMode, setLocalMode] = useState(0);
|
||||||
|
|||||||
11
src/features/setup/Setup.tsx
Normal file
11
src/features/setup/Setup.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import VideoFeedSetup from "./components/videofeed/VideoFeedSetup";
|
||||||
|
|
||||||
|
const Setup = () => {
|
||||||
|
return (
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-2 md:gap-5">
|
||||||
|
<VideoFeedSetup />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Setup;
|
||||||
41
src/features/setup/components/videofeed/VideoFeedSetup.tsx
Normal file
41
src/features/setup/components/videofeed/VideoFeedSetup.tsx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { Stage, Layer, Image } from "react-konva";
|
||||||
|
import { useCreateVideoPreviewSnapshot } from "../../hooks/useCreatePreviewImage";
|
||||||
|
import { useEffect, type RefObject } from "react";
|
||||||
|
import { useCameraSettingsContext } from "../../../../app/context/CameraSettingsContext";
|
||||||
|
|
||||||
|
const VideoFeedSetup = () => {
|
||||||
|
const { latestBitmapRef, isLoading } = useCreateVideoPreviewSnapshot();
|
||||||
|
const { state, dispatch } = useCameraSettingsContext();
|
||||||
|
const size = state.imageSize;
|
||||||
|
|
||||||
|
const draw = (bmp: RefObject<ImageBitmap | null>): ImageBitmap | null => {
|
||||||
|
if (!bmp || !bmp.current) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const image = bmp.current;
|
||||||
|
return image;
|
||||||
|
};
|
||||||
|
const image = draw(latestBitmapRef);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updateSize = () => {
|
||||||
|
const width = window.innerWidth * 0.48;
|
||||||
|
const height = (width * 2) / 3;
|
||||||
|
dispatch({ type: "SET_IMAGE_SIZE", payload: { width, height } });
|
||||||
|
};
|
||||||
|
updateSize();
|
||||||
|
window.addEventListener("resize", updateSize);
|
||||||
|
return () => window.removeEventListener("resize", updateSize);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (isLoading) return <>Loading...</>;
|
||||||
|
return (
|
||||||
|
<div className="mt-[1%]">
|
||||||
|
<Stage width={size.width} height={size.height}>
|
||||||
|
<Layer>{image && <Image image={image} height={size.height} width={size.width} cornerRadius={10} />}</Layer>
|
||||||
|
</Stage>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VideoFeedSetup;
|
||||||
25
src/features/setup/hooks/useCreatePreviewImage.ts
Normal file
25
src/features/setup/hooks/useCreatePreviewImage.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
import { useVideoPreview } from "./useVideoPreview";
|
||||||
|
|
||||||
|
export const useCreateVideoPreviewSnapshot = () => {
|
||||||
|
const { videoPreviewQuery } = useVideoPreview();
|
||||||
|
const latestBitmapRef = useRef<ImageBitmap | null>(null);
|
||||||
|
const isLoading = videoPreviewQuery?.isPending;
|
||||||
|
const imageBlob = videoPreviewQuery?.data;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function createImageBitmapFromBlob() {
|
||||||
|
if (!imageBlob) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const bitmap = await createImageBitmap(imageBlob);
|
||||||
|
latestBitmapRef.current = bitmap;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createImageBitmapFromBlob();
|
||||||
|
}, [imageBlob]);
|
||||||
|
|
||||||
|
return { latestBitmapRef, isLoading, imageURL: imageBlob ? URL.createObjectURL(imageBlob) : null };
|
||||||
|
};
|
||||||
19
src/features/setup/hooks/useVideoPreview.ts
Normal file
19
src/features/setup/hooks/useVideoPreview.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { cambase } from "../../../app/config";
|
||||||
|
|
||||||
|
const fetchVideoPreview = async () => {
|
||||||
|
const response = await fetch(`${cambase}/Colour-preview`);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to fetch video preview");
|
||||||
|
}
|
||||||
|
return response.blob();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useVideoPreview = () => {
|
||||||
|
const videoPreviewQuery = useQuery({
|
||||||
|
queryKey: ["videoPreview"],
|
||||||
|
queryFn: fetchVideoPreview,
|
||||||
|
refetchInterval: 100,
|
||||||
|
});
|
||||||
|
return { videoPreviewQuery };
|
||||||
|
};
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
import { createFileRoute } from "@tanstack/react-router";
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
|
import Setup from "../features/setup/Setup";
|
||||||
|
|
||||||
export const Route = createFileRoute("/setup")({
|
export const Route = createFileRoute("/setup")({
|
||||||
component: RouteComponent,
|
component: RouteComponent,
|
||||||
});
|
});
|
||||||
|
|
||||||
function RouteComponent() {
|
function RouteComponent() {
|
||||||
return <div className="">Hello "/setup"!</div>;
|
return <Setup />;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user