- implement setup page with video feed and preview functionality

This commit is contained in:
2025-12-23 14:36:16 +00:00
parent 9394793669
commit 73c67ad992
7 changed files with 100 additions and 3 deletions

View File

@@ -12,7 +12,7 @@ const Dashboard = () => {
const mostRecent = sightingList[0];
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>
<VideoFeed mostRecentSighting={mostRecent} isLoading={isLoading} size={size} />
<PlateRead sighting={mostRecent} />

View File

@@ -8,12 +8,12 @@ type VideoFeedProps = {
mostRecentSighting: SightingType;
isLoading: boolean;
size: { width: number; height: number };
modeSetting?: number;
isModal?: boolean;
};
const VideoFeed = ({ mostRecentSighting, isLoading, size, modeSetting, isModal = false }: VideoFeedProps) => {
console.log(size);
const { state: cameraSettings, dispatch } = useCameraSettingsContext();
const contextMode = cameraSettings.mode;
const [localMode, setLocalMode] = useState(0);

View 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;

View 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;

View 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 };
};

View 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 };
};

View File

@@ -1,9 +1,10 @@
import { createFileRoute } from "@tanstack/react-router";
import Setup from "../features/setup/Setup";
export const Route = createFileRoute("/setup")({
component: RouteComponent,
});
function RouteComponent() {
return <div className="">Hello "/setup"!</div>;
return <Setup />;
}