feat: 声网插件网络质量检测与双流功能与头像

pull/64/head
moonrailgun 2 years ago
parent e27094d0f2
commit 141db8f1cf

@ -1,6 +1,5 @@
import React, { useEffect, useRef, useState } from 'react';
import { getJWTUserInfo, isValidStr, showErrorToasts } from '@capital/common';
import type { IAgoraRTCRemoteUser } from 'agora-rtc-react';
import { useClient } from './client';
import { Videos } from './Videos';
import { Controls } from './Controls';
@ -9,6 +8,7 @@ import { useMemoizedFn } from 'ahooks';
import { request } from '../request';
import styled from 'styled-components';
import { useMeetingStore } from './store';
import { NetworkStats } from './NetworkStats';
const Root = styled.div`
.body {
@ -74,7 +74,7 @@ export const MeetingView: React.FC<MeetingViewProps> = React.memo((props) => {
const { appId, token } = data ?? {};
await client.join(appId, channelName, token, _id);
console.log('client.remoteUsers', client.remoteUsers);
await client.enableDualStream();
setStart(true);
} catch (err) {
showErrorToasts(err);
@ -94,6 +94,8 @@ export const MeetingView: React.FC<MeetingViewProps> = React.memo((props) => {
return (
<Root>
<NetworkStats />
<div className="body">
{start ? <Videos /> : <LoadingSpinner tip={'正在加入通话...'} />}
</div>

@ -0,0 +1,78 @@
import { localTrans } from '@capital/common';
import type { NetworkQuality } from 'agora-rtc-react';
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import { Translate } from '../translate';
import { useClient } from './client';
const Root = styled.div`
display: flex;
position: absolute;
padding: 4px 8px;
z-index: 20;
div + div {
margin-left: 8px;
}
`;
export const NetworkStats: React.FC = React.memo(() => {
const client = useClient();
const [stats, setStats] = useState<NetworkQuality>(undefined);
useEffect(() => {
const cb = (stats: NetworkQuality) => {
setStats(stats);
};
client.on('network-quality', cb);
return () => {
client.off('network-quality', cb);
};
}, []);
if (!stats) {
return null;
}
return (
<Root>
<div>
{Translate.uplink}: {parseQualityText(stats.uplinkNetworkQuality)}
</div>
<div>
{Translate.downlink}: {parseQualityText(stats.downlinkNetworkQuality)}
</div>
</Root>
);
});
NetworkStats.displayName = 'NetworkStats';
function parseQualityText(quality: 0 | 1 | 2 | 3 | 4 | 5 | 6) {
if (quality === 1 || quality === 2) {
return localTrans({
'zh-CN': '优秀',
'en-US': 'Good',
});
}
if (quality === 3 || quality === 4) {
return localTrans({
'zh-CN': '一般',
'en-US': 'Normal',
});
}
if (quality === 5 || quality === 6) {
return localTrans({
'zh-CN': '差',
'en-US': 'Bad',
});
}
return localTrans({
'zh-CN': '未知',
'en-US': 'Unknown',
});
}

@ -1,4 +1,4 @@
import { UserName } from '@capital/component';
import { UserAvatar, UserName } from '@capital/component';
import { AgoraVideoPlayer, IAgoraRTCRemoteUser } from 'agora-rtc-react';
import React from 'react';
import styled from 'styled-components';
@ -15,6 +15,9 @@ const Root = styled.div`
justify-self: center;
align-self: center;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
.player {
width: 100%;
@ -36,8 +39,10 @@ export const VideoView: React.FC<{
return (
<Root>
{user.hasVideo && (
{user.hasVideo ? (
<AgoraVideoPlayer className="player" videoTrack={user.videoTrack} />
) : (
<UserAvatar size={96} userId={String(user.uid)} />
)}
<UserName className="name" userId={String(user.uid)} />
@ -53,8 +58,10 @@ export const OwnVideoView: React.FC<{}> = React.memo(() => {
return (
<Root>
{ready && mediaPerm.video && (
{ready && mediaPerm.video ? (
<AgoraVideoPlayer className="player" videoTrack={tracks[1]} />
) : (
<UserAvatar size={96} userId={String(client.uid)} />
)}
<UserName className="name" userId={String(client.uid)} />

@ -0,0 +1,12 @@
import { localTrans } from '@capital/common';
export const Translate = {
uplink: localTrans({
'zh-CN': '上行网络',
'en-US': 'Uplink',
}),
downlink: localTrans({
'zh-CN': '下行网络',
'en-US': 'Downlink',
}),
};
Loading…
Cancel
Save