Nadro/adhoc/system io machine (#6352)

* chore: saving off skeleton

* fix: saving skeleton

* chore: skeleton for loading projects from project directory path

* chore: cleaning up useless state transition to be an on event direct to action state

* fix: new structure for web vs desktop vs react machine provider code

* chore: saving off skeleton

* fix: skeleton logic for react? going to move it from a string to obj.string

* fix: trying to prevent error element unmount on global react components. This is bricking JS state

* fix: we are so back

* chore: implemented navigating to specfic KCL file

* chore: implementing renaming project

* chore: deleting project

* fix: auto fixes

* fix: old debug/testing file oops

* chore: generic create new file

* chore: skeleton for web create file provide

* chore: basic machine vitest... need to figure out how to get window.electron implemented in vitest?

* chore: save off progress before deleting other project implementation, a few missing features still

* chore: trying a different init skeleton? most likely will migrate

* chore: first attempt of purging projects context provider

* chore: enabling toast for some machine state

* chore: enabling more toast success and error

* chore: writing read write state to the system io based on the project path

* fix: tsc fixes

* fix: use file system watcher, navigate to project after creation via the requestProjectName

* chore: open project command, hooks vs snapshot context helpers

* chore: implemented open and create project for e2e testing. They are hard coded in poor spot for now.

* fix: codespell fixes

* chore: implementing more project commands

* chore: PR improvements for root.tsx

* chore: leaving comment about new Router.tsx layout

* fix: removing debugging code

* fix: rewriting component for readability

* fix: improving web initialization

* chore: implementing import file from url which is not actually that?

* fix: clearing search params on import file from url

* fix: fixed two e2e tests, forgot needsReview when making new command

* fix: fixing some import from url business logic to pass e2e tests

* chore: script for diffing circular deps +/-

* fix: formatting

* fix: massive fix for circular depsga!

* fix: trying to fix some errors and auto fmt

* fix: updating deps

* fix: removing debugging code

* fix: big clean up

* fix: more deletion

* fix: tsc cleanup

* fix: TSC TSC TSC TSC!

* fix: typo fix

* fix: clear query params on web only, desktop not required

* fix: removing unused code

* fmt

* Bring back `trap` removed in merge

* Use explicit types instead of `any`s on arg configs

* Add project commands directly to command palette

* fix: deleting debugging code, from PR review

* fix: this got added back(?)

* fix: using referred type

* fix: more PR clean up

* fix: big block comment for xstate architecture decision

* fix: more pr comment fixes

* fix: merge conflict just added them back why dude

* fix: more PR comments

* fix: big ciruclar deps fix, commandBarActor in appActor

---------

Co-authored-by: Frank Noirot <frankjohnson1993@gmail.com>
This commit is contained in:
Kevin Nadro
2025-04-24 13:32:49 -05:00
committed by GitHub
parent 95f2caacab
commit 305d613d40
93 changed files with 1704 additions and 1250 deletions

View File

@ -9,6 +9,26 @@ import { SceneEntities } from '@src/clientSideScene/sceneEntities'
import { SceneInfra } from '@src/clientSideScene/sceneInfra'
import type { BaseUnit } from '@src/lib/settings/settingsTypes'
import { useSelector } from '@xstate/react'
import type { SnapshotFrom } from 'xstate'
import { createActor, setup, assign } from 'xstate'
import { isDesktop } from '@src/lib/isDesktop'
import { createSettings } from '@src/lib/settings/initialSettings'
import { authMachine } from '@src/machines/authMachine'
import {
engineStreamContextCreate,
engineStreamMachine,
} from '@src/machines/engineStreamMachine'
import { ACTOR_IDS } from '@src/machines/machineConstants'
import { settingsMachine } from '@src/machines/settingsMachine'
import { systemIOMachineDesktop } from '@src/machines/systemIO/systemIOMachineDesktop'
import { systemIOMachineWeb } from '@src/machines/systemIO/systemIOMachineWeb'
import type { AppMachineContext } from '@src/lib/types'
import { createAuthCommands } from '@src/lib/commandBarConfigs/authCommandConfig'
import { commandBarMachine } from '@src/machines/commandBarMachine'
import { createProjectCommands } from '@src/lib/commandBarConfigs/projectsCommandConfig'
export const codeManager = new CodeManager()
export const engineCommandManager = new EngineCommandManager()
export const rustContext = new RustContext(engineCommandManager)
@ -90,3 +110,122 @@ if (typeof window !== 'undefined') {
},
})
}
const { AUTH, SETTINGS, SYSTEM_IO, ENGINE_STREAM, COMMAND_BAR } = ACTOR_IDS
const appMachineActors = {
[AUTH]: authMachine,
[SETTINGS]: settingsMachine,
[SYSTEM_IO]: isDesktop() ? systemIOMachineDesktop : systemIOMachineWeb,
[ENGINE_STREAM]: engineStreamMachine,
[COMMAND_BAR]: commandBarMachine,
} as const
const appMachine = setup({
types: {} as {
context: AppMachineContext
},
actors: appMachineActors,
}).createMachine({
id: 'modeling-app',
context: {
codeManager: codeManager,
kclManager: kclManager,
engineCommandManager: engineCommandManager,
sceneInfra: sceneInfra,
sceneEntitiesManager: sceneEntitiesManager,
},
entry: [
/**
* We originally wanted to use spawnChild but the inferred type blew up. The more children we
* created the type complexity went through the roof. This functionally should act the same.
* the system and parent internals are tracked properly. After reading the documentation
* it suggests either method but this method requires manual clean up as described in the gotcha
* comment block below. If this becomes an issue we can always move this spawn into createActor functions
* in javascript above and reference those directly but the system and parent internals within xstate
* will not work.
*/
assign({
// Gotcha, if you use spawn, make sure you remove the ActorRef from context
// to prevent memory leaks when the spawned actor is no longer needed
authActor: ({ spawn }) => spawn(AUTH, { id: AUTH, systemId: AUTH }),
settingsActor: ({ spawn }) =>
spawn(SETTINGS, {
id: SETTINGS,
systemId: SETTINGS,
input: createSettings(),
}),
systemIOActor: ({ spawn }) =>
spawn(SYSTEM_IO, { id: SYSTEM_IO, systemId: SYSTEM_IO }),
engineStreamActor: ({ spawn }) =>
spawn(ENGINE_STREAM, {
id: ENGINE_STREAM,
systemId: ENGINE_STREAM,
input: engineStreamContextCreate(),
}),
commandBarActor: ({ spawn }) =>
spawn(COMMAND_BAR, {
id: COMMAND_BAR,
systemId: COMMAND_BAR,
input: {
commands: [],
},
}),
}),
],
})
export const appActor = createActor(appMachine, {
systemId: 'root',
})
/**
* GOTCHA: the type coercion of this actor works because it is spawned for
* the lifetime of {appActor}, but would not work if it were invoked
* or if it were destroyed under any conditions during {appActor}'s life
*/
export const authActor = appActor.getSnapshot().context.authActor!
export const useAuthState = () => useSelector(authActor, (state) => state)
export const useToken = () =>
useSelector(authActor, (state) => state.context.token)
export const useUser = () =>
useSelector(authActor, (state) => state.context.user)
/**
* GOTCHA: the type coercion of this actor works because it is spawned for
* the lifetime of {appActor}, but would not work if it were invoked
* or if it were destroyed under any conditions during {appActor}'s life
*/
export const settingsActor = appActor.getSnapshot().context.settingsActor!
export const getSettings = () => {
const { currentProject: _, ...settings } = settingsActor.getSnapshot().context
return settings
}
export const useSettings = () =>
useSelector(settingsActor, (state) => {
// We have to peel everything that isn't settings off
const { currentProject, ...settings } = state.context
return settings
})
export const systemIOActor = appActor.getSnapshot().context.systemIOActor!
export const engineStreamActor =
appActor.getSnapshot().context.engineStreamActor!
export const commandBarActor = appActor.getSnapshot().context.commandBarActor!
const cmdBarStateSelector = (state: SnapshotFrom<typeof commandBarActor>) =>
state
export const useCommandBarState = () => {
return useSelector(commandBarActor, cmdBarStateSelector)
}
// Initialize global commands
commandBarActor.send({
type: 'Add commands',
data: {
commands: [
...createAuthCommands({ authActor }),
...createProjectCommands({ systemIOActor }),
],
},
})