All files / client/src/hooks useSimulatorPinControls.ts

100% Statements 29/29
87.5% Branches 7/8
100% Functions 8/8
100% Lines 27/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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                          14x   14x 2x             14x   3x 1x 1x       2x     2x 1x 1x 1x 1x         1x           14x   4x 1x 1x     3x     3x 2x 2x 2x 1x           1x   2x           14x          
import { useCallback, type Dispatch, type SetStateAction } from "react";
 
import type { ToastFn } from "@/hooks/use-toast";
import type { IncomingArduinoMessage } from "@/types/websocket";
import type { SimulationStatus } from "@/hooks/use-simulation-controls";
import type { PinState } from "@/hooks/use-simulation-store";
 
export function useSimulatorPinControls(params: {
  sendMessage: (message: IncomingArduinoMessage) => void;
  simulationStatus: SimulationStatus;
  toast: ToastFn;
  setPinStates: Dispatch<SetStateAction<PinState[]>>;
}) {
  const { sendMessage, simulationStatus, toast, setPinStates } = params;
 
  const showSimulationNotActiveToast = useCallback(() => {
    toast({
      title: "Simulation not active",
      description: "Start the simulation to change pin values.",
      variant: "destructive",
    });
  }, [toast]);
 
  const handlePinToggle = useCallback(
    (pin: number, newValue: number) => {
      if (simulationStatus === "stopped") {
        showSimulationNotActiveToast();
        return;
      }
 
      // Send the new pin value to the server
      sendMessage({ type: "set_pin_value", pin, value: newValue });
 
      // Update local pin state immediately for responsive UI
      setPinStates((prev) => {
        const newStates = [...prev];
        const existingIndex = newStates.findIndex((p) => p.pin === pin);
        Eif (existingIndex >= 0) {
          newStates[existingIndex] = {
            ...newStates[existingIndex],
            value: newValue,
          };
        }
        return newStates;
      });
    },
    [simulationStatus, sendMessage, setPinStates, showSimulationNotActiveToast],
  );
 
  const handleAnalogChange = useCallback(
    (pin: number, newValue: number) => {
      if (simulationStatus === "stopped") {
        showSimulationNotActiveToast();
        return;
      }
 
      sendMessage({ type: "set_pin_value", pin, value: newValue });
 
      // Update local pin state immediately for responsive UI
      setPinStates((prev) => {
        const newStates = [...prev];
        const existingIndex = newStates.findIndex((p) => p.pin === pin);
        if (existingIndex >= 0) {
          newStates[existingIndex] = {
            ...newStates[existingIndex],
            value: newValue,
            type: "analog",
          };
        } else {
          newStates.push({ pin, mode: "INPUT", value: newValue, type: "analog" });
        }
        return newStates;
      });
    },
    [simulationStatus, sendMessage, setPinStates, showSimulationNotActiveToast],
  );
 
  return {
    handlePinToggle,
    handleAnalogChange,
  };
}