import range from 'lodash/range' import ReconnectingWebSocket from 'reconnecting-websocket' import { h, render } from 'preact' import { useEffect, useState, useCallback, useRef } from 'preact/hooks' import styled from 'styled-components' import '../index.css' import SoundIcon from '../static/volume-up-solid.svg' function App({ wsEndpoint }) { const wsRef = useRef() const [isConnected, setIsConnected] = useState(false) const [streamData, setStreamData] = useState() const [spaceIdxMap, setSpaceIdxMap] = useState(new Map()) const [listeningIdxSet, setListeningIdxSet] = useState(new Set()) useEffect(() => { const ws = new ReconnectingWebSocket(wsEndpoint, [], { maxReconnectionDelay: 5000, minReconnectionDelay: 1000 + Math.random() * 500, reconnectionDelayGrowFactor: 1.1, }) ws.addEventListener('open', () => setIsConnected(true)) ws.addEventListener('close', () => setIsConnected(false)) ws.addEventListener('message', (ev) => { const msg = JSON.parse(ev.data) if (msg.type === 'state') { const { streams, views } = msg.state setStreamData(streams) const newSpaceIdxMap = new Map() const newListeningIdxSet = new Set() for (const viewState of views) { const { pos, url } = viewState.context if (!url) { continue } const streamId = streams.find((d) => d.Link === url)?._id const isListening = viewState.state.displaying?.running === 'listening' for (const space of pos.spaces) { newSpaceIdxMap.set(space, streamId) if (isListening) { newListeningIdxSet.add(space) } } } setSpaceIdxMap(newSpaceIdxMap) setListeningIdxSet(newListeningIdxSet) } else { console.warn('unexpected ws message', msg) } }) wsRef.current = ws }, []) const handleSetSpace = useCallback( (idx, id) => { const newSpaceIdxMap = new Map(spaceIdxMap) if (id !== undefined) { newSpaceIdxMap.set(idx, id) } else { newSpaceIdxMap.delete(idx) } setSpaceIdxMap(newSpaceIdxMap) const views = Array.from(newSpaceIdxMap, ([spaceIdx, streamId]) => [ spaceIdx, streamData.find((d) => d._id === streamId)?.Link, ]).filter(([s, i]) => i) wsRef.current.send(JSON.stringify({ type: 'set-views', views })) }, [streamData, spaceIdxMap], ) const handleSetListening = useCallback((idx, listening) => { wsRef.current.send( JSON.stringify({ type: 'set-listening-view', viewIdx: listening ? idx : null, }), ) }, []) return (