fix: 修复挂断通话后仍然会显示正在使用摄像头/麦克风小红点的bug

pull/64/head
moonrailgun 2 years ago
parent 9f360ffa77
commit 98af14969a

@ -53,7 +53,8 @@ export const IconBtn: React.FC<IconBtnProps> = React.memo(
/>
);
if (isValidStr(title)) {
if (isValidStr(title) && !props.disabled) {
// 这里判断 props.disabled 是因为在禁用场景下显示title会有className无法带到Button组件上导致样式错误的问题(背景色溢出形状)
return <Tooltip title={title}>{btnEl}</Tooltip>;
} else {
return btnEl;

@ -1,6 +1,11 @@
import { useAsyncFn } from '@capital/common';
import { IconBtn } from '@capital/component';
import React from 'react';
import { useClient, useMicrophoneAndCameraTracks } from './client';
import {
useClient,
createMicrophoneAudioTrack,
createCameraVideoTrack,
} from './client';
import { useMeetingStore } from './store';
import { getClientLocalTrack } from './utils';
@ -8,42 +13,47 @@ export const Controls: React.FC<{
onClose: () => void;
}> = React.memo((props) => {
const client = useClient();
const { ready, tracks } = useMicrophoneAndCameraTracks();
const mediaPerm = useMeetingStore((state) => state.mediaPerm);
const mute = async (type: 'audio' | 'video') => {
if (type === 'audio') {
if (mediaPerm.audio === true) {
const track = getClientLocalTrack(client, 'audio');
if (track) {
await client.unpublish(track);
const [{ loading }, mute] = useAsyncFn(
async (type: 'audio' | 'video') => {
if (type === 'audio') {
if (mediaPerm.audio === true) {
const track = getClientLocalTrack(client, 'audio');
if (track) {
await client.unpublish(track);
}
} else {
const track = await createMicrophoneAudioTrack();
await client.publish(track);
}
} else {
await client.publish(tracks[0]);
}
useMeetingStore.getState().setMediaPerm({ audio: !mediaPerm.audio });
} else if (type === 'video') {
if (mediaPerm.video === true) {
const track = getClientLocalTrack(client, 'video');
if (track) {
await client.unpublish(track);
useMeetingStore.getState().setMediaPerm({ audio: !mediaPerm.audio });
} else if (type === 'video') {
if (mediaPerm.video === true) {
const track = getClientLocalTrack(client, 'video');
if (track) {
await client.unpublish(track);
}
} else {
const track = await createCameraVideoTrack();
await client.publish(track);
}
} else {
await client.publish(tracks[1]);
}
useMeetingStore.getState().setMediaPerm({ video: !mediaPerm.video });
}
};
useMeetingStore.getState().setMediaPerm({ video: !mediaPerm.video });
}
},
[client, mediaPerm]
);
const leaveChannel = async () => {
await client.leave();
client.removeAllListeners();
useMeetingStore.getState().reset();
// we close the tracks to perform cleanup
tracks[0].close();
tracks[1].close();
client.localTracks.forEach((track) => {
track.close();
});
props.onClose();
};
@ -53,7 +63,7 @@ export const Controls: React.FC<{
icon={mediaPerm.video ? 'mdi:video' : 'mdi:video-off'}
title={mediaPerm.video ? '关闭摄像头' : '开启摄像头'}
active={mediaPerm.video}
disabled={!ready}
disabled={loading}
size="large"
onClick={() => mute('video')}
/>
@ -62,7 +72,7 @@ export const Controls: React.FC<{
icon={mediaPerm.audio ? 'mdi:microphone' : 'mdi:microphone-off'}
title={mediaPerm.audio ? '关闭麦克风' : '开启麦克风'}
active={mediaPerm.audio}
disabled={!ready}
disabled={loading}
size="large"
onClick={() => mute('audio')}
/>

@ -2,8 +2,9 @@ import { UserAvatar, UserName } from '@capital/component';
import { AgoraVideoPlayer, IAgoraRTCRemoteUser } from 'agora-rtc-react';
import React from 'react';
import styled from 'styled-components';
import { useClient, useMicrophoneAndCameraTracks } from './client';
import { useClient } from './client';
import { useMeetingStore } from './store';
import { getClientLocalTrack } from './utils';
const Root = styled.div<{
active?: boolean;
@ -59,15 +60,20 @@ export const VideoView: React.FC<{
VideoView.displayName = 'VideoView';
export const OwnVideoView: React.FC<{}> = React.memo(() => {
const { ready, tracks } = useMicrophoneAndCameraTracks();
const client = useClient();
const mediaPerm = useMeetingStore((state) => state.mediaPerm);
const active = useVolumeActive(String(client.uid));
if (!client.uid) {
return null;
}
const videoTrack = getClientLocalTrack(client, 'video');
return (
<Root active={active}>
{ready && mediaPerm.video ? (
<AgoraVideoPlayer className="player" videoTrack={tracks[1]} />
{mediaPerm.video ? (
<AgoraVideoPlayer className="player" videoTrack={videoTrack} />
) : (
<UserAvatar size={96} userId={String(client.uid)} />
)}

@ -1,8 +1,4 @@
import {
ClientConfig,
createClient,
createMicrophoneAndCameraTracks,
} from 'agora-rtc-react';
import AgoraRTC, { ClientConfig, createClient } from 'agora-rtc-react';
const config: ClientConfig = {
mode: 'rtc',
@ -10,4 +6,5 @@ const config: ClientConfig = {
};
export const useClient = createClient(config);
export const useMicrophoneAndCameraTracks = createMicrophoneAndCameraTracks();
export const createCameraVideoTrack = AgoraRTC.createCameraVideoTrack;
export const createMicrophoneAudioTrack = AgoraRTC.createMicrophoneAudioTrack;

@ -1,11 +1,24 @@
import type { IAgoraRTCClient, ILocalTrack } from 'agora-rtc-react';
import type {
IAgoraRTCClient,
ILocalAudioTrack,
ILocalTrack,
ILocalVideoTrack,
} from 'agora-rtc-react';
/**
*
*/
export function getClientLocalTrack(
client: IAgoraRTCClient,
trackMediaType: 'audio' | 'video'
trackMediaType: 'video'
): ILocalVideoTrack | null;
export function getClientLocalTrack(
client: IAgoraRTCClient,
trackMediaType: 'audio'
): ILocalAudioTrack | null;
export function getClientLocalTrack(
client: IAgoraRTCClient,
trackMediaType: string
): ILocalTrack | null {
return (
client.localTracks.find(

Loading…
Cancel
Save