import { useEffect, useRef, useState, type RefObject } from "react"; import { Stage, Layer, Image, Shape } from "react-konva"; import type { KonvaEventObject } from "konva/lib/Node"; import { useCreateVideoSnapshot } from "../../hooks/useGetvideoSnapshots"; import Card from "../../../../ui/Card"; import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext"; const rows = 40; const cols = 40; const size = 20; const gap = 0; const VideoFeedGridPainter = () => { const { state } = useCameraFeedContext(); const cameraFeedID = state.cameraFeedID; const paintedCells = state.paintedCells[cameraFeedID]; const regions = state.regionsByCamera[cameraFeedID]; const selectedRegionIndex = state.selectedRegionIndex; const mode = state.modeByCamera[cameraFeedID]; const { latestBitmapRef, isloading } = useCreateVideoSnapshot(); const [stageSize, setStageSize] = useState({ width: 740, height: 460 }); const isDrawingRef = useRef(false); // eslint-disable-next-line @typescript-eslint/no-explicit-any const paintLayerRef = useRef(null); const draw = (bmp: RefObject): ImageBitmap | null => { if (!bmp || !bmp.current) { return null; } const image = bmp.current; return image; }; const image = draw(latestBitmapRef); const paintCell = (x: number, y: number) => { const col = Math.floor(x / (size + gap)); const row = Math.floor(y / (size + gap)); if (row < 0 || row >= rows || col < 0 || col >= cols) return; const activeRegion = regions[selectedRegionIndex]; if (!activeRegion) return; const key = `${row}-${col}`; const currentColour = regions[selectedRegionIndex].brushColour; const map = paintedCells; const existing = map.get(key); if (mode === "eraser") { if (map.has(key)) { map.delete(key); paintLayerRef.current?.batchDraw(); } return; } if (existing && existing.colour === currentColour) return; map.set(key, { colour: currentColour }); paintLayerRef.current?.batchDraw(); }; const handleStageMouseDown = (e: KonvaEventObject) => { if (!regions[selectedRegionIndex]) return; isDrawingRef.current = true; const pos = e.target.getStage()?.getPointerPosition(); if (pos) paintCell(pos.x, pos.y); }; const handleStageMouseMove = (e: KonvaEventObject) => { if (!isDrawingRef.current) return; if (!regions[selectedRegionIndex]) return; const pos = e.target.getStage()?.getPointerPosition(); if (pos) paintCell(pos.x, pos.y); }; const handleStageMouseUp = () => { isDrawingRef.current = false; }; useEffect(() => { const handleResize = () => { const width = window.innerWidth; const aspectRatio = 740 / 460; const newWidth = width * 0.39; const newHeight = newWidth / aspectRatio; setStageSize({ width: newWidth, height: newHeight }); }; handleResize(); window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, []); if (image === null || isloading) return ( Loading Video feed… ); return (
{ const cells = paintedCells; cells.forEach((cell, key) => { const [rowStr, colStr] = key.split("-"); const row = Number(rowStr); const col = Number(colStr); const x = col * (size + gap); const y = row * (size + gap); ctx.beginPath(); ctx.rect(x, y, size, size); ctx.fillStyle = cell.colour; ctx.fill(); }); ctx.fillStrokeShape(shape); }} width={stageSize.width} height={stageSize.height} />
); }; export default VideoFeedGridPainter;