Refactor camera feed handling to support dynamic camera IDs and improve context management

This commit is contained in:
2025-12-17 14:19:23 +00:00
parent cc8b3a5691
commit 775fce7900
19 changed files with 211 additions and 248 deletions

View File

@@ -28,6 +28,7 @@ const CameraPanel = ({ tabIndex, isResetAllModalOpen, handleClose, setIsResetMod
return "B";
case 2:
return "C";
//Add more cases if more cameras are added
default:
return "A";
}

View File

@@ -2,6 +2,7 @@ import Card from "../../../../ui/Card";
import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
import "react-tabs/style/react-tabs.css";
import CameraPanel from "./CameraPanel";
import { CAMERA_IDS } from "../../../../app/config/cameraConfig";
type CameraSettingsProps = {
setTabIndex: (tabIndex: number) => void;
@@ -12,7 +13,6 @@ type CameraSettingsProps = {
};
const CameraSettings = ({
tabIndex,
setTabIndex,
isResetAllModalOpen,
handleClose,
@@ -26,34 +26,20 @@ const CameraSettings = ({
onSelect={(index) => setTabIndex(index)}
>
<TabList>
<Tab>Camera A</Tab>
<Tab>Camera B</Tab>
<Tab>Camera C</Tab>
{CAMERA_IDS.map((id) => (
<Tab key={id}>Camera {id}</Tab>
))}
</TabList>
<TabPanel>
<CameraPanel
tabIndex={tabIndex}
isResetAllModalOpen={isResetAllModalOpen}
handleClose={handleClose}
setIsResetModalOpen={setIsResetModalOpen}
/>
</TabPanel>
<TabPanel>
<CameraPanel
tabIndex={tabIndex}
isResetAllModalOpen={isResetAllModalOpen}
handleClose={handleClose}
setIsResetModalOpen={setIsResetModalOpen}
/>
</TabPanel>
<TabPanel>
<CameraPanel
tabIndex={tabIndex}
isResetAllModalOpen={isResetAllModalOpen}
handleClose={handleClose}
setIsResetModalOpen={setIsResetModalOpen}
/>
</TabPanel>
{CAMERA_IDS.map((id, index) => (
<TabPanel key={id}>
<CameraPanel
tabIndex={index}
isResetAllModalOpen={isResetAllModalOpen}
handleClose={handleClose}
setIsResetModalOpen={setIsResetModalOpen}
/>
</TabPanel>
))}
</Tabs>
</Card>
);

View File

@@ -4,17 +4,14 @@ import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext"
import { useColourDectection } from "../../hooks/useColourDetection";
import { useBlackBoard } from "../../../../hooks/useBlackBoard";
import { toast } from "sonner";
import {
useCameraFeedASocket,
useCameraFeedBSocket,
useCameraFeedCSocket,
} from "../../../../app/context/WebSocketContext";
import { useCameraFeedSocket } from "../../../../app/context/WebSocketContext";
import type { CameraID } from "../../../../app/config/cameraConfig";
type RegionSelectorProps = {
regions: Region[];
selectedRegionIndex: number;
mode: string;
cameraFeedID: "A" | "B" | "C";
cameraFeedID: CameraID;
isResetAllModalOpen: boolean;
handleClose: () => void;
setIsResetModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
@@ -33,26 +30,24 @@ const RegionSelector = ({
const { state, dispatch } = useCameraFeedContext();
const { blackboardMutation } = useBlackBoard();
const paintedCells = state.paintedCells[cameraFeedID];
const cameraASocket = useCameraFeedASocket();
const cameraBSocket = useCameraFeedBSocket();
const cameraCSocket = useCameraFeedCSocket();
const cameraSocket = useCameraFeedSocket();
const getCurrentSocket = () => {
switch (cameraFeedID) {
case "A":
return cameraASocket;
return cameraSocket;
case "B":
return cameraBSocket;
return cameraSocket;
case "C":
return cameraCSocket;
return cameraSocket;
}
};
const socket = getCurrentSocket();
const getMagnificationLevel = () => {
const test = socket.data;
if (!socket.data) return null;
const test = socket?.data;
if (!socket?.data) return null;
console.log(test);
if (!test || !test.magnificationLevel) return "1x";
return test?.magnificationLevel;

View File

@@ -1,10 +1,11 @@
import type { CameraID } from "../../../../../app/config/cameraConfig";
import { useCameraFeedContext } from "../../../../../app/context/CameraFeedContext";
import SliderComponent from "../../../../../ui/SliderComponent";
import { useCameraZoom } from "../../../hooks/useCameraZoom";
import { useDebouncedCallback } from "use-debounce";
type CameraControlsProps = {
cameraFeedID: "A" | "B" | "C";
cameraFeedID: CameraID;
};
const CameraControls = ({ cameraFeedID }: CameraControlsProps) => {

View File

@@ -3,13 +3,10 @@ import { Stage, Layer, Image, Shape } from "react-konva";
import type { KonvaEventObject } from "konva/lib/Node";
import { useCreateVideoSnapshot } from "../../hooks/useGetvideoSnapshots";
import { useCameraFeedContext } from "../../../../app/context/CameraFeedContext";
import {
useCameraFeedASocket,
useCameraFeedBSocket,
useCameraFeedCSocket,
} from "../../../../app/context/WebSocketContext";
import { useCameraFeedSocket } from "../../../../app/context/WebSocketContext";
import { ReadyState } from "react-use-websocket";
import { toast } from "sonner";
import type { CameraID } from "../../../../app/config/cameraConfig";
const BACKEND_WIDTH = 640;
const BACKEND_HEIGHT = 360;
@@ -41,22 +38,20 @@ const VideoFeedGridPainter = () => {
const currentScale = stageSize.width / BACKEND_WIDTH;
const size = BACKEND_CELL_SIZE * currentScale;
const cameraASocket = useCameraFeedASocket();
const cameraBSocket = useCameraFeedBSocket();
const cameraCSocket = useCameraFeedCSocket();
const cameraSocket = useCameraFeedSocket();
const getCurrentSocket = () => {
switch (cameraFeedID) {
case "A":
return cameraASocket;
return cameraSocket;
case "B":
return cameraBSocket;
return cameraSocket;
case "C":
return cameraCSocket;
return cameraSocket;
}
};
const handleZoomClick = (e: KonvaEventObject<MouseEvent>, cameraFeedID: "A" | "B" | "C") => {
const handleZoomClick = (e: KonvaEventObject<MouseEvent>, cameraFeedID: CameraID) => {
if (mode !== "zoom") return;
const socket = getCurrentSocket();
const stage = e.target.getStage();