import React, { useCallback, useEffect, useRef, useState } from "react"; import ColorHash from "color-hash"; import classNames from "classnames"; import styles from "./DevTools.module.css"; const colorHash = new ColorHash({ lightness: 0.8 }); function UserId({ userId, ...rest }) { const shortUserId = userId.split(":")[0]; const color = colorHash.hex(shortUserId); return ( {shortUserId} ); } function CallId({ callId, ...rest }) { const shortId = callId.substr(callId.length - 16); const color = colorHash.hex(shortId); return ( {shortId} ); } function sortEntries(a, b) { const aInactive = a[1].state === "inactive"; const bInactive = b[1].state === "inactive"; if (aInactive && !bInactive) { return 1; } else if (bInactive && !aInactive) { return -1; } else { return a[0] < b[0] ? -1 : 1; } } export function DevTools({ manager }) { const [debugState, setDebugState] = useState(manager.debugState); const [selectedEvent, setSelectedEvent] = useState(); const [activeTab, setActiveTab] = useState("users"); useEffect(() => { function onRoomDebug() { setDebugState({ ...manager.debugState }); } manager.on("debug", onRoomDebug); return () => { manager.removeListener("debug", onRoomDebug); }; }, [manager]); if (!manager.joined) { return
; } return (
setActiveTab("users")} > Users
setActiveTab("calls")} > Calls
{activeTab === "users" && Array.from(debugState.users.entries()) .sort(sortEntries) .map(([userId, props]) => ( } {...props} onSelect={setSelectedEvent} /> ))} {activeTab === "calls" && Array.from(debugState.calls.entries()) .sort(sortEntries) .map(([callId, props]) => ( } {...props} onSelect={setSelectedEvent} /> ))}
{selectedEvent && ( setSelectedEvent(null)} /> )}
); } function EventContainer({ title, state, events, ...rest }) { const eventsRef = useRef(); const [autoScroll, setAutoScroll] = useState(true); useEffect(() => { if (autoScroll) { const el = eventsRef.current; el.scrollTop = el.scrollHeight - el.clientHeight; } }); const onScroll = useCallback(() => { const el = eventsRef.current; if (el.scrollHeight - el.scrollTop === el.clientHeight) { setAutoScroll(true); } else { setAutoScroll(false); } }, []); return (
{title} {`(${state})`}
{events.map((event, idx) => ( ))}
); } function EventItem({ event, showCallId, showSender, onSelect }) { const type = event.getType(); const sender = event.getSender(); const { call_id, invitee, reason, eventType, ...rest } = event.getContent(); let eventValue; if (eventType === "icegatheringstatechange") { eventValue = rest.iceGatheringState; } else if (eventType === "iceconnectionstatechange") { eventValue = rest.iceConnectionState; } else if (eventType === "signalingstatechange") { eventValue = rest.signalingState; } return (
onSelect(event)}> {showSender && sender && ( )} {type.replace("me.robertlong.", "x.")} {showCallId && call_id && ( )} {invitee && } {reason && {reason}} {eventType && {eventType}} {eventValue && {eventValue}}
); } function EventViewer({ event, onClose }) { const type = event.getType(); const sender = event.getSender(); const { call_id, invitee } = event.getContent(); const json = event.toJSON(); return (

Event Type: {type}

Sender: {sender}

{call_id && (

Call Id:

)} {invitee && (

Invitee:

)}

Raw Event:

{JSON.stringify(json, undefined, 2)}
); }