yangjie #46
18
main.js
18
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] = ""
|
||||
|
|
@ -609,6 +614,9 @@ app.on('ready', () => {
|
|||
childWindow[config.key].hide()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (config.bool) {
|
||||
childWindow[config.key].hide()
|
||||
} else {
|
||||
if (childWindow[config.key].isVisible()) {
|
||||
childWindow[config.key].hide()
|
||||
|
|
@ -616,6 +624,7 @@ app.on('ready', () => {
|
|||
childWindow[config.key].show()
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// 定位主窗口
|
||||
ipcMain.handle('setPosition', (event, data) => {
|
||||
|
|
@ -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];
|
||||
|
|
|
|||
55
preload.js
55
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) => {
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ const Meeting: React.FC = () => {
|
|||
})
|
||||
const [networkOther, setNetworkOther] = useState<RtcStats>({})
|
||||
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,
|
||||
})
|
||||
}, 1000);
|
||||
getShowUser();
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -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<void> => {
|
||||
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);
|
||||
} else {
|
||||
setTimeout(async () => {
|
||||
await agora.setupRemoteVideoJoin({
|
||||
uid: Number(userItem.uid),
|
||||
view: document.getElementById(`video-${userItem.uid}`),
|
||||
channelId: state.channelId,
|
||||
})
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
// 替换数据
|
||||
|
|
@ -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<void> => {
|
||||
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) => {
|
||||
try {
|
||||
track.stop()
|
||||
} catch (error) {
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -1659,19 +1689,25 @@ const Meeting: React.FC = () => {
|
|||
}
|
||||
// 退出房间
|
||||
const leaveChannel = async (bool: boolean = true): Promise<void> => {
|
||||
setIsLeave(true)
|
||||
await stopScreenCapture()
|
||||
await stopRecorderMedia()
|
||||
if (bool) {
|
||||
await getLeave()
|
||||
}
|
||||
await agora.leaveChannel()
|
||||
setTimeout(() => {
|
||||
setRecorder((res: any) => {
|
||||
if (res) {
|
||||
|
||||
} else {
|
||||
if (userInfo.isAnonymous) {
|
||||
storage.setItem('userLogin', false)
|
||||
} else {
|
||||
navigate('/home/index')
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
return res
|
||||
})
|
||||
}
|
||||
// 分享屏幕
|
||||
const clickSharedScreen = async (): Promise<void> => {
|
||||
|
|
@ -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 = () => {
|
|||
<div className={styles.meetingUserVideoList} style={{ width: statusList.userVideo ? '500px' : '500px' }}>
|
||||
<div className={styles.meetingUserVideoListTitle}>
|
||||
<span>会议监控</span>
|
||||
<img src={ImageUrl.icon18} alt="" onClick={() => {
|
||||
<img src={ImageUrl.icon18} alt="" onClick={async () => {
|
||||
await agora.allLeaveChannelEx()
|
||||
setStatusList({
|
||||
userList: false,
|
||||
userChatList: false,
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export interface IElectronAPI {
|
|||
isVisible: () => Promise<string>;
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue