feat: voice dashboard
This commit is contained in:
@@ -45,5 +45,6 @@
|
|||||||
|
|
||||||
"file": "file",
|
"file": "file",
|
||||||
"image": "image",
|
"image": "image",
|
||||||
"forward": "forward"
|
"forward": "forward",
|
||||||
|
"voice": "Voice"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,5 +46,6 @@
|
|||||||
|
|
||||||
"file": "文件",
|
"file": "文件",
|
||||||
"image": "图片",
|
"image": "图片",
|
||||||
"forward": "转发"
|
"forward": "转发",
|
||||||
|
"voice": "音频通话"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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.
|
user.audioTrack?.play();
|
||||||
// channelParameters.remoteAudioTrack.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();
|
||||||
dispatch(updateVoiceStatus(true));
|
// Publish the local audio track in the channel.
|
||||||
|
await agoraEngine.publish(localAudioTrack);
|
||||||
|
console.log("Publish success!");
|
||||||
|
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;
|
||||||
@@ -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;
|
||||||
@@ -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" />
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user