@ -39,3 +39,32 @@ export const AppStateProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
</AppStateContext.Provider>
|
</AppStateContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface AppStream {
|
||||||
|
mediaStream: MediaStream
|
||||||
|
setMediaStream: (mediaStream: MediaStream) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const AppStreamContext = createContext<AppStream>({
|
||||||
|
mediaStream: undefined as unknown as MediaStream,
|
||||||
|
setMediaStream: () => {},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const useAppStream = () => useContext(AppStreamContext)
|
||||||
|
|
||||||
|
export const AppStreamProvider = ({ children }: { children: ReactNode }) => {
|
||||||
|
const [mediaStream, setMediaStream] = useState<MediaStream>(
|
||||||
|
undefined as unknown as MediaStream
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppStreamContext.Provider
|
||||||
|
value={{
|
||||||
|
mediaStream,
|
||||||
|
setMediaStream,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</AppStreamContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import { ClientSideScene } from 'clientSideScene/ClientSideSceneComp'
|
|||||||
import { btnName } from 'lib/cameraControls'
|
import { btnName } from 'lib/cameraControls'
|
||||||
import { sendSelectEventToEngine } from 'lib/selections'
|
import { sendSelectEventToEngine } from 'lib/selections'
|
||||||
import { kclManager, engineCommandManager, sceneInfra } from 'lib/singletons'
|
import { kclManager, engineCommandManager, sceneInfra } from 'lib/singletons'
|
||||||
|
import { useAppStream } from 'AppState'
|
||||||
|
|
||||||
export const Stream = () => {
|
export const Stream = () => {
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
@ -17,6 +18,7 @@ export const Stream = () => {
|
|||||||
const videoRef = useRef<HTMLVideoElement>(null)
|
const videoRef = useRef<HTMLVideoElement>(null)
|
||||||
const { settings } = useSettingsAuthContext()
|
const { settings } = useSettingsAuthContext()
|
||||||
const { state, send, context } = useModelingContext()
|
const { state, send, context } = useModelingContext()
|
||||||
|
const { mediaStream } = useAppStream()
|
||||||
const { overallState } = useNetworkContext()
|
const { overallState } = useNetworkContext()
|
||||||
const [isFreezeFrame, setIsFreezeFrame] = useState(false)
|
const [isFreezeFrame, setIsFreezeFrame] = useState(false)
|
||||||
|
|
||||||
@ -124,12 +126,10 @@ export const Stream = () => {
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
if (!videoRef.current) return
|
if (!videoRef.current) return
|
||||||
const _mediaStream =
|
if (!mediaStream) return
|
||||||
context.store?.mediaStream || (window as any).mediaStream
|
|
||||||
if (!_mediaStream) return
|
|
||||||
|
|
||||||
// Do not immediately play the stream!
|
// Do not immediately play the stream!
|
||||||
videoRef.current.srcObject = _mediaStream
|
videoRef.current.srcObject = mediaStream
|
||||||
videoRef.current.pause()
|
videoRef.current.pause()
|
||||||
|
|
||||||
send({
|
send({
|
||||||
@ -138,7 +138,7 @@ export const Stream = () => {
|
|||||||
videoElement: videoRef.current,
|
videoElement: videoRef.current,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}, [context.store?.mediaStream])
|
}, [mediaStream])
|
||||||
|
|
||||||
const handleMouseDown: MouseEventHandler<HTMLDivElement> = (e) => {
|
const handleMouseDown: MouseEventHandler<HTMLDivElement> = (e) => {
|
||||||
if (!isNetworkOkay) return
|
if (!isNetworkOkay) return
|
||||||
|
@ -4,7 +4,7 @@ import { deferExecution } from 'lib/utils'
|
|||||||
import { Themes } from 'lib/theme'
|
import { Themes } from 'lib/theme'
|
||||||
import { makeDefaultPlanes, modifyGrid } from 'lang/wasm'
|
import { makeDefaultPlanes, modifyGrid } from 'lang/wasm'
|
||||||
import { useModelingContext } from './useModelingContext'
|
import { useModelingContext } from './useModelingContext'
|
||||||
import { useAppState } from 'AppState'
|
import { useAppState, useAppStream } from 'AppState'
|
||||||
|
|
||||||
export function useSetupEngineManager(
|
export function useSetupEngineManager(
|
||||||
streamRef: React.RefObject<HTMLDivElement>,
|
streamRef: React.RefObject<HTMLDivElement>,
|
||||||
@ -28,6 +28,7 @@ export function useSetupEngineManager(
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const { setAppState } = useAppState()
|
const { setAppState } = useAppState()
|
||||||
|
const { setMediaStream } = useAppStream()
|
||||||
|
|
||||||
const streamWidth = streamRef?.current?.offsetWidth
|
const streamWidth = streamRef?.current?.offsetWidth
|
||||||
const streamHeight = streamRef?.current?.offsetHeight
|
const streamHeight = streamRef?.current?.offsetHeight
|
||||||
@ -54,13 +55,7 @@ export function useSetupEngineManager(
|
|||||||
settings.modelingSend
|
settings.modelingSend
|
||||||
) {
|
) {
|
||||||
engineCommandManager.start({
|
engineCommandManager.start({
|
||||||
setMediaStream: (mediaStream) => {
|
setMediaStream: setMediaStream,
|
||||||
settings.modelingSend({
|
|
||||||
type: 'Set context',
|
|
||||||
data: { mediaStream },
|
|
||||||
})
|
|
||||||
;(window as any).mediaStream = mediaStream
|
|
||||||
},
|
|
||||||
setIsStreamReady: (isStreamReady) => setAppState({ isStreamReady }),
|
setIsStreamReady: (isStreamReady) => setAppState({ isStreamReady }),
|
||||||
width: quadWidth,
|
width: quadWidth,
|
||||||
height: quadHeight,
|
height: quadHeight,
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
UpdaterRestartModal,
|
UpdaterRestartModal,
|
||||||
createUpdaterRestartModal,
|
createUpdaterRestartModal,
|
||||||
} from 'components/UpdaterRestartModal'
|
} from 'components/UpdaterRestartModal'
|
||||||
|
import { AppStreamProvider } from 'AppState'
|
||||||
|
|
||||||
// uncomment for xstate inspector
|
// uncomment for xstate inspector
|
||||||
// import { DEV } from 'env'
|
// import { DEV } from 'env'
|
||||||
@ -26,28 +27,30 @@ const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
|
|||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
<HotkeysProvider>
|
<HotkeysProvider>
|
||||||
<Router />
|
<AppStreamProvider>
|
||||||
<Toaster
|
<Router />
|
||||||
position="bottom-center"
|
<Toaster
|
||||||
toastOptions={{
|
position="bottom-center"
|
||||||
style: {
|
toastOptions={{
|
||||||
borderRadius: '3px',
|
style: {
|
||||||
},
|
borderRadius: '3px',
|
||||||
className:
|
|
||||||
'bg-chalkboard-10 dark:bg-chalkboard-90 text-chalkboard-110 dark:text-chalkboard-10 rounded-sm border-chalkboard-20/50 dark:border-chalkboard-80/50',
|
|
||||||
success: {
|
|
||||||
iconTheme: {
|
|
||||||
primary: 'oklch(89% 0.16 143.4deg)',
|
|
||||||
secondary: 'oklch(48.62% 0.1654 142.5deg)',
|
|
||||||
},
|
},
|
||||||
duration:
|
className:
|
||||||
window?.localStorage.getItem('playwright') === 'true'
|
'bg-chalkboard-10 dark:bg-chalkboard-90 text-chalkboard-110 dark:text-chalkboard-10 rounded-sm border-chalkboard-20/50 dark:border-chalkboard-80/50',
|
||||||
? 10 // speed up e2e tests
|
success: {
|
||||||
: 1500,
|
iconTheme: {
|
||||||
},
|
primary: 'oklch(89% 0.16 143.4deg)',
|
||||||
}}
|
secondary: 'oklch(48.62% 0.1654 142.5deg)',
|
||||||
/>
|
},
|
||||||
<ModalContainer />
|
duration:
|
||||||
|
window?.localStorage.getItem('playwright') === 'true'
|
||||||
|
? 10 // speed up e2e tests
|
||||||
|
: 1500,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ModalContainer />
|
||||||
|
</AppStreamProvider>
|
||||||
</HotkeysProvider>
|
</HotkeysProvider>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -138,7 +138,6 @@ export type SegmentOverlayPayload =
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Store {
|
interface Store {
|
||||||
mediaStream?: MediaStream
|
|
||||||
videoElement?: HTMLVideoElement
|
videoElement?: HTMLVideoElement
|
||||||
buttonDownInStream: number | undefined
|
buttonDownInStream: number | undefined
|
||||||
didDragInStream: boolean
|
didDragInStream: boolean
|
||||||
|
Reference in New Issue
Block a user