From 928f1a25b212e382beee948792b8a0381625a358 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Tue, 27 Dec 2022 00:03:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A3=B0=E7=BD=91=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0ahooks=E5=B9=B6=E4=BC=98=E5=8C=96=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pnpm-lock.yaml | 56 +++++++++ .../plugins/com.msgbyte.agora/.ministarrc.js | 4 + server/plugins/com.msgbyte.agora/package.json | 1 + .../plugins/com.msgbyte.agora/package.json | 3 +- .../src/FloatWindow/Controls.tsx | 28 +++-- .../src/FloatWindow/Videos.tsx | 10 +- .../src/FloatWindow/window.tsx | 109 +++++++++--------- 7 files changed, 138 insertions(+), 73 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9256d8c5..6a987d5d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -947,6 +947,7 @@ importers: server/plugins/com.msgbyte.agora: specifiers: + '@rollup/plugin-replace': ^5.0.2 '@types/react': 18.0.20 got: 11.8.6 mini-star: '*' @@ -957,6 +958,7 @@ importers: got: 11.8.6 tailchat-server-sdk: link:../../packages/sdk devDependencies: + '@rollup/plugin-replace': 5.0.2 '@types/react': 18.0.20 mini-star: 2.0.5 normalize-path: 3.0.0 @@ -966,10 +968,12 @@ importers: specifiers: '@types/styled-components': ^5.1.26 agora-rtc-react: ^1.1.3 + ahooks: ^3.7.4 react: 18.2.0 styled-components: ^5.3.6 dependencies: agora-rtc-react: 1.1.3_react@18.2.0 + ahooks: 3.7.4_react@18.2.0 devDependencies: '@types/styled-components': 5.1.26 react: 18.2.0 @@ -8394,6 +8398,19 @@ packages: rollup: 2.79.1 dev: true + /@rollup/plugin-replace/5.0.2: + resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@rollup/pluginutils': 5.0.2 + magic-string: 0.27.0 + dev: true + /@rollup/plugin-url/6.1.0_rollup@2.78.1: resolution: {integrity: sha512-FJNWBnBB7nLzbcaGmu1no+U/LlRR67TtgfRFP+VEKSrWlDTE6n9jMns/N4Q/VL6l4x6kTHQX4HQfwTcldaAfHQ==} engines: {node: '>=10.0.0'} @@ -8446,6 +8463,20 @@ packages: estree-walker: 2.0.2 picomatch: 2.3.1 + /@rollup/pluginutils/5.0.2: + resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.0 + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + /@seald-io/binary-search-tree/1.0.2: resolution: {integrity: sha512-+pYGvPFAk7wUR+ONMOlc6A+LUN4kOCFwyPLjyaeS7wVibADPHWYJNYsNtyIAwjF1AXQkuaXElnIc4XjKt55QZA==} dev: false @@ -12475,6 +12506,24 @@ packages: screenfull: 5.2.0 dev: false + /ahooks/3.7.4_react@18.2.0: + resolution: {integrity: sha512-hvgdqzPUKXn95mK3cGlDCi/ZZqv+FRibCUCFT8zW3hCwLGvixVfnHrIW2/2lgzPdLo8mLjp/XOdIJvcPvE2lgQ==} + engines: {node: '>=8.0.0'} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@types/js-cookie': 2.2.7 + ahooks-v3-count: 1.0.0 + dayjs: 1.11.7 + intersection-observer: 0.12.2 + js-cookie: 2.2.1 + lodash: 4.17.21 + react: 18.2.0 + resize-observer-polyfill: 1.5.1 + screenfull: 5.2.0 + tslib: 2.4.1 + dev: false + /airbnb-js-shims/2.2.1: resolution: {integrity: sha512-wJNXPH66U2xjgo1Zwyjf9EydvJ2Si94+vSdk6EERcBfB2VZkeltpqIats0cqIZMLCXP3zcyaUKGYQeIBT6XjsQ==} dependencies: @@ -23683,6 +23732,13 @@ packages: sourcemap-codec: 1.4.8 dev: false + /magic-string/0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.14 + dev: true + /make-dir/1.3.0: resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==} engines: {node: '>=4'} diff --git a/server/plugins/com.msgbyte.agora/.ministarrc.js b/server/plugins/com.msgbyte.agora/.ministarrc.js index 2572af57..76d5d996 100644 --- a/server/plugins/com.msgbyte.agora/.ministarrc.js +++ b/server/plugins/com.msgbyte.agora/.ministarrc.js @@ -1,6 +1,7 @@ const path = require('path'); const copy = require('rollup-plugin-copy'); const normalize = require('normalize-path'); +const replace = require('@rollup/plugin-replace'); const pluginRoot = path.resolve(__dirname, './web'); const outDir = path.resolve(__dirname, '../../public'); @@ -49,5 +50,8 @@ module.exports = { dest: normalize(item.dest, false), })), }), + replace({ + 'process.env.NODE_ENV': JSON.stringify('production'), + }), ], }; diff --git a/server/plugins/com.msgbyte.agora/package.json b/server/plugins/com.msgbyte.agora/package.json index 13fb8113..d6af6cb7 100644 --- a/server/plugins/com.msgbyte.agora/package.json +++ b/server/plugins/com.msgbyte.agora/package.json @@ -11,6 +11,7 @@ "build:web:watch": "ministar watchPlugin all" }, "devDependencies": { + "@rollup/plugin-replace": "^5.0.2", "@types/react": "18.0.20", "mini-star": "*", "normalize-path": "^3.0.0", diff --git a/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/package.json b/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/package.json index d5cb1b9c..53cee1a2 100644 --- a/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/package.json +++ b/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/package.json @@ -8,7 +8,8 @@ "sync:declaration": "tailchat declaration github" }, "dependencies": { - "agora-rtc-react": "^1.1.3" + "agora-rtc-react": "^1.1.3", + "ahooks": "^3.7.4" }, "devDependencies": { "@types/styled-components": "^5.1.26", diff --git a/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/Controls.tsx b/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/Controls.tsx index 4dda2105..cc84f9f3 100644 --- a/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/Controls.tsx +++ b/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/Controls.tsx @@ -1,25 +1,34 @@ import { IconBtn } from '@capital/component'; -import type { ICameraVideoTrack, IMicrophoneAudioTrack } from 'agora-rtc-react'; import React, { useState } from 'react'; -import { useClient } from './client'; +import { useClient, useMicrophoneAndCameraTracks } from './client'; export const Controls: React.FC<{ - tracks: [IMicrophoneAudioTrack, ICameraVideoTrack]; - setStart: React.Dispatch>; onClose: () => void; }> = React.memo((props) => { const client = useClient(); - const { tracks, setStart } = props; - const [trackState, setTrackState] = useState({ video: true, audio: true }); + const [trackState, setTrackState] = useState({ video: false, audio: false }); + const { ready, tracks } = useMicrophoneAndCameraTracks(); const mute = async (type: 'audio' | 'video') => { if (type === 'audio') { - await tracks[0].setEnabled(!trackState.audio); + if (trackState.audio === true) { + // await tracks[0].setEnabled(false); + await client.unpublish(tracks[0]); + } else { + // await tracks[0].setEnabled(true); + await client.publish(tracks[0]); + } setTrackState((ps) => { return { ...ps, audio: !ps.audio }; }); } else if (type === 'video') { - await tracks[1].setEnabled(!trackState.video); + if (trackState.video === true) { + // await tracks[1].setEnabled(false); + await client.unpublish(tracks[1]); + } else { + // await tracks[1].setEnabled(true); + await client.publish(tracks[1]); + } setTrackState((ps) => { return { ...ps, video: !ps.video }; }); @@ -32,7 +41,6 @@ export const Controls: React.FC<{ // we close the tracks to perform cleanup tracks[0].close(); tracks[1].close(); - setStart(false); props.onClose(); }; @@ -41,6 +49,7 @@ export const Controls: React.FC<{ mute('video')} /> @@ -48,6 +57,7 @@ export const Controls: React.FC<{ mute('audio')} /> diff --git a/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/Videos.tsx b/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/Videos.tsx index 527f5170..8f0edc93 100644 --- a/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/Videos.tsx +++ b/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/Videos.tsx @@ -1,16 +1,10 @@ -import { - AgoraVideoPlayer, - IAgoraRTCRemoteUser, - ICameraVideoTrack, - IMicrophoneAudioTrack, -} from 'agora-rtc-react'; +import { AgoraVideoPlayer, IAgoraRTCRemoteUser } from 'agora-rtc-react'; import React from 'react'; export const Videos: React.FC<{ users: IAgoraRTCRemoteUser[]; - tracks: [IMicrophoneAudioTrack, ICameraVideoTrack]; }> = React.memo((props) => { - const { users, tracks } = props; + const { users } = props; return (
diff --git a/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/window.tsx b/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/window.tsx index 546a4bdf..e9e450c6 100644 --- a/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/window.tsx +++ b/server/plugins/com.msgbyte.agora/web/plugins/com.msgbyte.agora/src/FloatWindow/window.tsx @@ -1,15 +1,12 @@ -import React, { useEffect, useState } from 'react'; -import { getJWTUserInfo } from '@capital/common'; +import React, { useEffect, useRef, useState } from 'react'; +import { getJWTUserInfo, isValidStr, showErrorToasts } from '@capital/common'; import type { IAgoraRTCRemoteUser } from 'agora-rtc-react'; import styled from 'styled-components'; -import { - appId, - token, - useClient, - useMicrophoneAndCameraTracks, -} from './client'; +import { appId, token, useClient } from './client'; import { Videos } from './Videos'; import { Controls } from './Controls'; +import { LoadingSpinner } from '@capital/component'; +import { useMemoizedFn } from 'ahooks'; const FloatWindow = styled.div` z-index: 100; @@ -81,59 +78,63 @@ export const FloatMeetingWindow: React.FC<{ }> = React.memo((props) => { const [folder, setFolder] = useState(false); const client = useClient(); - const { ready, tracks } = useMicrophoneAndCameraTracks(); const channelName = props.meetingId; const [users, setUsers] = useState([]); const [start, setStart] = useState(false); + const initedRef = useRef(false); - useEffect(() => { - // function to initialise the SDK - const init = async (channel: string) => { - client.on('user-published', async (user, mediaType) => { - await client.subscribe(user, mediaType); - console.log('subscribe success'); - if (mediaType === 'video') { - setUsers((prevUsers) => { - return [...prevUsers, user]; - }); - } - if (mediaType === 'audio') { - user.audioTrack?.play(); - } - }); - - client.on('user-unpublished', (user, type) => { - console.log('unpublished', user, type); - if (type === 'audio') { - user.audioTrack?.stop(); - } - if (type === 'video') { - setUsers((prevUsers) => { - return prevUsers.filter((User) => User.uid !== user.uid); - }); - } - }); + const init = useMemoizedFn(async (channelName: string) => { + client.on('user-published', async (user, mediaType) => { + await client.subscribe(user, mediaType); + console.log('subscribe success'); + if (mediaType === 'video') { + setUsers((prevUsers) => { + return [...prevUsers, user]; + }); + } + if (mediaType === 'audio') { + user.audioTrack?.play(); + } + }); - client.on('user-left', (user) => { - console.log('leaving', user); + client.on('user-unpublished', (user, type) => { + console.log('unpublished', user, type); + if (type === 'audio') { + user.audioTrack?.stop(); + } + if (type === 'video') { setUsers((prevUsers) => { return prevUsers.filter((User) => User.uid !== user.uid); }); + } + }); + + client.on('user-left', (user) => { + console.log('leaving', user); + setUsers((prevUsers) => { + return prevUsers.filter((User) => User.uid !== user.uid); }); + }); - const { _id } = await getJWTUserInfo(); - await client.join(appId, channel, token, _id); - if (tracks) { - await client.publish([tracks[0], tracks[1]]); - } + const { _id } = await getJWTUserInfo(); + try { + await client.join(appId, channelName, token, _id); setStart(true); - }; + } catch (err) { + showErrorToasts(err); + } + }); - if (ready && tracks) { - console.log('init ready'); + useEffect(() => { + if (initedRef.current) { + return; + } + + if (isValidStr(channelName)) { init(channelName); + initedRef.current = true; } - }, [channelName, client, ready, tracks]); + }, [channelName]); return (
- {start && tracks && } + {start ? ( + + ) : ( + + )}
- {ready && tracks && ( - - )} +
setFolder(!folder)}>