import { useEffect } from 'react' import { AnyStateMachine, InterpreterFrom, StateFrom } from 'xstate' import { createMachineCommand } from '../lib/createMachineCommand' import { useCommandsContext } from './useCommandsContext' import { modelingMachine } from 'machines/modelingMachine' import { authMachine } from 'machines/authMachine' import { settingsMachine } from 'machines/settingsMachine' import { homeMachine } from 'machines/homeMachine' import { Command, StateMachineCommandSetConfig, StateMachineCommandSetSchema, } from 'lib/commandTypes' import { useKclContext } from 'lang/KclProvider' import { useNetworkContext } from 'hooks/useNetworkContext' import { NetworkHealthState } from 'hooks/useNetworkStatus' import { useAppState } from 'AppState' // This might not be necessary, AnyStateMachine from xstate is working export type AllMachines = | typeof modelingMachine | typeof settingsMachine | typeof authMachine | typeof homeMachine interface UseStateMachineCommandsArgs< T extends AllMachines, S extends StateMachineCommandSetSchema > { machineId: T['id'] state: StateFrom send: Function actor: InterpreterFrom commandBarConfig?: StateMachineCommandSetConfig allCommandsRequireNetwork?: boolean onCancel?: () => void } export default function useStateMachineCommands< T extends AnyStateMachine, S extends StateMachineCommandSetSchema >({ machineId, state, send, actor, commandBarConfig, allCommandsRequireNetwork = false, onCancel, }: UseStateMachineCommandsArgs) { const { commandBarSend } = useCommandsContext() const { overallState } = useNetworkContext() const { isExecuting } = useKclContext() const { isStreamReady } = useAppState() useEffect(() => { const disableAllButtons = (overallState !== NetworkHealthState.Ok && overallState !== NetworkHealthState.Weak) || isExecuting || !isStreamReady const newCommands = state.nextEvents .filter((_) => !allCommandsRequireNetwork || !disableAllButtons) .filter((e) => !['done.', 'error.'].some((n) => e.includes(n))) .flatMap((type) => createMachineCommand({ // The group is the owner machine's ID. groupId: machineId, type, state, send, actor, commandBarConfig, onCancel, }) ) .filter((c) => c !== null) as Command[] // TS isn't smart enough to know this filter removes nulls commandBarSend({ type: 'Add commands', data: { commands: newCommands } }) return () => { commandBarSend({ type: 'Remove commands', data: { commands: newCommands }, }) } }, [state, overallState, isExecuting, isStreamReady]) }