93 lines
1.9 KiB
TypeScript
93 lines
1.9 KiB
TypeScript
import { useEffect, useReducer } from "react";
|
|
|
|
type State = {
|
|
autorunMode: boolean;
|
|
renderedCode: string;
|
|
isRunning: boolean;
|
|
executionId: number;
|
|
};
|
|
|
|
const buildInitialState = (code: string) => ({
|
|
autorunMode: true,
|
|
renderedCode: code,
|
|
isRunning: false,
|
|
executionId: 0,
|
|
});
|
|
|
|
type Action =
|
|
| {
|
|
type: "SET_AUTORUN_MODE";
|
|
value: boolean;
|
|
code: string;
|
|
}
|
|
| {
|
|
type: "PREPARE_RUN";
|
|
}
|
|
| {
|
|
type: "RUN";
|
|
code: string;
|
|
}
|
|
| {
|
|
type: "STOP_RUN";
|
|
};
|
|
|
|
const reducer = (state: State, action: Action): State => {
|
|
switch (action.type) {
|
|
case "SET_AUTORUN_MODE":
|
|
return {
|
|
...state,
|
|
autorunMode: action.value,
|
|
};
|
|
case "PREPARE_RUN":
|
|
return {
|
|
...state,
|
|
isRunning: true,
|
|
};
|
|
case "RUN":
|
|
return {
|
|
...state,
|
|
renderedCode: action.code,
|
|
executionId: state.executionId + 1,
|
|
};
|
|
case "STOP_RUN":
|
|
return {
|
|
...state,
|
|
isRunning: false,
|
|
};
|
|
}
|
|
};
|
|
|
|
export const useRunnerState = (code: string) => {
|
|
const [state, dispatch] = useReducer(reducer, buildInitialState(code));
|
|
|
|
useEffect(() => {
|
|
if (state.isRunning) {
|
|
if (state.renderedCode !== code) {
|
|
dispatch({ type: "RUN", code });
|
|
} else {
|
|
dispatch({ type: "STOP_RUN" });
|
|
}
|
|
}
|
|
}, [state.isRunning, state.renderedCode, code]);
|
|
|
|
const run = () => {
|
|
// The rest will be handled by dispatches above on following renders, but we need to update the spinner first.
|
|
dispatch({ type: "PREPARE_RUN" });
|
|
};
|
|
|
|
if (state.autorunMode && state.renderedCode !== code && !state.isRunning) {
|
|
run();
|
|
}
|
|
|
|
return {
|
|
run,
|
|
autorunMode: state.autorunMode,
|
|
renderedCode: state.renderedCode,
|
|
isRunning: state.isRunning,
|
|
executionId: state.executionId,
|
|
setAutorunMode: (newValue: boolean) => {
|
|
dispatch({ type: "SET_AUTORUN_MODE", value: newValue, code });
|
|
},
|
|
};
|
|
};
|