diff --git a/packages/client/src/Call.ts b/packages/client/src/Call.ts index 1230684d3b..1e0706250f 100644 --- a/packages/client/src/Call.ts +++ b/packages/client/src/Call.ts @@ -2238,13 +2238,10 @@ export class Call { /** * Allows you to grant or revoke a specific permission to a user in a call. The permissions are specific to the call experience and do not survive the call itself. - * * When revoking a permission, this endpoint will also mute the relevant track from the user. This is similar to muting a user with the difference that the user will not be able to unmute afterwards. - * * Supported permissions that can be granted or revoked: `send-audio`, `send-video` and `screenshare`. * * `call.permissions_updated` event is sent to all members of the call. - * */ updateUserPermissions = async (data: UpdateUserPermissionsRequest) => { return this.streamClient.post< @@ -2561,6 +2558,33 @@ export class Call { return this.streamClient.get(endpoint, params); }; + /** + * Loads the call report for the given session ID. + */ + getCallParticipantsStats = async (opts: { + sessionId?: string; + userId?: string; + userSessionId?: string; + kind?: 'timeline' | 'details'; + }): Promise => { + const { + sessionId = this.state.session?.id, + userId = this.currentUserId, + userSessionId = this.unifiedSessionId, + kind = 'details', + } = opts; + // FIXME OL: not yet part of the API + if (!sessionId) return; + const base = `${this.streamClient.baseURL}/call_stats/${this.type}/${this.id}/${sessionId}`; + const endpoint = + userId && userSessionId + ? kind === 'details' + ? `${base}/participant/${userId}/${userSessionId}/details` + : `${base}/participants/${userId}/${userSessionId}/timeline` + : `${base}/participants`; + return this.streamClient.get(endpoint); + }; + /** * Submit user feedback for the call * diff --git a/sample-apps/react/react-dogfood/components/DevMenu.tsx b/sample-apps/react/react-dogfood/components/DevMenu.tsx index 0c954288db..2b4f257796 100644 --- a/sample-apps/react/react-dogfood/components/DevMenu.tsx +++ b/sample-apps/react/react-dogfood/components/DevMenu.tsx @@ -4,6 +4,8 @@ import { getConnectionString } from '../lib/connectionString'; export const DevMenu = () => { const call = useCall(); + const { useLocalParticipant } = useCallStateHooks(); + const localParticipant = useLocalParticipant(); return ( ); }; diff --git a/sample-apps/react/react-dogfood/pages/stats/[cid].tsx b/sample-apps/react/react-dogfood/pages/stats/[cid].tsx new file mode 100644 index 0000000000..5d710b3816 --- /dev/null +++ b/sample-apps/react/react-dogfood/pages/stats/[cid].tsx @@ -0,0 +1,70 @@ +import { useEffect, useState } from 'react'; +import { useRouter } from 'next/router'; +import { + getServerSideCredentialsProps, + ServerSideCredentialsProps, +} from '../../lib/getServerSideCredentialsProps'; +import { useAppEnvironment } from '../../context/AppEnvironmentContext'; +import { getClient } from '../../helpers/client'; + +export default function Stats(props: ServerSideCredentialsProps) { + const { apiKey, userToken, user } = props; + const environment = useAppEnvironment(); + const router = useRouter(); + const cid = router.query['cid'] as string; + const [data, setData] = useState({ message: 'Loading...' }); + + useEffect(() => { + const useLocalCoordinator = + router.query['use_local_coordinator'] === 'true'; + const coordinatorUrl = useLocalCoordinator + ? 'http://localhost:3030/video' + : (router.query['coordinator_url'] as string | undefined); + const callSessionId = router.query['call_session_id'] as string | undefined; + const _client = getClient( + { apiKey, user, userToken, coordinatorUrl }, + environment, + ); + window.client = _client; + + const [type, id] = cid.split(':'); + const _call = _client.call(type, id, { reuseInstance: true }); + (async () => { + try { + await _call.get(); + const userId = + (router.query['user_id'] as string | undefined) || user.id; + const userSessionId = router.query['user_session_id'] as + | string + | undefined; + const kind = + (router.query['kind'] as 'details' | 'timeline') || 'details'; + const stats = await _call.getCallParticipantsStats({ + userId, + userSessionId, + sessionId: callSessionId, + kind, + }); + console.log('Call participants stats:', stats); + setData(stats); + } catch (err) { + setData({ message: 'Failed to get call participants stats', err }); + } + })(); + + return () => { + _client + .disconnectUser() + .catch((e) => console.error('Failed to disconnect user', e)); + + window.client = undefined; + }; + }, [apiKey, user, userToken, environment, cid, router.query]); + + return ( +
+      {data && JSON.stringify(data, null, 2)}
+    
+ ); +} +export const getServerSideProps = getServerSideCredentialsProps;