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 (
+
+ )
+}