Merge pull request #889 from vector-im/SimonBrandner/feat/debug

This commit is contained in:
Šimon Brandner 2023-01-31 15:02:22 +01:00 committed by GitHub
commit 00385e91da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 63 additions and 0 deletions

View file

@ -101,6 +101,7 @@
"Sending…": "Sending…", "Sending…": "Sending…",
"Settings": "Settings", "Settings": "Settings",
"Share screen": "Share screen", "Share screen": "Share screen",
"Show call feed debug info": "Show call feed debug info",
"Show call inspector": "Show call inspector", "Show call inspector": "Show call inspector",
"Sign in": "Sign in", "Sign in": "Sign in",
"Sign out": "Sign out", "Sign out": "Sign out",

View file

@ -33,6 +33,7 @@ import {
useShowInspector, useShowInspector,
useOptInAnalytics, useOptInAnalytics,
canEnableSpatialAudio, canEnableSpatialAudio,
useShowCallFeedDebugInfo,
} from "./useSetting"; } from "./useSetting";
import { FieldRow, InputField } from "../input/Input"; import { FieldRow, InputField } from "../input/Input";
import { Button } from "../button"; import { Button } from "../button";
@ -60,6 +61,8 @@ export const SettingsModal = (props: Props) => {
const [spatialAudio, setSpatialAudio] = useSpatialAudio(); const [spatialAudio, setSpatialAudio] = useSpatialAudio();
const [showInspector, setShowInspector] = useShowInspector(); const [showInspector, setShowInspector] = useShowInspector();
const [showCallFeedDebugInfo, setShowCallFeedDebugInfo] =
useShowCallFeedDebugInfo();
const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics(); const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
const [keyboardShortcuts, setKeyboardShortcuts] = useKeyboardShortcuts(); const [keyboardShortcuts, setKeyboardShortcuts] = useKeyboardShortcuts();
@ -216,6 +219,18 @@ export const SettingsModal = (props: Props) => {
} }
/> />
</FieldRow> </FieldRow>
<FieldRow>
<InputField
id="showCallFeedDebugInfo"
name="callFeedDebugInfo"
label={t("Show call feed debug info")}
type="checkbox"
checked={showCallFeedDebugInfo}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setShowCallFeedDebugInfo(e.target.checked)
}
/>
</FieldRow>
<FieldRow> <FieldRow>
<Button onPress={downloadDebugLog}> <Button onPress={downloadDebugLog}>
{t("Download debug logs")} {t("Download debug logs")}

View file

@ -90,3 +90,5 @@ export const useShowInspector = () => useSetting("show-inspector", false);
export const useOptInAnalytics = () => useSetting("opt-in-analytics", false); export const useOptInAnalytics = () => useSetting("opt-in-analytics", false);
export const useKeyboardShortcuts = () => export const useKeyboardShortcuts = () =>
useSetting("keyboard-shortcuts", true); useSetting("keyboard-shortcuts", true);
export const useShowCallFeedDebugInfo = () =>
useSetting("show-call-feed-debug-info", false);

View file

@ -82,6 +82,7 @@ export const ParticipantsTest = () => {
name={`User ${item.id}`} name={`User ${item.id}`}
disableSpeakingIndicator={items.length < 3} disableSpeakingIndicator={items.length < 3}
connectionState={ConnectionState.Connected} connectionState={ConnectionState.Connected}
debugInfo={{ width: undefined, height: undefined }}
{...rest} {...rest}
/> />
)} )}

View file

@ -179,3 +179,10 @@ limitations under the License.
max-width: 360px; max-width: 360px;
border-radius: 20px; border-radius: 20px;
} }
.debugInfo {
position: absolute;
top: 16px;
left: 16px;
background-color: rgba(0, 0, 0, 0.5);
}

View file

@ -24,6 +24,8 @@ import { ReactComponent as MicMutedIcon } from "../icons/MicMuted.svg";
import { ReactComponent as VideoMutedIcon } from "../icons/VideoMuted.svg"; import { ReactComponent as VideoMutedIcon } from "../icons/VideoMuted.svg";
import { AudioButton, FullscreenButton } from "../button/Button"; import { AudioButton, FullscreenButton } from "../button/Button";
import { ConnectionState } from "../room/useGroupCall"; import { ConnectionState } from "../room/useGroupCall";
import { CallFeedDebugInfo } from "./useCallFeed";
import { useShowCallFeedDebugInfo } from "../settings/useSetting";
interface Props { interface Props {
name: string; name: string;
@ -44,6 +46,7 @@ interface Props {
showOptions?: boolean; showOptions?: boolean;
isLocal?: boolean; isLocal?: boolean;
disableSpeakingIndicator?: boolean; disableSpeakingIndicator?: boolean;
debugInfo: CallFeedDebugInfo;
} }
export const VideoTile = forwardRef<HTMLDivElement, Props>( export const VideoTile = forwardRef<HTMLDivElement, Props>(
@ -68,10 +71,12 @@ export const VideoTile = forwardRef<HTMLDivElement, Props>(
isLocal, isLocal,
// TODO: disableSpeakingIndicator is not used atm. // TODO: disableSpeakingIndicator is not used atm.
disableSpeakingIndicator, disableSpeakingIndicator,
debugInfo,
...rest ...rest
}, },
ref ref
) => { ) => {
const [showCallFeedDebugInfo] = useShowCallFeedDebugInfo();
const { t } = useTranslation(); const { t } = useTranslation();
const toolbarButtons: JSX.Element[] = []; const toolbarButtons: JSX.Element[] = [];
@ -125,6 +130,11 @@ export const VideoTile = forwardRef<HTMLDivElement, Props>(
ref={ref} ref={ref}
{...rest} {...rest}
> >
{showCallFeedDebugInfo && (
<div className={classNames(styles.debugInfo)}>
{JSON.stringify(debugInfo)}
</div>
)}
{toolbarButtons.length > 0 && !maximised && ( {toolbarButtons.length > 0 && !maximised && (
<div className={classNames(styles.toolbar)}>{toolbarButtons}</div> <div className={classNames(styles.toolbar)}>{toolbarButtons}</div>
)} )}

View file

@ -66,6 +66,7 @@ export function VideoTileContainer({
speaking, speaking,
stream, stream,
purpose, purpose,
debugInfo,
} = useCallFeed(item.callFeed); } = useCallFeed(item.callFeed);
const { rawDisplayName } = useRoomMemberName(item.member); const { rawDisplayName } = useRoomMemberName(item.member);
const [tileRef, mediaRef] = useSpatialMediaStream( const [tileRef, mediaRef] = useSpatialMediaStream(
@ -122,6 +123,7 @@ export function VideoTileContainer({
maximised={maximised} maximised={maximised}
fullscreen={fullscreen} fullscreen={fullscreen}
onFullscreen={onFullscreenCallback} onFullscreen={onFullscreenCallback}
debugInfo={debugInfo}
{...rest} {...rest}
/> />
{videoTileSettingsModalState.isOpen && !maximised && item.callFeed && ( {videoTileSettingsModalState.isOpen && !maximised && item.callFeed && (

View file

@ -18,6 +18,13 @@ import { useState, useEffect } from "react";
import { CallFeed, CallFeedEvent } from "matrix-js-sdk/src/webrtc/callFeed"; import { CallFeed, CallFeedEvent } from "matrix-js-sdk/src/webrtc/callFeed";
import { SDPStreamMetadataPurpose } from "matrix-js-sdk/src/webrtc/callEventTypes"; import { SDPStreamMetadataPurpose } from "matrix-js-sdk/src/webrtc/callEventTypes";
const DEBUG_INFO_INTERVAL = 1000; // ms
export interface CallFeedDebugInfo {
width: number | undefined;
height: number | undefined;
}
interface CallFeedState { interface CallFeedState {
callFeed: CallFeed | undefined; callFeed: CallFeed | undefined;
isLocal: boolean; isLocal: boolean;
@ -29,6 +36,14 @@ interface CallFeedState {
disposed: boolean | undefined; disposed: boolean | undefined;
stream: MediaStream | undefined; stream: MediaStream | undefined;
purpose: SDPStreamMetadataPurpose | undefined; purpose: SDPStreamMetadataPurpose | undefined;
debugInfo: CallFeedDebugInfo;
}
function getDebugInfo(callFeed: CallFeed | undefined): CallFeedDebugInfo {
return {
width: callFeed?.stream?.getVideoTracks()?.[0]?.getSettings()?.width,
height: callFeed?.stream?.getVideoTracks()?.[0]?.getSettings()?.height,
};
} }
function getCallFeedState(callFeed: CallFeed | undefined): CallFeedState { function getCallFeedState(callFeed: CallFeed | undefined): CallFeedState {
@ -46,6 +61,7 @@ function getCallFeedState(callFeed: CallFeed | undefined): CallFeedState {
disposed: callFeed ? callFeed.disposed : undefined, disposed: callFeed ? callFeed.disposed : undefined,
stream: callFeed ? callFeed.stream : undefined, stream: callFeed ? callFeed.stream : undefined,
purpose: callFeed ? callFeed.purpose : undefined, purpose: callFeed ? callFeed.purpose : undefined,
debugInfo: getDebugInfo(callFeed),
}; };
} }
@ -81,7 +97,16 @@ export function useCallFeed(callFeed: CallFeed | undefined): CallFeedState {
onUpdateCallFeed(); onUpdateCallFeed();
const debugInfoInterval = setInterval(() => {
setState((prevState) => ({
...prevState,
debugInfo: getDebugInfo(callFeed),
}));
}, DEBUG_INFO_INTERVAL);
return () => { return () => {
clearInterval(debugInfoInterval);
if (callFeed) { if (callFeed) {
callFeed.removeListener(CallFeedEvent.Speaking, onSpeaking); callFeed.removeListener(CallFeedEvent.Speaking, onSpeaking);
callFeed.removeListener( callFeed.removeListener(