From 23191fd3bf5b48c812207386a4f7c5a95daee505 Mon Sep 17 00:00:00 2001 From: Tristan Yang Date: Tue, 16 May 2023 14:54:29 +0800 Subject: [PATCH] refactor: calling --- package.json | 4 +- public/locales/en/setting.json | 5 +- public/locales/zh/setting.json | 1 - src/app/slices/voice.ts | 15 ++++- src/components/Voice/DMCalling.tsx | 10 ++-- src/components/Voice/index.tsx | 11 +++- src/components/Voice/useVoice.ts | 6 +- src/hooks/useStreaming/index.ts | 6 ++ src/routes/chat/Layout/DMVoicing.tsx | 16 +++--- src/routes/chat/VoiceChat/index.tsx | 4 +- src/types/sse.ts | 8 ++- yarn.lock | 82 ++++++++++++++-------------- 12 files changed, 99 insertions(+), 69 deletions(-) diff --git a/package.json b/package.json index 7854acda..5dfcd4a8 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "@toast-ui/editor": "^3.2.2", "@toast-ui/editor-plugin-code-syntax-highlight": "^3.1.0", "@toast-ui/react-editor": "^3.2.3", - "@types/node": "^20.1.2", + "@types/node": "^20.1.4", "@types/react": "^18.2.6", "@types/react-dom": "^18.2.4", "@udecode/plate": "16.8", @@ -32,7 +32,7 @@ "emoji-mart": "5.5.2", "eslint": "^8.40.0", "file-loader": "^6.2.0", - "firebase": "^9.21.0", + "firebase": "^9.22.0", "framer-motion": "^10.12.10", "fs-extra": "^11.1.1", "html-webpack-plugin": "^5.5.1", diff --git a/public/locales/en/setting.json b/public/locales/en/setting.json index 31565994..42638fb9 100644 --- a/public/locales/en/setting.json +++ b/public/locales/en/setting.json @@ -42,7 +42,6 @@ }, "overview": { "title_feat": "Features", - "title_feat_desc": "you can toggle features as you need", "name": "Server Name", "desc": "Server Description", "upload_desc": "Minimum size is 128x128, We recommend at least 512x512 for the server. Max size limited to 5M.", @@ -85,9 +84,9 @@ }, "chat_layout": { "title": "Chat Layout", - "desc": "message self send on the left or right", + "desc": "Which side to show messages sent by yourself", "left": "Left", - "self_right": "Self Right" + "self_right": "Right" }, "contact_verify": { "title": "Contact Verification", diff --git a/public/locales/zh/setting.json b/public/locales/zh/setting.json index e3eee7b1..08d595d4 100644 --- a/public/locales/zh/setting.json +++ b/public/locales/zh/setting.json @@ -39,7 +39,6 @@ }, "overview": { "title_feat": "特性开关", - "title_feat_desc": "根据你的需要开启或关闭特性", "name": "服务器名", "desc": "服务器描述", "upload_desc": "图片最小 128x128,我们推荐上传 512x512 大小的图片,最大不要超过5M。", diff --git a/src/app/slices/voice.ts b/src/app/slices/voice.ts index 4c2ffb20..b932c118 100644 --- a/src/app/slices/voice.ts +++ b/src/app/slices/voice.ts @@ -38,6 +38,7 @@ export type VoiceInfo = { interface State { callingFrom: number, callingTo: number, + calling: boolean, voicing: VoicingInfo | null, voicingMembers: VoicingMembers, list: VoiceInfo[] @@ -48,6 +49,7 @@ interface State { // members: [] // }; const initialState: State = { + calling: false, callingFrom: 0, callingTo: 0, voicing: null, @@ -64,10 +66,16 @@ const voiceSlice = createSlice({ name: "voice", initialState, reducers: { - updateCalling(state, { payload }: PayloadAction<{ from: number, to?: number }>) { - const { from, to = 0 } = payload; + updateCallInfo(state, { payload }: PayloadAction<{ from: number, to?: number, calling?: boolean }>) { + const { from, to = 0, calling } = payload; state.callingFrom = from; state.callingTo = to; + if (typeof calling === "boolean") { + state.calling = calling; + } + }, + updateCalling(state, { payload }: PayloadAction) { + state.calling = payload; }, updateVoicingInfo(state, { payload }: PayloadAction) { if (payload) { @@ -182,6 +190,7 @@ const voiceSlice = createSlice({ }); } state.voicing = null; + state.calling = false; state.voicingMembers = { ids: [], byId: {} @@ -190,5 +199,5 @@ const voiceSlice = createSlice({ } }); -export const { updateCalling, updatePin, updateConnectionState, addVoiceMember, removeVoiceMember, upsertVoiceList, updateVoicingInfo, updateVoicingNetworkQuality, updateVoicingMember } = voiceSlice.actions; +export const { updateCalling, updateCallInfo, updatePin, updateConnectionState, addVoiceMember, removeVoiceMember, upsertVoiceList, updateVoicingInfo, updateVoicingNetworkQuality, updateVoicingMember } = voiceSlice.actions; export default voiceSlice.reducer; diff --git a/src/components/Voice/DMCalling.tsx b/src/components/Voice/DMCalling.tsx index 479d95c7..bc202010 100644 --- a/src/components/Voice/DMCalling.tsx +++ b/src/components/Voice/DMCalling.tsx @@ -26,9 +26,10 @@ const DMCalling = ({ from, to = 0 }: Props) => { const dispatch = useDispatch(); const { leave, joinVoice, joining } = useVoice({ id: to, context: "dm" }); const containerRef = useRef(null); - const { voicingInfo, voicingMembers, fromUser, toUser, loginUser } = useAppSelector(store => { + const { calling, voicingMembers, fromUser, toUser, loginUser } = useAppSelector(store => { return { - voicingInfo: store.voice.voicing ?? {}, + calling: store.voice.calling, + // voicingInfo: store.voice.voicing ?? {}, voicingMembers: store.voice.voicingMembers, fromUser: store.users.byId[from], toUser: store.users.byId[to], @@ -48,7 +49,8 @@ const DMCalling = ({ from, to = 0 }: Props) => { if (sendByMe || voicingMembers.ids.length == 2) { leave(); } - dispatch(updateCalling({ from: 0, to: 0 })); + // 拒绝 + dispatch(updateCalling(false)); }; const handleAnswer = () => { joinVoice(); @@ -58,7 +60,7 @@ const DMCalling = ({ from, to = 0 }: Props) => { const connected = voicingMembers.ids.length == 2; console.log("dm calling", !fromUser, !toUser, connected); const atChatPath = sendByMe ? pathname == `/chat/dm/${to}` : pathname == `/chat/dm/${from}`; - if (!fromUser || !toUser || connected || atChatPath) return null; + if (!fromUser || !toUser || connected || atChatPath || !calling) return null; return (
diff --git a/src/components/Voice/index.tsx b/src/components/Voice/index.tsx index 0323bc69..6eccc686 100644 --- a/src/components/Voice/index.tsx +++ b/src/components/Voice/index.tsx @@ -2,7 +2,7 @@ import AgoraRTC from 'agora-rtc-sdk-ng'; import { memo, useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { useGetAgoraChannelsQuery, useGetAgoraStatusQuery, useLazyGetAgoraUsersByChannelQuery } from '../../app/services/server'; -import { addVoiceMember, removeVoiceMember, updateCalling, updateConnectionState, updateVoicingMember, updateVoicingNetworkQuality } from '../../app/slices/voice'; +import { addVoiceMember, removeVoiceMember, updateCallInfo, updateConnectionState, updateVoicingMember, updateVoicingNetworkQuality } from '../../app/slices/voice'; import { useAppSelector } from '../../app/store'; import { playAgoraVideo } from '../../utils'; import useVoice from './useVoice'; @@ -86,7 +86,7 @@ const Voice = () => { window.VIDEO_TRACK_MAP[+user.uid] = null; if (voicingInfo && voicingInfo.context == "dm") { // 有人离开,就断开 - dispatch(updateCalling({ from: 0 })); + dispatch(updateCallInfo({ from: 0 })); } } break; @@ -161,6 +161,7 @@ const Voice = () => { }; }, [voicingInfo]); + useEffect(() => { // 有人呼叫我 const callMeList = voiceList.filter(item => item.context == "dm" && item.id == loginUid); @@ -168,14 +169,18 @@ const Voice = () => { const [firstCall] = callMeList; const { memberCount, channelName, id } = firstCall; if (memberCount == 1) { + // 呼叫的人在频道里 getUsersByChannel(channelName).then(resp => { const [uid] = resp.data ?? []; if (uid) { - dispatch(updateCalling({ from: uid, to: id })); + dispatch(updateCallInfo({ from: uid, to: id })); } }); } } + // else { + // dispatch(updateCallInfo({ from: 0, to: 0, calling: false })); + // } }, [voiceList, loginUid]); // return ; if (from !== 0) return ; diff --git a/src/components/Voice/useVoice.ts b/src/components/Voice/useVoice.ts index 5da74cd2..fea7b519 100644 --- a/src/components/Voice/useVoice.ts +++ b/src/components/Voice/useVoice.ts @@ -52,7 +52,11 @@ const useVoice = ({ id, context = "channel" }: VoiceProps) => { // Publish the local audio track in the channel. await window.VOICE_CLIENT.publish(localAudioTrack); // play the join audio - audioJoin.play(); + try { + await audioJoin.play(); + } catch (error) { + console.warn("play join sound failed!", error); + } console.log("Publish success!,joined the channel"); dispatch(updateVoicingInfo({ deafen: false, diff --git a/src/hooks/useStreaming/index.ts b/src/hooks/useStreaming/index.ts index b5793d25..cdd0a731 100644 --- a/src/hooks/useStreaming/index.ts +++ b/src/hooks/useStreaming/index.ts @@ -30,6 +30,7 @@ import { useRenewMutation } from "@/app/services/auth"; import { getLocalAuthData } from "@/utils"; import { removeUserSession } from "@/app/slices/message.user"; import { clearChannelMessage, removeChannelSession } from "@/app/slices/message.channel"; +import { updateCallInfo } from "@/app/slices/voice"; const getQueryString = (params: { [key: string]: string }) => { const sp = new URLSearchParams(); @@ -151,6 +152,11 @@ export default function useStreaming() { dispatch(clearChannelMessage(gid)); break; } + case "user_calling": { + const { target, uid } = data; + dispatch(updateCallInfo({ from: uid, to: target, calling: true })); + break; + } case "pinned_chats": { const { chats } = data; dispatch(upsertPinChats({ pins: chats, override: true })); diff --git a/src/routes/chat/Layout/DMVoicing.tsx b/src/routes/chat/Layout/DMVoicing.tsx index a51ca786..02f7c146 100644 --- a/src/routes/chat/Layout/DMVoicing.tsx +++ b/src/routes/chat/Layout/DMVoicing.tsx @@ -13,7 +13,7 @@ import IconMic from '@/assets/icons/mic.on.svg'; import IconCamera from '@/assets/icons/camera.svg'; import IconCameraOff from '@/assets/icons/camera.off.svg'; import IconScreen from '@/assets/icons/share.screen.svg'; -import { VoicingInfo, updateCalling } from "@/app/slices/voice"; +import { VoicingInfo, updateCallInfo } from "@/app/slices/voice"; import { useVoice } from "@/components/Voice"; import { playAgoraVideo } from "@/utils"; import Avatar from "@/components/Avatar"; @@ -32,13 +32,13 @@ type BlockProps = { to: VoicingMember } const VoicingBlocks = ({ sendByMe, connected, from, to }: BlockProps) => { - const blocks = [from, to].map(({ id, speaking, name, avatar, video }, idx) => { - const showWaiting = idx == 1 && !connected && sendByMe; + const showWaiting = idx == 1 && !connected && !sendByMe; + const showToWaiting = idx == 1 && !connected && sendByMe; return
-
+
{speaking &&
} - {showWaiting &&
} + {showToWaiting &&
} { if (sendByMe || voicingMembers.ids.length == 2) { leave(); } - dispatch(updateCalling({ from: 0, to: 0 })); + dispatch(updateCallInfo({ from: 0, to: 0 })); }; const handleAnswer = () => { joinVoice(); @@ -117,11 +117,11 @@ const DMVoice = ({ uid }: Props) => { }} />
- + {(sendByMe || connected) && - + } {!sendByMe && !connected &&