Move executeCode out of routeLoaders, into shared space in Stream (#3332)
* Move executeCode out of routeLoaders, into shared space in Stream
* Update src/components/Stream.tsx
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Remove unused dependency
* file switching useEffect should depend on engineConnection
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Re-run CI
* Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)"
This reverts commit d97e74a48b
.
* Post-merge fix up
---------
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
This commit is contained in:
@ -15,6 +15,9 @@ import {
|
|||||||
EngineConnectionStateType,
|
EngineConnectionStateType,
|
||||||
DisconnectingType,
|
DisconnectingType,
|
||||||
} from 'lang/std/engineConnection'
|
} from 'lang/std/engineConnection'
|
||||||
|
import { useRouteLoaderData } from 'react-router-dom'
|
||||||
|
import { PATHS } from 'lib/paths'
|
||||||
|
import { IndexLoaderData } from 'lib/types'
|
||||||
|
|
||||||
enum StreamState {
|
enum StreamState {
|
||||||
Playing = 'playing',
|
Playing = 'playing',
|
||||||
@ -32,6 +35,7 @@ export const Stream = () => {
|
|||||||
const { mediaStream } = useAppStream()
|
const { mediaStream } = useAppStream()
|
||||||
const { overallState, immediateState } = useNetworkContext()
|
const { overallState, immediateState } = useNetworkContext()
|
||||||
const [streamState, setStreamState] = useState(StreamState.Unset)
|
const [streamState, setStreamState] = useState(StreamState.Unset)
|
||||||
|
const { file } = useRouteLoaderData(PATHS.FILE) as IndexLoaderData
|
||||||
|
|
||||||
const IDLE = settings.context.app.streamIdleMode.current
|
const IDLE = settings.context.app.streamIdleMode.current
|
||||||
|
|
||||||
@ -39,6 +43,39 @@ export const Stream = () => {
|
|||||||
overallState === NetworkHealthState.Ok ||
|
overallState === NetworkHealthState.Ok ||
|
||||||
overallState === NetworkHealthState.Weak
|
overallState === NetworkHealthState.Weak
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute code and show a "building scene message"
|
||||||
|
* in Stream.tsx in the meantime.
|
||||||
|
*
|
||||||
|
* I would like for this to live somewhere more central,
|
||||||
|
* but it seems to me that we need the video element ref
|
||||||
|
* to be able to play the video after the code has been
|
||||||
|
* executed. If we can find a way to do this from a more
|
||||||
|
* central place, we can move this code there.
|
||||||
|
*/
|
||||||
|
async function executeCodeAndPlayStream() {
|
||||||
|
kclManager.isFirstRender = true
|
||||||
|
kclManager.executeCode(true).then(() => {
|
||||||
|
videoRef.current?.play().catch((e) => {
|
||||||
|
console.warn('Video playing was prevented', e, videoRef.current)
|
||||||
|
})
|
||||||
|
kclManager.isFirstRender = false
|
||||||
|
setStreamState(StreamState.Playing)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to execute code when the file changes
|
||||||
|
* but only if the scene is already ready.
|
||||||
|
* See onSceneReady for the initial scene setup.
|
||||||
|
*/
|
||||||
|
useEffect(() => {
|
||||||
|
if (engineCommandManager.engineConnection?.isReady() && file?.path) {
|
||||||
|
console.log('execute on file change')
|
||||||
|
executeCodeAndPlayStream()
|
||||||
|
}
|
||||||
|
}, [file?.path, engineCommandManager.engineConnection])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
immediateState.type === EngineConnectionStateType.Disconnecting &&
|
immediateState.type === EngineConnectionStateType.Disconnecting &&
|
||||||
@ -135,26 +172,19 @@ export const Stream = () => {
|
|||||||
timeoutIdIdleB = setTimeout(teardown, IDLE_TIME_MS)
|
timeoutIdIdleB = setTimeout(teardown, IDLE_TIME_MS)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onSceneReady = () => {
|
/**
|
||||||
kclManager.isFirstRender = true
|
* Add a listener to execute code and play the stream
|
||||||
setStreamState(StreamState.Playing)
|
* on initial stream setup.
|
||||||
kclManager.executeCode(true).then(() => {
|
*/
|
||||||
videoRef.current?.play().catch((e) => {
|
|
||||||
console.warn('Video playing was prevented', e, videoRef.current)
|
|
||||||
})
|
|
||||||
kclManager.isFirstRender = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
engineCommandManager.addEventListener(
|
engineCommandManager.addEventListener(
|
||||||
EngineCommandManagerEvents.SceneReady,
|
EngineCommandManagerEvents.SceneReady,
|
||||||
onSceneReady
|
executeCodeAndPlayStream
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
engineCommandManager.removeEventListener(
|
engineCommandManager.removeEventListener(
|
||||||
EngineCommandManagerEvents.SceneReady,
|
EngineCommandManagerEvents.SceneReady,
|
||||||
onSceneReady
|
executeCodeAndPlayStream
|
||||||
)
|
)
|
||||||
globalThis?.window?.document?.removeEventListener('paste', handlePaste, {
|
globalThis?.window?.document?.removeEventListener('paste', handlePaste, {
|
||||||
capture: true,
|
capture: true,
|
||||||
@ -185,16 +215,18 @@ export const Stream = () => {
|
|||||||
}
|
}
|
||||||
}, [IDLE, streamState])
|
}, [IDLE, streamState])
|
||||||
|
|
||||||
// HOT FIX: for https://github.com/KittyCAD/modeling-app/pull/3250
|
/**
|
||||||
// TODO review if there's a better way to play the stream again.
|
* Play the vid
|
||||||
|
*/
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!kclManager.isFirstRender)
|
if (!kclManager.isFirstRender) {
|
||||||
setTimeout(() =>
|
setTimeout(() =>
|
||||||
// execute in the next event loop
|
// execute in the next event loop
|
||||||
videoRef.current?.play().catch((e) => {
|
videoRef.current?.play().catch((e) => {
|
||||||
console.warn('Video playing was prevented', e, videoRef.current)
|
console.warn('Video playing was prevented', e, videoRef.current)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}, [kclManager.isFirstRender])
|
}, [kclManager.isFirstRender])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -12,7 +12,7 @@ import { loadAndValidateSettings } from './settings/settingsUtils'
|
|||||||
import makeUrlPathRelative from './makeUrlPathRelative'
|
import makeUrlPathRelative from './makeUrlPathRelative'
|
||||||
import { sep } from '@tauri-apps/api/path'
|
import { sep } from '@tauri-apps/api/path'
|
||||||
import { readTextFile } from '@tauri-apps/plugin-fs'
|
import { readTextFile } from '@tauri-apps/plugin-fs'
|
||||||
import { codeManager, kclManager } from 'lib/singletons'
|
import { codeManager } from 'lib/singletons'
|
||||||
import { fileSystemManager } from 'lang/std/fileSystemManager'
|
import { fileSystemManager } from 'lang/std/fileSystemManager'
|
||||||
import {
|
import {
|
||||||
getProjectInfo,
|
getProjectInfo,
|
||||||
@ -105,9 +105,6 @@ export const fileLoader: LoaderFunction = async ({
|
|||||||
codeManager.updateCurrentFilePath(current_file_path)
|
codeManager.updateCurrentFilePath(current_file_path)
|
||||||
codeManager.updateCodeStateEditor(code)
|
codeManager.updateCodeStateEditor(code)
|
||||||
|
|
||||||
// We don't want to call await on execute code since we don't want to block the UI
|
|
||||||
kclManager.executeCode(true)
|
|
||||||
|
|
||||||
// Set the file system manager to the project path
|
// Set the file system manager to the project path
|
||||||
// So that WASM gets an updated path for operations
|
// So that WASM gets an updated path for operations
|
||||||
fileSystemManager.dir = project_path
|
fileSystemManager.dir = project_path
|
||||||
|
Reference in New Issue
Block a user