diff --git a/main.js b/main.js index 0415f85..c942700 100644 --- a/main.js +++ b/main.js @@ -402,6 +402,9 @@ app.on('ready', () => { case 'show': mainWindow.show() mainWindow.focus(); + mainWindow.setSkipTaskbar(false) + mainWindow.setResizable(true) + mainWindow.setAlwaysOnTop(false) break; } }); @@ -485,6 +488,11 @@ app.on('ready', () => { }); // 设置桌面应用基础属性 ipcMain.handle('setMainWindowSize', (event, config) => { + if (config.width === 250) { + mainWindow.setSkipTaskbar(true) + mainWindow.setResizable(false) + mainWindow.setAlwaysOnTop(true, 'screen-saver') + } // 设置最小窗口尺寸 mainWindow.setMinimumSize(config.width, config.height); // 设置最大尺寸 @@ -572,9 +580,6 @@ app.on('ready', () => { childWindow[k] = "" } } - mainWindow.setSkipTaskbar(false) - mainWindow.setResizable(true) - mainWindow.setAlwaysOnTop(false) } else { childWindow[key].close() childWindow[key] = "" @@ -610,10 +615,14 @@ app.on('ready', () => { } } } else { - if (childWindow[config.key].isVisible()) { + if (config.bool) { childWindow[config.key].hide() } else { - childWindow[config.key].show() + if (childWindow[config.key].isVisible()) { + childWindow[config.key].hide() + } else { + childWindow[config.key].show() + } } } }); @@ -715,9 +724,6 @@ function windowOperation(config) { case 'shareScreenWindow': x = Math.round((display.workArea.width - child.getSize()[0]) / 2); child.setPosition(x, 0); - mainWindow.setSkipTaskbar(true) - mainWindow.setResizable(false) - mainWindow.setAlwaysOnTop(true, 'screen-saver') break; case 'chatSmallWindow': y = height - child.getSize()[1]; diff --git a/preload.js b/preload.js index 55a0c47..4879689 100644 --- a/preload.js +++ b/preload.js @@ -116,8 +116,59 @@ window.electron = { ipcRenderer.invoke('setRegistry', uuid) }, // 创建子窗口 - createChildWindow: (config) => { - ipcRenderer.invoke('createChildWindow', config) + createChildWindow: (str) => { + switch (str) { + case 'show': + ipcRenderer.invoke('setChildWindowShow', { + key: 'shareScreenWindow', + }) + ipcRenderer.invoke('setChildWindowShow', { + key: 'chatSmallWindow', + }) + break; + case 'hide': + ipcRenderer.invoke('createChildWindow', { + url: location.origin + `/#/noticeWindow`, + width: 388, + height: 150, + key: 'noticeWindow', + }) + ipcRenderer.invoke('createChildWindow', { + url: location.origin + `/#/shareScreenWindow`, + width: 400, + height: 80, + key: 'shareScreenWindow', + }) + ipcRenderer.invoke('createChildWindow', { + url: location.origin + `/#/chatSmallWindow`, + width: 200, + height: 150, + key: 'chatSmallWindow', + }) + ipcRenderer.invoke('createChildWindow', { + url: location.origin + `/#/chatBigWindow`, + width: 540, + height: 640, + key: 'chatBigWindow', + }) + ipcRenderer.invoke('createChildWindow', { + url: location.origin + `/#/userListWindow`, + width: 440, + height: 540, + key: 'userListWindow', + }) + break; + case 'stop': + ipcRenderer.invoke('setChildWindowShow', { + key: 'shareScreenWindow', + bool: true + }) + ipcRenderer.invoke('setChildWindowShow', { + key: 'chatSmallWindow', + bool: true + }) + break; + } }, // 关闭子窗口 closeChildWindow: (key) => { diff --git a/src/page/Meeting/index.tsx b/src/page/Meeting/index.tsx index ccf0a00..7f2103e 100644 --- a/src/page/Meeting/index.tsx +++ b/src/page/Meeting/index.tsx @@ -171,6 +171,7 @@ const Meeting: React.FC = () => { }) const [networkOther, setNetworkOther] = useState({}) const [isComputerAudio, setIsComputerAudio] = useState(false) + const [_isLeave, setIsLeave] = useState(false) const [isScreenCapture, setIsScreenCapture] = useState(false) const [isFluencyPriority, setIsFluencyPriority] = useState(false) const [open, setOpen] = useState(false) @@ -208,6 +209,7 @@ const Meeting: React.FC = () => { const channel = new BroadcastChannel('meeting_channel'); let storeDevice: any; useEffect(() => { + window.electron.createChildWindow('hide') let time: NodeJS.Timeout; setUser(userInfo) window.electron.getIsMaximized().then((res: boolean) => { @@ -484,6 +486,7 @@ const Meeting: React.FC = () => { window.removeEventListener('wheel', handleWheelChange); clearInterval(time) channel.close(); + window.electron.closeChildWindow('shareScreenWindow') }; }, []); @@ -871,7 +874,22 @@ const Meeting: React.FC = () => { useEffect(() => { if (recorder) { - recorder.start(); + recorder.start() + recorder.onstart = async () => { + message.success('开始录制') + } + recorder.onerror = async () => { + setRecorder('') + setMediaStream([]) + setIsClickedMediaSteam(false) + changeStatusList({ + title: '录制中' + }, 1, 3) + message.error('录制失败,请重新录制!') + } + recorder.onstop = async () => { + + } recorder.ondataavailable = async (event: any) => { const blob = await fixWebmDuration(event.data); const reader = new FileReader() as any; @@ -900,6 +918,16 @@ const Meeting: React.FC = () => { onCancel() { } }) + setIsLeave(bool => { + if (bool) { + if (userInfo.isAnonymous) { + storage.setItem('userLogin', false) + } else { + navigate('/home/index') + } + } + return false + }) }; reader.readAsArrayBuffer(blob); } @@ -1001,8 +1029,8 @@ const Meeting: React.FC = () => { channelId: connection.channelId, sourceType: VideoSourceType.VideoSourceCameraPrimary, }) - getShowUser(); - }, 1500); + }, 1000); + getShowUser(); } } }, @@ -1017,7 +1045,7 @@ const Meeting: React.FC = () => { view: document.getElementById(`video-${remoteUid}`), channelId: connection.channelId, }) - }, 1500); + }, 1000); } } }, @@ -1200,22 +1228,18 @@ const Meeting: React.FC = () => { // 刷新 const refreshVideoView = async (userItem: any): Promise => { if (userItem.uid === userInfo.uid) { - setTimeout(async () => { - await agora.setupLocalVideo({ - uid: Number(userItem.uid), - view: document.getElementById(`video-${userItem.uid}`), - channelId: state.channelId, - sourceType: VideoSourceType.VideoSourceCameraPrimary, - }) - }, 1500); + await agora.setupLocalVideo({ + uid: Number(userItem.uid), + view: document.getElementById(`video-${userItem.uid}`), + channelId: state.channelId, + sourceType: VideoSourceType.VideoSourceCameraPrimary, + }) } else { - setTimeout(async () => { - await agora.setupRemoteVideoJoin({ - uid: Number(userItem.uid), - view: document.getElementById(`video-${userItem.uid}`), - channelId: state.channelId, - }) - }, 1500); + await agora.setupRemoteVideoJoin({ + uid: Number(userItem.uid), + view: document.getElementById(`video-${userItem.uid}`), + channelId: state.channelId, + }) } } // 替换数据 @@ -1578,7 +1602,7 @@ const Meeting: React.FC = () => { // 开始录制 const mediaRecorder = new MediaRecorder(combinedSource, { mimeType: 'video/webm;codecs=vp9,opus', - videoBitsPerSecond: 1.5e6, + videoBitsPerSecond: 1500, }); setRecorder(mediaRecorder); }); @@ -1642,7 +1666,10 @@ const Meeting: React.FC = () => { const stopRecorderMedia = async (): Promise => { setRecorder((res: any) => { if (res) { - res.stop(); + try { + res.stop() + } catch (error) { + } } return res }) @@ -1650,7 +1677,10 @@ const Meeting: React.FC = () => { if (res.length) { res.forEach((item: any) => { item.getTracks().forEach((track: any) => { - track.stop() + try { + track.stop() + } catch (error) { + } }); }); } @@ -1659,19 +1689,25 @@ const Meeting: React.FC = () => { } // 退出房间 const leaveChannel = async (bool: boolean = true): Promise => { + setIsLeave(true) await stopScreenCapture() await stopRecorderMedia() if (bool) { await getLeave() } await agora.leaveChannel() - setTimeout(() => { - if (userInfo.isAnonymous) { - storage.setItem('userLogin', false) + setRecorder((res: any) => { + if (res) { + } else { - navigate('/home/index') + if (userInfo.isAnonymous) { + storage.setItem('userLogin', false) + } else { + navigate('/home/index') + } } - }, 1000) + return res + }) } // 分享屏幕 const clickSharedScreen = async (): Promise => { @@ -1694,39 +1730,7 @@ const Meeting: React.FC = () => { const isOpen = await getKeyOpenChildWindow('shareScreenWindow') setIsScreenCapture(true) if (!isOpen) { - window.electron.createChildWindow({ - url: location.origin + `/#/noticeWindow`, - width: 388, - height: 150, - key: 'noticeWindow', - show: true, - }) - window.electron.createChildWindow({ - url: location.origin + `/#/shareScreenWindow`, - width: 400, - height: 80, - key: 'shareScreenWindow', - show: true, - }) - window.electron.createChildWindow({ - url: location.origin + `/#/chatSmallWindow`, - width: 200, - height: 150, - key: 'chatSmallWindow', - show: true, - }) - window.electron.createChildWindow({ - url: location.origin + `/#/chatBigWindow`, - width: 540, - height: 640, - key: 'chatBigWindow', - }) - window.electron.createChildWindow({ - url: location.origin + `/#/userListWindow`, - width: 440, - height: 540, - key: 'userListWindow', - }) + window.electron.createChildWindow('show') setKeyOpenChildWindow('shareScreenWindow', true) window.electron.setMainWindowSize({ width: 250, @@ -1749,7 +1753,7 @@ const Meeting: React.FC = () => { } // 获取桌面可共享屏幕的引用 const getDesktopCapturerVideo = (): void => { - agora.getDesktopCapturerVideo({ width: 300, height: 300 }, { width: 300, height: 300 }, true).then((res: any) => { + agora.getDesktopCapturerVideo({ width: 50, height: 50 }, { width: 30, height: 30 }, true).then((res: any) => { res.forEach((item: any, index: number) => { if (item.type === 1) { item.sourceTitle = '桌面' + (index + 1) @@ -1785,9 +1789,10 @@ const Meeting: React.FC = () => { const footerListTemplate = [...footerList] await agora.leaveChannelEx(userInfo.screenShareId) agora.stopScreenCapture() + await agora.destroyRendererByView() footerListTemplate[1][0].title = '共享屏幕' setFooterList(footerListTemplate) - window.electron.closeChildWindow('shareScreenWindow') + window.electron.createChildWindow('stop') setKeyOpenChildWindow('shareScreenWindow', false) setIsScreenCapture(bool => { if (bool) { @@ -2750,7 +2755,8 @@ const Meeting: React.FC = () => {
会议监控 - { + { + await agora.allLeaveChannelEx() setStatusList({ userList: false, userChatList: false, diff --git a/src/render.d.ts b/src/render.d.ts index 95e2967..ad0eae5 100644 --- a/src/render.d.ts +++ b/src/render.d.ts @@ -29,7 +29,7 @@ export interface IElectronAPI { isVisible: () => Promise; setRegistry: (uuid: string) => any; getRegistry: () => any; - createChildWindow: (config: any) => void; + createChildWindow: (str: string) => void; setChildWindow: (config: any) => void; setChildWindowShow: (config: any) => void; closeChildWindow: (key: string) => void; diff --git a/src/utils/package/agora.ts b/src/utils/package/agora.ts index c3ba703..90b9860 100644 --- a/src/utils/package/agora.ts +++ b/src/utils/package/agora.ts @@ -366,7 +366,6 @@ export const agora = { }, // 退出第二个房间 allLeaveChannelEx: async () => { - await agora.stopCameraCapture(); await rtcEngine.leaveChannelEx({ channelId: option.channelId + 'a', localUid: Number('1' + option.screenShareId) }) }, // 停止/恢复接收指定的视频流。 @@ -385,6 +384,12 @@ export const agora = { destroyRendererByConfig: async (uid: number, channelId?: string) => { await rtcEngine.destroyRendererByConfig(VideoSourceType.VideoSourceRemote, channelId, uid); }, + destroyRendererByView: async () => { + let dom = document.getElementById(`meetingAbsoluteVideo`); + if (dom) { + await rtcEngine.destroyRendererByView(dom); + } + }, // ai降噪 setAINSMode: async (enabled: boolean, mode: AudioAinsMode) => { rtcEngine.setAINSMode(enabled, mode) @@ -436,7 +441,7 @@ export const agora = { }, // 停止采集摄像头 stopCameraCapture: async () => { - await rtcEngine.stopCameraCapture() + await rtcEngine.stopCameraCapture(VideoSourceType.VideoSourceCamera) }, // 加入频道 setJoinChannel: async (data: any) => {