diff --git a/src/App.tsx b/src/App.tsx index d1dcb8b7c..6e6c6a378 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -22,6 +22,7 @@ import { RenderViewerArtifacts } from './components/RenderViewerArtifacts' import { PanelHeader } from './components/PanelHeader' import { MemoryPanel } from './components/MemoryPanel' import { useHotKeyListener } from './hooks/useHotKeyListener' +import { Stream } from './components/Stream' const OrrthographicCamera = OrthographicCamera as any @@ -164,52 +165,55 @@ function App() { -
- - -
-
- - - - - - - - - - -
- {errorState.isError && ( -
-
-                  {'last first: \n\n' +
-                    JSON.stringify(lastGuiMode, null, 2) +
-                    '\n\n' +
-                    JSON.stringify(guiMode)}
-                
+ +
+ + +
+
+ + + + + + + + + +
- )} + {errorState.isError && ( +
+
+                    {'last first: \n\n' +
+                      JSON.stringify(lastGuiMode, null, 2) +
+                      '\n\n' +
+                      JSON.stringify(guiMode)}
+                  
+
+ )} +
-
+ +
) diff --git a/src/Auth.tsx b/src/Auth.tsx index 87c97af45..e616c65d7 100644 --- a/src/Auth.tsx +++ b/src/Auth.tsx @@ -4,7 +4,7 @@ import withBaseUrl from './lib/withBaseURL' import App from './App' export const Auth = () => { - const { data: user, error } = useSWR(withBaseUrl('/user'), fetcher) as any + const { data: user } = useSWR(withBaseUrl('/user'), fetcher) as any const isLocalHost = typeof window !== 'undefined' && window.location.hostname === 'localhost' diff --git a/src/components/Stream.tsx b/src/components/Stream.tsx new file mode 100644 index 000000000..2f2b014d4 --- /dev/null +++ b/src/components/Stream.tsx @@ -0,0 +1,91 @@ +import { useEffect, useRef } from 'react' +import { PanelHeader } from '../components/PanelHeader' + +export const Stream = () => { + const videoRef = useRef(null) + + useEffect(() => { + const url = 'wss://dev.api.kittycad.io/ws/channel' + const [pc, socket] = [new RTCPeerConnection(), new WebSocket(url)] + // Connection opened + socket.addEventListener('open', (event) => { + console.log('Connected to websocket, waiting for ICE servers') + }) + + socket.addEventListener('close', (event) => { + console.log('websocket connection closed') + }) + + socket.addEventListener('error', (event) => { + console.log('websocket connection error') + }) + + // Listen for messages + socket.addEventListener('message', (event) => { + //console.log('Message from server ', event.data); + if (event.data instanceof Blob) { + const reader = new FileReader() + + reader.onload = () => { + //console.log("Result: " + reader.result); + } + + reader.readAsText(event.data) + } else { + const message = JSON.parse(event.data) + if (message.type === 'SDPAnswer') { + pc.setRemoteDescription(new RTCSessionDescription(message.answer)) + } else if (message.type === 'IceServerInfo') { + console.log('received IceServerInfo') + pc.setConfiguration({ + iceServers: message.ice_servers, + }) + pc.ontrack = function (event) { + const el = document.createElement( + event.track.kind + ) as HTMLVideoElement + + if (videoRef.current) { + videoRef.current.srcObject = event.streams[0] + videoRef.current.autoplay = true + videoRef.current.controls = true + } + } + pc.oniceconnectionstatechange = (e) => + console.log(pc.iceConnectionState) + pc.onicecandidate = (event) => { + if (event.candidate === null) { + console.log('sent SDPOffer') + socket.send( + JSON.stringify({ + type: 'SDPOffer', + offer: pc.localDescription, + }) + ) + } + } + + // Offer to receive 1 video track + pc.addTransceiver('video', { + direction: 'sendrecv', + }) + pc.createOffer() + .then((d) => pc.setLocalDescription(d)) + .catch(console.log) + } + } + }) + + return () => { + socket.close() + pc.close() + } + }, []) + + return ( +
+ +
+ ) +}