feat: voice dashboard

This commit is contained in:
Tristan Yang
2023-03-24 11:05:51 +08:00
parent ecfa3b8f24
commit da00f3b797
10 changed files with 100 additions and 32 deletions
+2 -1
View File
@@ -45,5 +45,6 @@
"file": "file", "file": "file",
"image": "image", "image": "image",
"forward": "forward" "forward": "forward",
"voice": "Voice"
} }
+2 -1
View File
@@ -46,5 +46,6 @@
"file": "文件", "file": "文件",
"image": "图片", "image": "图片",
"forward": "转发" "forward": "转发",
"voice": "音频通话"
} }
+9 -2
View File
@@ -16,7 +16,8 @@ import {
GithubAuthConfig, GithubAuthConfig,
LicenseResponse, LicenseResponse,
RenewLicense, RenewLicense,
RenewLicenseResponse RenewLicenseResponse,
AgoraTokenResponse
} from "../../types/server"; } from "../../types/server";
import { Channel } from "../../types/channel"; import { Channel } from "../../types/channel";
import { ContentTypeKey } from "../../types/message"; import { ContentTypeKey } from "../../types/message";
@@ -109,6 +110,11 @@ export const serverApi = createApi({
body: data body: data
}) })
}), }),
getAgoraToken: builder.query<AgoraTokenResponse, number>({
query: (id) => ({
url: `group/${id}/agora_token`,
})
}),
getSMTPConfig: builder.query<SMTPConfig, void>({ getSMTPConfig: builder.query<SMTPConfig, void>({
query: () => ({ url: `admin/smtp/config` }) query: () => ({ url: `admin/smtp/config` })
}), }),
@@ -320,5 +326,6 @@ export const {
useLazyGetBotRelatedChannelsQuery, useLazyGetBotRelatedChannelsQuery,
useSendMessageByBotMutation, useSendMessageByBotMutation,
useUpdateFrontendUrlMutation, useUpdateFrontendUrlMutation,
useGetFrontendUrlQuery useGetFrontendUrlQuery,
useLazyGetAgoraTokenQuery
} = serverApi; } = serverApi;
+1 -1
View File
@@ -84,7 +84,7 @@ function ChannelChat({ cid = 0, dropFiles = [] }: Props) {
</li> </li>
</Tippy> </Tippy>
</Tooltip> </Tooltip>
<VoiceChat channel={`channel_${cid}`} /> <VoiceChat channel={`channel_${cid}`} id={cid} />
<Tooltip tip={t("fav")} placement="left"> <Tooltip tip={t("fav")} placement="left">
<Tippy <Tippy
placement="left-start" placement="left-start"
+26 -20
View File
@@ -3,20 +3,24 @@ import AgoraRTC from "agora-rtc-sdk-ng";
import useConfig from '../../../common/hook/useConfig'; import useConfig from '../../../common/hook/useConfig';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { updateVoiceStatus } from '../../../app/slices/auth.data'; import { updateVoiceStatus } from '../../../app/slices/auth.data';
import { useLazyGetAgoraTokenQuery } from '../../../app/services/server';
import VoiceManagement from './VoiceManagement';
import JoinVoice from './JoinVoice';
type Props = { type Props = {
channel: string, channel: string,
id: number,
uid: number, uid: number,
voicing?: boolean; voicing?: boolean;
} }
const Dashboard = ({ voicing, uid, channel }: Props) => { const Dashboard = ({ id, voicing, uid, channel }: Props) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
console.log("aaaaa"); const [generateToken] = useLazyGetAgoraTokenQuery();
const { agoraConfig } = useConfig("agora"); const { agoraConfig } = useConfig("agora");
useEffect(() => { useEffect(() => {
console.log("aaa", agoraConfig); console.log("agora config", agoraConfig);
const startConnect = async () => { const startConnect = async () => {
// Create an instance of the Agora Engine // Create an instance of the Agora Engine
const agoraEngine = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" }); const agoraEngine = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" });
@@ -27,17 +31,16 @@ const Dashboard = ({ voicing, uid, channel }: Props) => {
await agoraEngine.subscribe(user, mediaType); await agoraEngine.subscribe(user, mediaType);
console.log("subscribe success"); console.log("subscribe success");
// // Subscribe and play the remote audio track. // Subscribe and play the remote audio track.
// if (mediaType == "audio") if (mediaType == "audio") {
// {
// channelParameters.remoteUid=user.uid; // channelParameters.remoteUid=user.uid;
// // Get the RemoteAudioTrack object from the AgoraRTCRemoteUser object. // // Get the RemoteAudioTrack object from the AgoraRTCRemoteUser object.
// channelParameters.remoteAudioTrack = user.audioTrack; // channelParameters.remoteAudioTrack = user.audioTrack;
// // Play the remote audio track. // Play the remote audio track.
// channelParameters.remoteAudioTrack.play(); user.audioTrack?.play();
// console.log("Remote user connected: " + user.uid); console.log("Remote user connected: " + user.uid);
// } }
// Listen for the "user-unpublished" event. // Listen for the "user-unpublished" event.
agoraEngine.on("user-unpublished", user => { agoraEngine.on("user-unpublished", user => {
@@ -47,14 +50,19 @@ const Dashboard = ({ voicing, uid, channel }: Props) => {
}); });
// Join a channel. // Join a channel.
console.log("join data ", agoraConfig); console.log("join data ", agoraConfig);
await agoraEngine.join(agoraConfig!.app_id, agoraConfig!.rtm_key, agoraConfig!.rtm_secret, uid); const { isError, data } = await generateToken(id);
console.log("Joined channel: " + agoraConfig!.rtm_key); if (!isError && data) {
// // Create a local audio track from the microphone audio. const { channel_name, app_id, agora_token, uid } = data;
// channelParameters.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack(); await agoraEngine.join(app_id, channel_name, agora_token, uid);
// // Publish the local audio track in the channel. console.table(data);
// await agoraEngine.publish(channelParameters.localAudioTrack); // Create a local audio track from the microphone audio.
// console.log("Publish success!"); const localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
// Publish the local audio track in the channel.
await agoraEngine.publish(localAudioTrack);
console.log("Publish success!");
dispatch(updateVoiceStatus(true)); dispatch(updateVoiceStatus(true));
}
}; };
if (!voicing && agoraConfig) { if (!voicing && agoraConfig) {
@@ -62,9 +70,7 @@ const Dashboard = ({ voicing, uid, channel }: Props) => {
} }
}, [voicing, agoraConfig, uid, channel]); }, [voicing, agoraConfig, uid, channel]);
return ( return voicing ? <VoiceManagement /> : <JoinVoice />;
<div>Dashboard</div>
);
}; };
export default Dashboard; export default Dashboard;
+11
View File
@@ -0,0 +1,11 @@
import React from 'react';
type Props = {}
const JoinVoice = (props: Props) => {
return (
<div>JoinVoice</div>
);
};
export default JoinVoice;
@@ -0,0 +1,11 @@
import React from 'react';
type Props = {}
const VoiceManagement = (props: Props) => {
return (
<div>VoiceManagement</div>
);
};
export default VoiceManagement;
+4 -3
View File
@@ -7,23 +7,24 @@ import Tooltip from '../../../common/component/Tooltip';
import Dashboard from './Dashboard'; import Dashboard from './Dashboard';
type Props = { type Props = {
id: number,
channel: string channel: string
} }
const VoiceChat = ({ channel }: Props) => { const VoiceChat = ({ channel, id }: Props) => {
const { loginUser, voice } = useAppSelector(store => { return { loginUser: store.authData.user, voice: store.authData.voice }; }); const { loginUser, voice } = useAppSelector(store => { return { loginUser: store.authData.user, voice: store.authData.voice }; });
const { t } = useTranslation("chat"); const { t } = useTranslation("chat");
const toolClass = `relative cursor-pointer`; const toolClass = `relative cursor-pointer`;
if (!loginUser) return null; if (!loginUser) return null;
return ( return (
<Tooltip tip={t("fav")} placement="left"> <Tooltip tip={t("voice")} placement="left">
<Tippy <Tippy
placement="left-start" placement="left-start"
popperOptions={{ strategy: "fixed" }} popperOptions={{ strategy: "fixed" }}
offset={[0, 164]} offset={[0, 164]}
interactive interactive
trigger="click" trigger="click"
content={<Dashboard uid={loginUser.uid} channel={channel} voicing={voice} />} content={<Dashboard id={id} uid={loginUser.uid} channel={channel} voicing={voice} />}
> >
<li className={`${toolClass}`}> <li className={`${toolClass}`}>
<IconHeadphone className="fill-gray-500" /> <IconHeadphone className="fill-gray-500" />
+23
View File
@@ -0,0 +1,23 @@
import { useState } from "react";
import { useAppSelector } from "../../../app/store";
const useVoice = (uid: number) => {
const [engine, setEngine] = useState(window.VoiceEngine);
const { voicing } = useAppSelector(store => {
return {
voicing: store.users.byId[uid].voice ?? false
};
});
return {
voicing,
};
};
export default useVoice;
+7
View File
@@ -27,6 +27,13 @@ export interface AgoraConfig {
rtm_key: string; rtm_key: string;
rtm_secret: string; rtm_secret: string;
} }
export interface AgoraTokenResponse {
agora_token: string,
uid: number,
channel_name: string,
expired_in: number,
app_id: string;
}
export interface SMTPConfig { export interface SMTPConfig {
enabled: boolean; enabled: boolean;
host: string; host: string;