Move app.tsx effects (#513)
* move useSetupEngineManager * move code eval * add comment
This commit is contained in:
192
src/App.tsx
192
src/App.tsx
@ -1,13 +1,6 @@
|
|||||||
import {
|
import { useRef, useEffect, useCallback, MouseEventHandler } from 'react'
|
||||||
useRef,
|
|
||||||
useEffect,
|
|
||||||
useLayoutEffect,
|
|
||||||
useCallback,
|
|
||||||
MouseEventHandler,
|
|
||||||
} from 'react'
|
|
||||||
import { DebugPanel } from './components/DebugPanel'
|
import { DebugPanel } from './components/DebugPanel'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { asyncParser } from './lang/abstractSyntaxTree'
|
|
||||||
import { _executor } from './lang/executor'
|
import { _executor } from './lang/executor'
|
||||||
import { PaneType, useStore } from './useStore'
|
import { PaneType, useStore } from './useStore'
|
||||||
import { Logs, KCLErrors } from './components/Logs'
|
import { Logs, KCLErrors } from './components/Logs'
|
||||||
@ -16,13 +9,9 @@ import { MemoryPanel } from './components/MemoryPanel'
|
|||||||
import { useHotKeyListener } from './hooks/useHotKeyListener'
|
import { useHotKeyListener } from './hooks/useHotKeyListener'
|
||||||
import { Stream } from './components/Stream'
|
import { Stream } from './components/Stream'
|
||||||
import ModalContainer from 'react-modal-promise'
|
import ModalContainer from 'react-modal-promise'
|
||||||
import {
|
import { EngineCommand } from './lang/std/engineConnection'
|
||||||
EngineCommand,
|
|
||||||
EngineCommandManager,
|
|
||||||
} from './lang/std/engineConnection'
|
|
||||||
import { throttle } from './lib/utils'
|
import { throttle } from './lib/utils'
|
||||||
import { AppHeader } from './components/AppHeader'
|
import { AppHeader } from './components/AppHeader'
|
||||||
import { KCLError } from './lang/errors'
|
|
||||||
import { Resizable } from 're-resizable'
|
import { Resizable } from 're-resizable'
|
||||||
import {
|
import {
|
||||||
faCode,
|
faCode,
|
||||||
@ -41,6 +30,8 @@ import { CameraDragInteractionType_type } from '@kittycad/lib/dist/types/src/mod
|
|||||||
import { CodeMenu } from 'components/CodeMenu'
|
import { CodeMenu } from 'components/CodeMenu'
|
||||||
import { TextEditor } from 'components/TextEditor'
|
import { TextEditor } from 'components/TextEditor'
|
||||||
import { Themes, getSystemTheme } from 'lib/theme'
|
import { Themes, getSystemTheme } from 'lib/theme'
|
||||||
|
import { useSetupEngineManager } from 'hooks/useSetupEngineManager'
|
||||||
|
import { useCodeEval } from 'hooks/useCodeEval'
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
const { code: loadedCode, project } = useLoaderData() as IndexLoaderData
|
const { code: loadedCode, project } = useLoaderData() as IndexLoaderData
|
||||||
@ -48,59 +39,23 @@ export function App() {
|
|||||||
const streamRef = useRef<HTMLDivElement>(null)
|
const streamRef = useRef<HTMLDivElement>(null)
|
||||||
useHotKeyListener()
|
useHotKeyListener()
|
||||||
const {
|
const {
|
||||||
addLog,
|
|
||||||
addKCLError,
|
|
||||||
setCode,
|
setCode,
|
||||||
setAst,
|
|
||||||
setError,
|
|
||||||
setProgramMemory,
|
|
||||||
resetLogs,
|
|
||||||
resetKCLErrors,
|
|
||||||
setArtifactMap,
|
|
||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
setEngineCommandManager,
|
|
||||||
highlightRange,
|
|
||||||
setHighlightRange,
|
|
||||||
setCursor2,
|
|
||||||
setMediaStream,
|
|
||||||
setIsStreamReady,
|
|
||||||
isStreamReady,
|
|
||||||
buttonDownInStream,
|
buttonDownInStream,
|
||||||
openPanes,
|
openPanes,
|
||||||
setOpenPanes,
|
setOpenPanes,
|
||||||
didDragInStream,
|
didDragInStream,
|
||||||
setStreamDimensions,
|
|
||||||
streamDimensions,
|
streamDimensions,
|
||||||
setIsExecuting,
|
|
||||||
defferedCode,
|
|
||||||
guiMode,
|
guiMode,
|
||||||
} = useStore((s) => ({
|
} = useStore((s) => ({
|
||||||
guiMode: s.guiMode,
|
guiMode: s.guiMode,
|
||||||
addLog: s.addLog,
|
|
||||||
defferedCode: s.defferedCode,
|
|
||||||
setCode: s.setCode,
|
setCode: s.setCode,
|
||||||
setAst: s.setAst,
|
|
||||||
setError: s.setError,
|
|
||||||
setProgramMemory: s.setProgramMemory,
|
|
||||||
resetLogs: s.resetLogs,
|
|
||||||
resetKCLErrors: s.resetKCLErrors,
|
|
||||||
setArtifactMap: s.setArtifactNSourceRangeMaps,
|
|
||||||
engineCommandManager: s.engineCommandManager,
|
engineCommandManager: s.engineCommandManager,
|
||||||
setEngineCommandManager: s.setEngineCommandManager,
|
|
||||||
highlightRange: s.highlightRange,
|
|
||||||
setHighlightRange: s.setHighlightRange,
|
|
||||||
setCursor2: s.setCursor2,
|
|
||||||
setMediaStream: s.setMediaStream,
|
|
||||||
isStreamReady: s.isStreamReady,
|
|
||||||
setIsStreamReady: s.setIsStreamReady,
|
|
||||||
buttonDownInStream: s.buttonDownInStream,
|
buttonDownInStream: s.buttonDownInStream,
|
||||||
addKCLError: s.addKCLError,
|
|
||||||
openPanes: s.openPanes,
|
openPanes: s.openPanes,
|
||||||
setOpenPanes: s.setOpenPanes,
|
setOpenPanes: s.setOpenPanes,
|
||||||
didDragInStream: s.didDragInStream,
|
didDragInStream: s.didDragInStream,
|
||||||
setStreamDimensions: s.setStreamDimensions,
|
|
||||||
streamDimensions: s.streamDimensions,
|
streamDimensions: s.streamDimensions,
|
||||||
setIsExecuting: s.setIsExecuting,
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -149,143 +104,8 @@ export function App() {
|
|||||||
}
|
}
|
||||||
}, [loadedCode, setCode])
|
}, [loadedCode, setCode])
|
||||||
|
|
||||||
const streamWidth = streamRef?.current?.offsetWidth
|
useSetupEngineManager(streamRef, token)
|
||||||
const streamHeight = streamRef?.current?.offsetHeight
|
useCodeEval()
|
||||||
|
|
||||||
const width = streamWidth ? streamWidth : 0
|
|
||||||
const quadWidth = Math.round(width / 4) * 4
|
|
||||||
const height = streamHeight ? streamHeight : 0
|
|
||||||
const quadHeight = Math.round(height / 4) * 4
|
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
setStreamDimensions({
|
|
||||||
streamWidth: quadWidth,
|
|
||||||
streamHeight: quadHeight,
|
|
||||||
})
|
|
||||||
if (!width || !height) return
|
|
||||||
const eng = new EngineCommandManager({
|
|
||||||
setMediaStream,
|
|
||||||
setIsStreamReady,
|
|
||||||
width: quadWidth,
|
|
||||||
height: quadHeight,
|
|
||||||
token,
|
|
||||||
})
|
|
||||||
setEngineCommandManager(eng)
|
|
||||||
return () => {
|
|
||||||
eng?.tearDown()
|
|
||||||
}
|
|
||||||
}, [quadWidth, quadHeight])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isStreamReady) return
|
|
||||||
if (!engineCommandManager) return
|
|
||||||
let unsubFn: any[] = []
|
|
||||||
const asyncWrap = async () => {
|
|
||||||
try {
|
|
||||||
if (!defferedCode) {
|
|
||||||
setAst({
|
|
||||||
start: 0,
|
|
||||||
end: 0,
|
|
||||||
body: [],
|
|
||||||
nonCodeMeta: {
|
|
||||||
noneCodeNodes: {},
|
|
||||||
start: null,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
setProgramMemory({ root: {}, return: null })
|
|
||||||
engineCommandManager.endSession()
|
|
||||||
engineCommandManager.startNewSession()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const _ast = await asyncParser(defferedCode)
|
|
||||||
setAst(_ast)
|
|
||||||
resetLogs()
|
|
||||||
resetKCLErrors()
|
|
||||||
engineCommandManager.endSession()
|
|
||||||
engineCommandManager.startNewSession()
|
|
||||||
setIsExecuting(true)
|
|
||||||
const programMemory = await _executor(
|
|
||||||
_ast,
|
|
||||||
{
|
|
||||||
root: {
|
|
||||||
_0: {
|
|
||||||
type: 'UserVal',
|
|
||||||
value: 0,
|
|
||||||
__meta: [],
|
|
||||||
},
|
|
||||||
_90: {
|
|
||||||
type: 'UserVal',
|
|
||||||
value: 90,
|
|
||||||
__meta: [],
|
|
||||||
},
|
|
||||||
_180: {
|
|
||||||
type: 'UserVal',
|
|
||||||
value: 180,
|
|
||||||
__meta: [],
|
|
||||||
},
|
|
||||||
_270: {
|
|
||||||
type: 'UserVal',
|
|
||||||
value: 270,
|
|
||||||
__meta: [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
return: null,
|
|
||||||
},
|
|
||||||
engineCommandManager
|
|
||||||
)
|
|
||||||
|
|
||||||
const { artifactMap, sourceRangeMap } =
|
|
||||||
await engineCommandManager.waitForAllCommands()
|
|
||||||
setIsExecuting(false)
|
|
||||||
if (programMemory !== undefined) {
|
|
||||||
setProgramMemory(programMemory)
|
|
||||||
}
|
|
||||||
|
|
||||||
setArtifactMap({ artifactMap, sourceRangeMap })
|
|
||||||
const unSubHover = engineCommandManager.subscribeToUnreliable({
|
|
||||||
event: 'highlight_set_entity',
|
|
||||||
callback: ({ data }) => {
|
|
||||||
if (data?.entity_id) {
|
|
||||||
const sourceRange = sourceRangeMap[data.entity_id]
|
|
||||||
setHighlightRange(sourceRange)
|
|
||||||
} else if (
|
|
||||||
!highlightRange ||
|
|
||||||
(highlightRange[0] !== 0 && highlightRange[1] !== 0)
|
|
||||||
) {
|
|
||||||
setHighlightRange([0, 0])
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const unSubClick = engineCommandManager.subscribeTo({
|
|
||||||
event: 'select_with_point',
|
|
||||||
callback: ({ data }) => {
|
|
||||||
if (!data?.entity_id) {
|
|
||||||
setCursor2()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const sourceRange = sourceRangeMap[data.entity_id]
|
|
||||||
setCursor2({ range: sourceRange, type: 'default' })
|
|
||||||
},
|
|
||||||
})
|
|
||||||
unsubFn.push(unSubHover, unSubClick)
|
|
||||||
|
|
||||||
setError()
|
|
||||||
} catch (e: any) {
|
|
||||||
setIsExecuting(false)
|
|
||||||
if (e instanceof KCLError) {
|
|
||||||
addKCLError(e)
|
|
||||||
} else {
|
|
||||||
setError('problem')
|
|
||||||
console.log(e)
|
|
||||||
addLog(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
asyncWrap()
|
|
||||||
return () => {
|
|
||||||
unsubFn.forEach((fn) => fn())
|
|
||||||
}
|
|
||||||
}, [defferedCode, isStreamReady, engineCommandManager])
|
|
||||||
|
|
||||||
const debounceSocketSend = throttle<EngineCommand>((message) => {
|
const debounceSocketSend = throttle<EngineCommand>((message) => {
|
||||||
engineCommandManager?.sendSceneCommand(message)
|
engineCommandManager?.sendSceneCommand(message)
|
||||||
|
156
src/hooks/useCodeEval.ts
Normal file
156
src/hooks/useCodeEval.ts
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import { useEffect } from 'react'
|
||||||
|
import { asyncParser } from '../lang/abstractSyntaxTree'
|
||||||
|
import { _executor } from '../lang/executor'
|
||||||
|
import { useStore } from '../useStore'
|
||||||
|
import { KCLError } from '../lang/errors'
|
||||||
|
|
||||||
|
// This recently moved out of app.tsx
|
||||||
|
// and is our old way of thinking that whenever the code changes we need to re-execute, instead of
|
||||||
|
// being more decisive about when and where we execute, its likey this custom hook will be
|
||||||
|
// refactored away entirely at some point
|
||||||
|
|
||||||
|
export function useCodeEval() {
|
||||||
|
const {
|
||||||
|
addLog,
|
||||||
|
addKCLError,
|
||||||
|
setAst,
|
||||||
|
setError,
|
||||||
|
setProgramMemory,
|
||||||
|
resetLogs,
|
||||||
|
resetKCLErrors,
|
||||||
|
setArtifactMap,
|
||||||
|
engineCommandManager,
|
||||||
|
highlightRange,
|
||||||
|
setHighlightRange,
|
||||||
|
setCursor2,
|
||||||
|
isStreamReady,
|
||||||
|
setIsExecuting,
|
||||||
|
defferedCode,
|
||||||
|
} = useStore((s) => ({
|
||||||
|
addLog: s.addLog,
|
||||||
|
defferedCode: s.defferedCode,
|
||||||
|
setAst: s.setAst,
|
||||||
|
setError: s.setError,
|
||||||
|
setProgramMemory: s.setProgramMemory,
|
||||||
|
resetLogs: s.resetLogs,
|
||||||
|
resetKCLErrors: s.resetKCLErrors,
|
||||||
|
setArtifactMap: s.setArtifactNSourceRangeMaps,
|
||||||
|
engineCommandManager: s.engineCommandManager,
|
||||||
|
highlightRange: s.highlightRange,
|
||||||
|
setHighlightRange: s.setHighlightRange,
|
||||||
|
setCursor2: s.setCursor2,
|
||||||
|
isStreamReady: s.isStreamReady,
|
||||||
|
addKCLError: s.addKCLError,
|
||||||
|
setIsExecuting: s.setIsExecuting,
|
||||||
|
}))
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isStreamReady) return
|
||||||
|
if (!engineCommandManager) return
|
||||||
|
let unsubFn: any[] = []
|
||||||
|
const asyncWrap = async () => {
|
||||||
|
try {
|
||||||
|
if (!defferedCode) {
|
||||||
|
setAst({
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
body: [],
|
||||||
|
nonCodeMeta: {
|
||||||
|
noneCodeNodes: {},
|
||||||
|
start: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
setProgramMemory({ root: {}, return: null })
|
||||||
|
engineCommandManager.endSession()
|
||||||
|
engineCommandManager.startNewSession()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const _ast = await asyncParser(defferedCode)
|
||||||
|
setAst(_ast)
|
||||||
|
resetLogs()
|
||||||
|
resetKCLErrors()
|
||||||
|
engineCommandManager.endSession()
|
||||||
|
engineCommandManager.startNewSession()
|
||||||
|
setIsExecuting(true)
|
||||||
|
const programMemory = await _executor(
|
||||||
|
_ast,
|
||||||
|
{
|
||||||
|
root: {
|
||||||
|
_0: {
|
||||||
|
type: 'UserVal',
|
||||||
|
value: 0,
|
||||||
|
__meta: [],
|
||||||
|
},
|
||||||
|
_90: {
|
||||||
|
type: 'UserVal',
|
||||||
|
value: 90,
|
||||||
|
__meta: [],
|
||||||
|
},
|
||||||
|
_180: {
|
||||||
|
type: 'UserVal',
|
||||||
|
value: 180,
|
||||||
|
__meta: [],
|
||||||
|
},
|
||||||
|
_270: {
|
||||||
|
type: 'UserVal',
|
||||||
|
value: 270,
|
||||||
|
__meta: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
return: null,
|
||||||
|
},
|
||||||
|
engineCommandManager
|
||||||
|
)
|
||||||
|
|
||||||
|
const { artifactMap, sourceRangeMap } =
|
||||||
|
await engineCommandManager.waitForAllCommands()
|
||||||
|
setIsExecuting(false)
|
||||||
|
if (programMemory !== undefined) {
|
||||||
|
setProgramMemory(programMemory)
|
||||||
|
}
|
||||||
|
|
||||||
|
setArtifactMap({ artifactMap, sourceRangeMap })
|
||||||
|
const unSubHover = engineCommandManager.subscribeToUnreliable({
|
||||||
|
event: 'highlight_set_entity',
|
||||||
|
callback: ({ data }) => {
|
||||||
|
if (data?.entity_id) {
|
||||||
|
const sourceRange = sourceRangeMap[data.entity_id]
|
||||||
|
setHighlightRange(sourceRange)
|
||||||
|
} else if (
|
||||||
|
!highlightRange ||
|
||||||
|
(highlightRange[0] !== 0 && highlightRange[1] !== 0)
|
||||||
|
) {
|
||||||
|
setHighlightRange([0, 0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const unSubClick = engineCommandManager.subscribeTo({
|
||||||
|
event: 'select_with_point',
|
||||||
|
callback: ({ data }) => {
|
||||||
|
if (!data?.entity_id) {
|
||||||
|
setCursor2()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const sourceRange = sourceRangeMap[data.entity_id]
|
||||||
|
setCursor2({ range: sourceRange, type: 'default' })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
unsubFn.push(unSubHover, unSubClick)
|
||||||
|
|
||||||
|
setError()
|
||||||
|
} catch (e: any) {
|
||||||
|
setIsExecuting(false)
|
||||||
|
if (e instanceof KCLError) {
|
||||||
|
addKCLError(e)
|
||||||
|
} else {
|
||||||
|
setError('problem')
|
||||||
|
console.log(e)
|
||||||
|
addLog(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
asyncWrap()
|
||||||
|
return () => {
|
||||||
|
unsubFn.forEach((fn) => fn())
|
||||||
|
}
|
||||||
|
}, [defferedCode, isStreamReady, engineCommandManager])
|
||||||
|
}
|
48
src/hooks/useSetupEngineManager.ts
Normal file
48
src/hooks/useSetupEngineManager.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { useLayoutEffect } from 'react'
|
||||||
|
import { _executor } from '../lang/executor'
|
||||||
|
import { useStore } from '../useStore'
|
||||||
|
import { EngineCommandManager } from '../lang/std/engineConnection'
|
||||||
|
|
||||||
|
export function useSetupEngineManager(
|
||||||
|
streamRef: React.RefObject<HTMLDivElement>,
|
||||||
|
token?: string
|
||||||
|
) {
|
||||||
|
const {
|
||||||
|
setEngineCommandManager,
|
||||||
|
setMediaStream,
|
||||||
|
setIsStreamReady,
|
||||||
|
setStreamDimensions,
|
||||||
|
} = useStore((s) => ({
|
||||||
|
setEngineCommandManager: s.setEngineCommandManager,
|
||||||
|
setMediaStream: s.setMediaStream,
|
||||||
|
setIsStreamReady: s.setIsStreamReady,
|
||||||
|
setStreamDimensions: s.setStreamDimensions,
|
||||||
|
}))
|
||||||
|
|
||||||
|
const streamWidth = streamRef?.current?.offsetWidth
|
||||||
|
const streamHeight = streamRef?.current?.offsetHeight
|
||||||
|
|
||||||
|
const width = streamWidth ? streamWidth : 0
|
||||||
|
const quadWidth = Math.round(width / 4) * 4
|
||||||
|
const height = streamHeight ? streamHeight : 0
|
||||||
|
const quadHeight = Math.round(height / 4) * 4
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
setStreamDimensions({
|
||||||
|
streamWidth: quadWidth,
|
||||||
|
streamHeight: quadHeight,
|
||||||
|
})
|
||||||
|
if (!width || !height) return
|
||||||
|
const eng = new EngineCommandManager({
|
||||||
|
setMediaStream,
|
||||||
|
setIsStreamReady,
|
||||||
|
width: quadWidth,
|
||||||
|
height: quadHeight,
|
||||||
|
token,
|
||||||
|
})
|
||||||
|
setEngineCommandManager(eng)
|
||||||
|
return () => {
|
||||||
|
eng?.tearDown()
|
||||||
|
}
|
||||||
|
}, [quadWidth, quadHeight])
|
||||||
|
}
|
Reference in New Issue
Block a user