diff --git a/pocs/xstate-study/app/Machine.tsx b/pocs/xstate-study/app/Machine.tsx index 94e1fdee1..e8c70eb6c 100644 --- a/pocs/xstate-study/app/Machine.tsx +++ b/pocs/xstate-study/app/Machine.tsx @@ -1,6 +1,6 @@ "use client"; import { memo } from "react"; -import makeOpenAppMachine from "./openAppStateMachine"; +import makeOpenAppMachine, { Context } from "./openAppStateMachine"; import { createActor } from "xstate"; import { createBrowserInspector } from "@statelyai/inspect"; @@ -22,8 +22,22 @@ function Machine() { }, }); + let previousUserActionNeeded: Context["userActionNeeded"] = null; + let previousStateValue: string | null = null; + openAppMachineActor.start(); openAppMachineActor.subscribe((state) => { + if (state.value !== previousStateValue) { + console.log("machine: new state", state.value); + previousStateValue = state.value; + } + if (state.context.userActionNeeded !== previousUserActionNeeded) { + console.log( + "machine: user action needed", + state.context.userActionNeeded + ); + previousUserActionNeeded = state.context.userActionNeeded; + } if (state.status === "done") { console.log("machine: done", state); console.log("machine output:", state.output); diff --git a/pocs/xstate-study/app/openAppStateMachine.ts b/pocs/xstate-study/app/openAppStateMachine.ts index ed0598c45..c416a8fdf 100644 --- a/pocs/xstate-study/app/openAppStateMachine.ts +++ b/pocs/xstate-study/app/openAppStateMachine.ts @@ -1,21 +1,6 @@ import { setup, fromPromise, assign, log } from "xstate"; -type DeviceSessionState = { - status: "Ready" | "Busy" | "Locked" | "NotConnected", - deviceOnboarded: boolean, -}; - -type Input = { - requestedAppName: string, - deviceSessionState: DeviceSessionState, -} - -type Context = Input & { - currentlyRunningApp: string | null; - error: Error | null; -} - export const LOCKED_DEVICE_ERROR = "Locked device"; export const APP_NOT_FOUND_ERROR = "App not installed"; export const OPEN_REJECTED_ERROR = "Open app rejected"; @@ -47,6 +32,22 @@ async function openAppStub(appName: string) { return; } +type DeviceSessionState = { + status: "Ready" | "Busy" | "Locked" | "NotConnected", + deviceOnboarded: boolean, +}; + +type Input = { + requestedAppName: string, + deviceSessionState: DeviceSessionState, +} + +export type Context = Input & { + currentlyRunningApp: string | null; + error: Error | null; + userActionNeeded: "OpenApp" | null; +} + function makeOpenAppMachine(params: { getAppAndVersion: () => Promise<{ app: string, version: string }>, closeApp: () => Promise, @@ -81,10 +82,12 @@ function makeOpenAppMachine(params: { }, actions: { assignErrorDeviceNotOnboarded: assign({error: new Error(DEVICE_NOT_ONBOARDED_ERROR)}), - assignErrorDeviceLocked: assign({error: new Error(LOCKED_DEVICE_ERROR)}) + assignErrorDeviceLocked: assign({error: new Error(LOCKED_DEVICE_ERROR)}), + assignUserActionNeededOpenApp: assign({userActionNeeded: "OpenApp"}), + assignNoUserActionNeeded: assign({userActionNeeded: null}), }, }).createMachine({ - /** @xstate-layout N4IgpgJg5mDOIC5QHkAOYB2BBVqAiYAbgJYDGYWpALsQPYYB0BJ5ASmAIYQCeAxANoAGALqJQqWrGI16YkAA9EAdgCMDAGyCVAVm3qAzAA4AnNq3bDAGhDdEKgCyGGpw4OMAmffbP37xgL7+1miYOPhEZBTUdIzIGABGtBwAThDEGFAAwgAWYKQA1gIichJSMhhyiggqggzugvbq2qr6Su7aKvr6Kta2CO5tGu7GhvrDKq4jxvaBwejYuMyRlOUMcYkpaRk5eYX8KqJIIKXSMZWI7uruDIYqKu53FtrGbYb2vRd+zg1vDuo67kasxAIQW4RYUVWABlaAV0llcgUiodxJJTrIjlUdAx7IJ9II2vj2ipjHjtB8EPpSTdLqY3B0Bn4lMDQWEluQVjEGDC4dtEXsDiU0eVzv0rjdtK1cQZLrjTBT9OonDUSZozAN7u0WfM2REOdF6AwwgAbMgccpYQgcYjGjjxY1gXgQehgBjpQi0fKu1mLPWQrkms0Wq02u0OhDu2HmmJCYSxoVlM6Y5QMQQPQzqdTGToWLOCck2RBNJQMZ4EwQNfNKSX6bWhX0QzmGwOkaP0S3W232x1gZLJWjJBioW1UABmA4AtmsdQ3lgbGC229gQ13w5HW+VY-GjicRcmxdpU117F5DO4TJLdBTLwx7lnGhX6mMVHWwez-c3cKaNzEdkjt6iiYYqAVT6N8xhGNWbSSpmKjqBShiSremiuPe7SNMyQQgjO4Jzqsi7lH+AooscwpJiBFxKGBSj2CqTSZvYwzwYWCCIWBcGCBmJLdKocGvrqjbzkwHCwNkGypERyIJuiFT7sSDBjDWEznlR7QUjUgjqBoHRKBB0pqgEWE+rh+qrHgIliUkEn8gIgo7mRwEKIgZiHppowTBB1aTOpFZaU0KhUb8NG4oY-GzqZXKZMakgUF+QYxE6LpuhgHpetO9YmR+jBRTFBExBGKVRpuIgAaRQGyRRCCOE4VIPEqtGKh5BZ9HcJgMKoHQVi0GYnmFmVNtl0WwLFw7xfQvC9v2g7Dua47JFOxnvgNDA5cNeX0AVHo-vQW7FPZ5Wiq8pZKpxSoTHiEw+f87U6F0hi6Xo1a1kZOFLUJxnfkuiUYK6kZpYtfrLR9Y0YJtRUxiVe2ATJooDNcgKaYxiqIfdSjqbi1z3HcF09SeMwvRlb2rMD20YBNfYDkOI5zQtr2A+9OGfeUYOk7tJG7uRTlVWeN2mKSJ5w2e6ndGBvi6BBhiuH46h9UTAZxaT7BcHwpUc45VSqBo5j2ISkvNMYzEtZoJbtEoNE5sYBu9cCGC0BAcByADgl7tDLtcwAtNo9jtXi9QZuouI1No7jqRo6iqAbRioRpnGy-TZl+krPDSW7VSMQhThKJopjB887gPC8cfO1y6xWVsCK7CnnNVJ4OJvF4xucW80wUg88O3M03gPBWzRF3hXI8vk8JEVX6uIK0paefougXhMaMsV0tQDNmNFGEqSqhQTb7x-Lo2kx2obdqPFUe1pSi+6dAdaPml0sZK1xvJLmmeGb+LPXMhM75+e9LiP+0w3Jb2HhJjnlaAYXS+YKRKFcDcNM-xWjnwmAFPuEVDTmVEuJCAf9XbVwuOKK4WZVCAg8kLFi0w1BUS9lRAw09TDv2wp-YuhpVojSZpzNWJ806jHaq0A2VszBtAGD5QYGZ84PGPG4LUW8BL90NCTJcx9YYWFLDoPQ4dSSWy0OpYY7F7gVgJK4LqmEP7byYQuBWS4k59BwWPfoh5g5eA6G8QE09pTqV0LUUwVFOJmwMFcfGJiZGoMYAAZQAK6kHILAeA-9U6IFxGHaUjFJaZmeO8FicEA51DuqoNoaZ8woKygwAAohTZIij9ykhLGmcYWZQFaGMOpBi2TeEdDuN0EYgRAhAA */ + /** @xstate-layout N4IgpgJg5mDOIC5QHkAOYB2BBVqAiYAbgJYDGYWpALsQPYYB0BJ5ASmAIYQCeAxANoAGALqJQqWrGI16YkAA9EAdgCMDAGyCVAVm3qAzAA4AnNq3bDAGhDdEKgCyGGpw4OMAmffbP37xgL7+1miYOPhEZBTUdIzIGABGtBwAThDEGFAAwgAWYKQA1gIichJSMhhyiggqggzugvbq2qr6Su7aKvr6Kta2CO5tGu7GhvrDKq4jxvaBwejYuMyRlOUMcYkpaRk5eYX8KqJIIKXSMZWI7uruDIYqKu53FtrGbYb2vRd+zg1vDuo67kasxAIQW4RYUVWABlaAV0llcgUiodxJJTrIjlUdAx7IJ9II2vj2ipjHjtB8EPpSTdLqY3B0Bn4lMDQWEluQVjEGDC4dtEXsDiU0eVzv0rjdtK1cQZLrjTBT9OonDUSZozAN7u0WfM2REOdF6AwwgAbMgccpYQgcYjGjjxY1gXgQehgBjpQi0fKu1mLPWQrkms0Wq02u0OhDu2HmmJCYSxoVlM6Y5QMQQPQzqdTGToWLOCck2RBNJQMZ4EwQNfNKSX6bWhX0QzmGwOkaP0S3W232x1gZLJWjJBioW1UABmA4AtmsdQ3lgbGC229gQ13w5HW+VY-GjicRcmxdpU117F5DO4TJLdBTLwx7lnGhX6mMVHWwez-c3cKaNzEdkjt6iiYYqAVT6N8xhGNWbSSpmKjqBShiSremiuPe7SNMyQQgjO4Jzqsi7lH+AooscwpJiBFxKGBSj2CqTSZvYwzwYWCCIWBcGCBmJLdKocGvrqjbzkwHCwNkGypERyIJuiFT7sSDBjDWEznlR7QUjUgjqBoHRKBB0pqgEWE+rh+qrHgIliUkEn8gIgo7mRwEKIgZiHppowTBB1aTOpFZaU0KhUb8NG4oY-GzqZXKZMakgUF+QYxE6LpuhgHpetO9YmR+jBRTFBExBGKVRpuIgAaRQGyRRCCOE4VIPEqtGKh5BZ9HcJgMKoHQVi0GYnmFmVNtl0WwLFw7xfQvC9v2g7Dua47JFOxnvgNDA5cNeX0AVHo-vQW7FPZ5Wiq8pZKpxSoTHiEw+f87U6F0hi6Xo1a1kZOFLUJxnfkuiUYK6kZpYtfrLR9Y0YJtRUxiVe2ATJooDNczzQaoEH3G06nePYClqnodxGAYL4vRlb2rMD20YBNfYDkOI5zQtr2A+9OGfeUYOk7tJG7uRTkIP8GOcYxiEElmJhWCxnT3HUwwNAZShXDMBNvvT+FxaT7BcHwpUc45VSqBo5j2IShiIbpzEtZoJbtEoNE5sYxjqL1wIYLQEBwHIAOCXu0Me1zAC02gY0oeL1BmdtaPm7jqRo6iqNWfjngMzzqH1RNcu+qs8NJXtVIxCFODL9LaO0HgPC8SeK1y6xWVsCK7BnnNVJ4OJvF4ZucW80wUg81znjoNEFxpzSl+7XI8vk8JEbXWuIK0paefougXhMSgKvidS6QFJ4ZpvoXywJeEBsrS4dqG3YTxVPtaQHYynSHNQdCLfSStcbyG5pniW-iz1zITZefqNpPj-tGGckMYeEmOeVoBhdL5gpEoVwNw0z-FaAHCYAVB570NOZUS4kIAAM9nXC44orhZlUICDyZ4KTTDUFRP2VEDBz1MJ-bC38h6GlWiNJmnNNZnyzqMdqrRba228ASdwAwfKDAzCIh4x43Bah3uFLK6UwQcMclw2GFhSw6D0FHUkNstDqWGOxe4FYCSuC6phL+CsWELgPuUNOfQ8GT36IeAuXg76MRPH7TS6ldC1FMFRTilsDCyzQRFQ0ABlAArqQcgsB4CAMzogXEkdpT82Ds8d4osGJ1DutHeo9RtAhIUQAUQpskU+opSQljTOMLM4CtDGHUlkzw-COg4xJNvQIQA */ id: "OpenAppDeviceAction", initial: "DeviceReady", context: ({input}): Context => { @@ -92,6 +95,7 @@ function makeOpenAppMachine(params: { ...input, currentlyRunningApp: null, error: null, + userActionNeeded: null, } }, states: { @@ -176,6 +180,8 @@ function makeOpenAppMachine(params: { }, OpenApplication: { // execute openApp command, + entry: "assignUserActionNeededOpenApp", + exit: "assignNoUserActionNeeded", invoke: { src: "openApp", input: ({context}) => ({appName: context.requestedAppName}),