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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 13x 13x 11x 1x 1x 13x 1x 1x 1x 1x 13x 1x 1x 13x 1x 1x 1x 1x 1x 1x 13x 1x 2x 2x 13x 5x 3x 13x | import { useCallback, useEffect, useState } from "react";
import type { OutputTab } from "@/types/compilation.types";
import type { ServerStatusEventData } from "@/types/external-api";
import type { IncomingArduinoMessage } from "@/types/websocket";
import type { SimulationStatus } from "@shared/types/arduino.types";
import {
emitServerStatusEvent,
emitSimulationStateEvent,
useExternalApi,
} from "./use-external-api";
type StateSetter<T> = (value: T | ((previous: T) => T)) => void;
type InternalServerStatus = Pick<ServerStatusEventData, "sandboxRunners" | "compileSlots">;
interface UseSimulatorExternalControlParams {
allowedOrigin: string;
backendReachable: boolean;
isConnected: boolean;
compileAndStartAction: () => void;
handleStop: () => void;
handlePause: () => void;
handleResume: () => void;
setCode: (code: string) => void;
setSimulationStatus: StateSetter<SimulationStatus>;
sendMessage: (message: IncomingArduinoMessage) => void;
pinStates: Array<{ pin: number; value?: number }>;
handleSerialSend: (data: string) => void;
setSimulationTimeout: (timeout: number) => void;
setActiveOutputTab: (tab: OutputTab) => void;
simulationStatus: SimulationStatus;
compilationStatus: string;
serverStatus: InternalServerStatus | null;
}
export function useSimulatorExternalControl(
params: UseSimulatorExternalControlParams,
): { pendingExternalStart: boolean } {
const [pendingExternalStart, setPendingExternalStart] = useState(false);
useEffect(() => {
if (pendingExternalStart && params.isConnected && params.backendReachable) {
setPendingExternalStart(false);
params.compileAndStartAction();
}
}, [
pendingExternalStart,
params.isConnected,
params.backendReachable,
params.compileAndStartAction,
]);
const handleExternalStartSimulation = useCallback(() => {
Iif (params.isConnected && params.backendReachable) {
params.compileAndStartAction();
} else {
setPendingExternalStart(true);
params.setSimulationStatus("queued");
emitSimulationStateEvent("QUEUED_FOR_COMPILING");
}
}, [params]);
const handleExternalStopSimulation = useCallback(() => {
setPendingExternalStart(false);
params.handleStop();
}, [params]);
const deriveClientState = useCallback((): string => {
Iif (pendingExternalStart) return "QUEUED_FOR_COMPILING";
Iif (params.compilationStatus === "compiling") return "COMPILING";
Iif (params.simulationStatus === "queued") return "QUEUED_FOR_SIMULATION";
Iif (params.simulationStatus === "running") return "RUNNING";
Iif (params.simulationStatus === "paused") return "PAUSED";
return "IDLE";
}, [pendingExternalStart, params.compilationStatus, params.simulationStatus]);
useExternalApi({
allowedOrigin: params.allowedOrigin,
onLoadCode: params.setCode,
onStartSimulation: handleExternalStartSimulation,
onStopSimulation: handleExternalStopSimulation,
onPauseSimulation: params.handlePause,
onResumeSimulation: params.handleResume,
onSetPinState: (pin, value) => {
params.sendMessage({ type: "set_pin_value", pin, value });
},
getPinState: (pin) => {
const found = params.pinStates.find((pinState) => pinState.pin === pin);
return found?.value ?? 0;
},
onSerialInput: params.handleSerialSend,
onSetSimulationTimeout: params.setSimulationTimeout,
onSetOutputTab: params.setActiveOutputTab,
getSimulationState: deriveClientState,
getServerStatus: () => params.serverStatus && {
serverReachable: params.backendReachable,
sandboxRunners: params.serverStatus.sandboxRunners,
compileSlots: params.serverStatus.compileSlots,
},
});
useEffect(() => {
if (!params.serverStatus) return;
emitServerStatusEvent({
serverReachable: params.backendReachable,
sandboxRunners: params.serverStatus.sandboxRunners,
compileSlots: params.serverStatus.compileSlots,
});
}, [params.serverStatus, params.backendReachable, emitServerStatusEvent]);
return { pendingExternalStart };
} |