Debug overlay (#97)
* add connection stats * add permissions * styling * css module * styles * scrolling * fix height * account for body height
This commit is contained in:
parent
2c984306cb
commit
2c202c25a2
4 changed files with 218 additions and 5 deletions
197
lib/Debug.tsx
197
lib/Debug.tsx
|
@ -1,10 +1,13 @@
|
|||
import * as React from 'react';
|
||||
import { useRoomContext } from '@livekit/components-react';
|
||||
import { setLogLevel, LogLevel } from 'livekit-client';
|
||||
import { setLogLevel, LogLevel, RemoteTrackPublication } from 'livekit-client';
|
||||
import { tinykeys } from 'tinykeys';
|
||||
import styles from '../styles/Debug.module.css';
|
||||
|
||||
export const useDebugMode = ({ logLevel }: { logLevel?: LogLevel }) => {
|
||||
setLogLevel(logLevel ?? 'debug');
|
||||
const room = useRoomContext();
|
||||
|
||||
React.useEffect(() => {
|
||||
// @ts-expect-error
|
||||
window.__lk_room = room;
|
||||
|
@ -13,10 +16,198 @@ export const useDebugMode = ({ logLevel }: { logLevel?: LogLevel }) => {
|
|||
// @ts-expect-error
|
||||
window.__lk_room = undefined;
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const DebugMode = ({ logLevel }: { logLevel?: LogLevel }) => {
|
||||
const room = useRoomContext();
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
const [, setRender] = React.useState({});
|
||||
|
||||
useDebugMode({ logLevel });
|
||||
return <></>;
|
||||
|
||||
React.useEffect(() => {
|
||||
if (window) {
|
||||
const unsubscribe = tinykeys(window, {
|
||||
'Shift+D': () => {
|
||||
console.log('setting open');
|
||||
setIsOpen((open) => !open);
|
||||
},
|
||||
});
|
||||
|
||||
// timer to re-render
|
||||
const interval = setInterval(() => {
|
||||
setRender({});
|
||||
}, 1000);
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
clearInterval(interval);
|
||||
};
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
if (typeof window === 'undefined' || !isOpen) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handleSimulate = (event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const { value } = event.target;
|
||||
if (value == '') {
|
||||
return;
|
||||
}
|
||||
event.target.value = '';
|
||||
let isReconnect = false;
|
||||
switch (value) {
|
||||
case 'signal-reconnect':
|
||||
isReconnect = true;
|
||||
|
||||
// fall through
|
||||
default:
|
||||
// @ts-expect-error
|
||||
room.simulateScenario(value);
|
||||
}
|
||||
};
|
||||
|
||||
const lp = room.localParticipant;
|
||||
|
||||
if (!isOpen) {
|
||||
return <></>;
|
||||
} else {
|
||||
return (
|
||||
<div className={styles.overlay}>
|
||||
<section id="room-info">
|
||||
<h3>
|
||||
Room Info {room.name}: {room.sid}
|
||||
</h3>
|
||||
</section>
|
||||
<details open>
|
||||
<summary>
|
||||
<b>Local Participant: {lp.identity}</b>
|
||||
</summary>
|
||||
<details open className={styles.detailsSection}>
|
||||
<summary>
|
||||
<b>Published tracks</b>
|
||||
</summary>
|
||||
<div>
|
||||
{Array.from(lp.tracks.values()).map((t) => (
|
||||
<>
|
||||
<div>
|
||||
<i>
|
||||
{t.source.toString()}
|
||||
<span>{t.trackSid}</span>
|
||||
</i>
|
||||
</div>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Kind</td>
|
||||
<td>
|
||||
{t.kind}
|
||||
{t.kind === 'video' && (
|
||||
<span>
|
||||
{t.track?.dimensions?.width}x{t.track?.dimensions?.height}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bitrate</td>
|
||||
<td>{Math.ceil(t.track!.currentBitrate / 1000)} kbps</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
</details>
|
||||
<details open className={styles.detailsSection}>
|
||||
<summary>
|
||||
<b>Permissions</b>
|
||||
</summary>
|
||||
<div>
|
||||
<table>
|
||||
<tbody>
|
||||
{lp.permissions &&
|
||||
Object.entries(lp.permissions).map(([key, val]) => (
|
||||
<>
|
||||
<tr>
|
||||
<td>{key}</td>
|
||||
{key !== 'canPublishSources' ? (
|
||||
<td>{val.toString()}</td>
|
||||
) : (
|
||||
<td> {val.join(', ')} </td>
|
||||
)}
|
||||
</tr>
|
||||
</>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</details>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<b>Remote Participants</b>
|
||||
</summary>
|
||||
{Array.from(room.participants.values()).map((p) => (
|
||||
<details key={p.sid} className={styles.detailsSection}>
|
||||
<summary>
|
||||
<b>
|
||||
{p.identity}
|
||||
<span></span>
|
||||
</b>
|
||||
</summary>
|
||||
<div>
|
||||
{Array.from(p.tracks.values()).map((t) => (
|
||||
<>
|
||||
<div>
|
||||
<i>
|
||||
{t.source.toString()}
|
||||
<span>{t.trackSid}</span>
|
||||
</i>
|
||||
</div>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Kind</td>
|
||||
<td>
|
||||
{t.kind}
|
||||
{t.kind === 'video' && (
|
||||
<span>
|
||||
{t.dimensions?.width}x{t.dimensions?.height}
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td>{trackStatus(t)}</td>
|
||||
</tr>
|
||||
{t.track && (
|
||||
<tr>
|
||||
<td>Bitrate</td>
|
||||
<td>{Math.ceil(t.track.currentBitrate / 1000)} kbps</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
</details>
|
||||
))}
|
||||
</details>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
function trackStatus(t: RemoteTrackPublication): string {
|
||||
if (t.isSubscribed) {
|
||||
return t.isEnabled ? 'enabled' : 'disabled';
|
||||
} else {
|
||||
return 'unsubscribed';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
"next": "12.3.4",
|
||||
"next-seo": "^6.0.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"react-dom": "18.2.0",
|
||||
"tinykeys": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.17.1",
|
||||
|
@ -27,4 +28,4 @@
|
|||
"source-map-loader": "^4.0.1",
|
||||
"typescript": "5.1.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
16
styles/Debug.module.css
Normal file
16
styles/Debug.module.css
Normal file
|
@ -0,0 +1,16 @@
|
|||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
padding: 1rem;
|
||||
max-height: min(100%, 100vh);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.detailsSection {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.detailsSection > div {
|
||||
padding-left: 1rem;
|
||||
}
|
|
@ -2249,6 +2249,11 @@ text-table@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
|
||||
|
||||
tinykeys@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tinykeys/-/tinykeys-2.1.0.tgz#1341563e92a7fac9ca90053fddaf2b7553500298"
|
||||
integrity sha512-/MESnqBD1xItZJn5oGQ4OsNORQgJfPP96XSGoyu4eLpwpL0ifO0SYR5OD76u0YMhMXsqkb0UqvI9+yXTh4xv8Q==
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
|
|
Loading…
Add table
Reference in a new issue