Group events by calls or users
This commit is contained in:
163
src/DevTools.jsx
163
src/DevTools.jsx
@@ -1,5 +1,6 @@
|
||||
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 });
|
||||
@@ -25,13 +26,27 @@ function CallId({ callId, ...rest }) {
|
||||
);
|
||||
}
|
||||
|
||||
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);
|
||||
setDebugState({ ...manager.debugState });
|
||||
}
|
||||
|
||||
manager.on("debug", onRoomDebug);
|
||||
@@ -47,15 +62,50 @@ export function DevTools({ manager }) {
|
||||
|
||||
return (
|
||||
<div className={styles.devTools}>
|
||||
{Array.from(debugState.entries()).map(([userId, props]) => (
|
||||
<UserState
|
||||
key={userId}
|
||||
roomId={manager.roomId}
|
||||
onSelectEvent={setSelectedEvent}
|
||||
userId={userId}
|
||||
{...props}
|
||||
/>
|
||||
))}
|
||||
<div className={styles.toolbar}>
|
||||
<div
|
||||
className={classNames(styles.tab, {
|
||||
[styles.activeTab]: activeTab === "users",
|
||||
})}
|
||||
onClick={() => setActiveTab("users")}
|
||||
>
|
||||
Users
|
||||
</div>
|
||||
<div
|
||||
className={classNames(styles.tab, {
|
||||
[styles.activeTab]: activeTab === "calls",
|
||||
})}
|
||||
onClick={() => setActiveTab("calls")}
|
||||
>
|
||||
Calls
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.devToolsContainer}>
|
||||
{activeTab === "users" &&
|
||||
Array.from(debugState.users.entries())
|
||||
.sort(sortEntries)
|
||||
.map(([userId, props]) => (
|
||||
<EventContainer
|
||||
key={userId}
|
||||
showCallId
|
||||
title={<UserId userId={userId} />}
|
||||
{...props}
|
||||
onSelect={setSelectedEvent}
|
||||
/>
|
||||
))}
|
||||
{activeTab === "calls" &&
|
||||
Array.from(debugState.calls.entries())
|
||||
.sort(sortEntries)
|
||||
.map(([callId, props]) => (
|
||||
<EventContainer
|
||||
key={callId}
|
||||
showSender
|
||||
title={<CallId callId={callId} />}
|
||||
{...props}
|
||||
onSelect={setSelectedEvent}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
{selectedEvent && (
|
||||
<EventViewer
|
||||
event={selectedEvent}
|
||||
@@ -66,7 +116,7 @@ export function DevTools({ manager }) {
|
||||
);
|
||||
}
|
||||
|
||||
function UserState({ roomId, userId, state, callId, events, onSelectEvent }) {
|
||||
function EventContainer({ title, state, events, ...rest }) {
|
||||
const eventsRef = useRef();
|
||||
const [autoScroll, setAutoScroll] = useState(true);
|
||||
|
||||
@@ -90,78 +140,59 @@ function UserState({ roomId, userId, state, callId, events, onSelectEvent }) {
|
||||
return (
|
||||
<div className={styles.user}>
|
||||
<div className={styles.userId}>
|
||||
<UserId userId={userId} />
|
||||
<span>{title}</span>
|
||||
<span>{`(${state})`}</span>
|
||||
{callId && <CallId callId={callId} />}
|
||||
</div>
|
||||
<div ref={eventsRef} className={styles.events} onScroll={onScroll}>
|
||||
{events
|
||||
.filter((e) => e.roomId === roomId)
|
||||
.map((event, idx) => (
|
||||
<div
|
||||
className={styles.event}
|
||||
key={idx}
|
||||
onClick={() => onSelectEvent(event)}
|
||||
>
|
||||
<span className={styles.eventType}>{event.type}</span>
|
||||
{event.callId && (
|
||||
<CallId className={styles.eventDetails} callId={event.callId} />
|
||||
)}
|
||||
{event.newCallId && (
|
||||
<>
|
||||
<span className={styles.eventDetails}>{"->"}</span>
|
||||
<CallId
|
||||
className={styles.eventDetails}
|
||||
callId={event.newCallId}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{event.to && (
|
||||
<UserId className={styles.eventDetails} userId={event.to} />
|
||||
)}
|
||||
{event.reason && (
|
||||
<span className={styles.eventDetails}>{event.reason}</span>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{events.map((event, idx) => (
|
||||
<EventItem key={idx} event={event} {...rest} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function EventItem({ event, showCallId, showSender, onSelect }) {
|
||||
const type = event.getType();
|
||||
const sender = event.getSender();
|
||||
const { call_id, invitee } = event.getContent();
|
||||
|
||||
return (
|
||||
<div className={styles.event} onClick={() => onSelect(event)}>
|
||||
{showSender && sender && (
|
||||
<UserId className={styles.eventDetails} userId={sender} />
|
||||
)}
|
||||
<span className={styles.eventType}>{type}</span>
|
||||
{showCallId && call_id && (
|
||||
<CallId className={styles.eventDetails} callId={call_id} />
|
||||
)}
|
||||
{invitee && <UserId className={styles.eventDetails} userId={invitee} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function EventViewer({ event, onClose }) {
|
||||
const type = event.getType();
|
||||
const sender = event.getSender();
|
||||
const { call_id, invitee } = event.getContent();
|
||||
const json = event.toJSON();
|
||||
|
||||
return (
|
||||
<div className={styles.eventViewer}>
|
||||
<p>Event Type: {event.type}</p>
|
||||
{event.callId && (
|
||||
<p>Event Type: {type}</p>
|
||||
<p>Sender: {sender}</p>
|
||||
{call_id && (
|
||||
<p>
|
||||
Call Id: <CallId callId={event.callId} />
|
||||
Call Id: <CallId callId={call_id} />
|
||||
</p>
|
||||
)}
|
||||
{event.newCallId && (
|
||||
{invitee && (
|
||||
<p>
|
||||
New Call Id:
|
||||
<CallId callId={event.newCallId} />
|
||||
Invitee: <UserId userId={invitee} />
|
||||
</p>
|
||||
)}
|
||||
{event.to && (
|
||||
<p>
|
||||
To: <UserId userId={event.to} />
|
||||
</p>
|
||||
)}
|
||||
{event.reason && (
|
||||
<p>
|
||||
Reason: <span>{event.reason}</span>
|
||||
</p>
|
||||
)}
|
||||
{event.content && (
|
||||
<>
|
||||
<p>Content:</p>
|
||||
<pre className={styles.content}>
|
||||
{JSON.stringify(event.content, undefined, 2)}
|
||||
</pre>
|
||||
</>
|
||||
)}
|
||||
<p>Raw Event:</p>
|
||||
<pre className={styles.content}>{JSON.stringify(json, undefined, 2)}</pre>
|
||||
<button onClick={onClose}>Close</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user