Merge pull request 'yangjie' (#41) from yangjie into master
Reviewed-on: #41
This commit is contained in:
commit
ae8ba8cbe2
11
main.js
11
main.js
|
|
@ -8,6 +8,7 @@ const {
|
|||
ipcMain,
|
||||
clipboard,
|
||||
dialog,
|
||||
crashReporter,
|
||||
desktopCapturer,
|
||||
} = require('electron');
|
||||
const path = require('node:path')
|
||||
|
|
@ -16,6 +17,7 @@ const fs = require('fs');
|
|||
const Registry = require('winreg');
|
||||
const { autoUpdater, CancellationToken } = require('electron-updater');
|
||||
const signalR = require('@microsoft/signalr');
|
||||
const { setTimeout, setInterval, clearTimeout, clearInterval } = require('timers');
|
||||
const cancellationToken = new CancellationToken()
|
||||
app.allowRendererProcessReuse = false;
|
||||
let mainWindow = null;
|
||||
|
|
@ -25,6 +27,7 @@ let env;
|
|||
let regKey;
|
||||
let connection = null;
|
||||
let envStr;
|
||||
let startNumber = 0;
|
||||
|
||||
class AppWindow extends BrowserWindow {
|
||||
constructor(config) {
|
||||
|
|
@ -99,6 +102,11 @@ const additionalData = { myKey: 'myValue' }
|
|||
app.on('ready', () => {
|
||||
const gotTheLock = app.requestSingleInstanceLock(additionalData)
|
||||
if (gotTheLock) {
|
||||
app.getPath('crashDumps')
|
||||
crashReporter.start({
|
||||
uploadToServer: false,
|
||||
ignoreSystemCrashHandler: false
|
||||
})
|
||||
env = process.argv.find((arg) => arg.startsWith('--env='))?.split('=')[1];
|
||||
if (env === 'development') {
|
||||
Object.defineProperty(app, 'isPackaged', {
|
||||
|
|
@ -141,11 +149,14 @@ app.on('ready', () => {
|
|||
});
|
||||
ipcMain.handle('setEnv', (event, str) => {
|
||||
envStr = str;
|
||||
if (startNumber === 0) {
|
||||
updateHandle() // 检查更新
|
||||
setInterval(() => {
|
||||
updateHandle() // 每一小时检查更新
|
||||
}, 1000 * 60 * 60)
|
||||
createTray()
|
||||
startNumber++
|
||||
}
|
||||
});
|
||||
// socket
|
||||
ipcMain.handle('startSignalr', (event, user) => {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import Avatar from '@/components/Avatar';
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
import { agora } from '@/utils/package/agora';
|
||||
import { role } from '@/config/role';
|
||||
const { setInterval, clearInterval } = require('timers');
|
||||
let time = null as any;
|
||||
const JoinSetting = forwardRef((_props: any, ref: any) => {
|
||||
useImperativeHandle(ref, () => ({
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@
|
|||
height: 0;
|
||||
|
||||
.userVideoContentListItem {
|
||||
height: 32%;
|
||||
width: calc(100% / 4 - 8px);
|
||||
height: 13%;
|
||||
width: calc(100% / 3 - 8px);
|
||||
padding: 4px;
|
||||
|
||||
.userVideoContentListItemVideo {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { Button, Empty, Select, message } from 'antd';
|
|||
import { useEffect, useState } from "react";
|
||||
import { useLocation } from 'react-router';
|
||||
import { VideoStreamType } from 'agora-electron-sdk';
|
||||
const { setInterval, clearInterval } = require('timers');
|
||||
const UserVideo: React.FC = () => {
|
||||
const { state } = useLocation();
|
||||
const [from, setFrom] = useState<any>({
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { role } from '@/config/role';
|
|||
import dayjs from 'dayjs';
|
||||
import StupWizard from '@/components/StupWizard';
|
||||
import { GetSubDpList } from '@/api/Home/User';
|
||||
const { setInterval, clearInterval } = require('timers');
|
||||
const fs = require('fs').promises;
|
||||
const { exec } = require('child_process');
|
||||
const { RangePicker } = DatePicker;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { storage } from '@/utils';
|
|||
import ImageUrl from '@/utils/package/imageUrl'
|
||||
import Avatar from '@/components/Avatar';
|
||||
import StupWizard from '@/components/StupWizard';
|
||||
const { setInterval, clearInterval } = require('timers');
|
||||
dayjs.locale('zh-cn');
|
||||
type navListType = {
|
||||
title: string;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons';
|
|||
import { Button } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
import { useEffect, useState } from "react";
|
||||
const { setInterval, clearInterval } = require('timers');
|
||||
const ShareScreenWindow: React.FC = () => {
|
||||
const [footerLists, setFooterLists] = useState<any>([
|
||||
{
|
||||
|
|
@ -54,6 +55,11 @@ const ShareScreenWindow: React.FC = () => {
|
|||
let timeout: NodeJS.Timeout;
|
||||
useEffect(() => {
|
||||
getRoomUser()
|
||||
if (!role.ID.includes(userInfo.roleId)) {
|
||||
setFooterLists((res: any) => {
|
||||
return res.splice(4, 1)
|
||||
})
|
||||
}
|
||||
channel.onmessage = function (event) {
|
||||
let { type, time } = event.data;
|
||||
switch (type) {
|
||||
|
|
@ -82,8 +88,10 @@ const ShareScreenWindow: React.FC = () => {
|
|||
footerListTemplate[0].active = data.parmes.footerList[0][0].active;
|
||||
footerListTemplate[1].title = data.parmes.footerList[0][1].active ? '开启视频' : '关闭视频';
|
||||
footerListTemplate[1].active = data.parmes.footerList[0][1].active;
|
||||
if (role.ID.includes(userInfo.roleId)) {
|
||||
footerListTemplate[4].title = data.parmes.footerList[1][3].active ? '录制中' : '录制';
|
||||
footerListTemplate[4].active = data.parmes.footerList[1][3].active;
|
||||
}
|
||||
setFooterLists(footerListTemplate)
|
||||
break;
|
||||
case 'roomUserList':
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import { fixWebmDuration } from "webm-duration-fix-buffer";
|
|||
import { getKeyOpenChildWindow, setKeyOpenChildWindow } from '@/utils/package/public';
|
||||
import MeetingDisconnected from '@/components/MeetingDisconnected';
|
||||
import SingIn from '@/components/SingIn';
|
||||
const { setTimeout, setInterval, clearTimeout, clearInterval } = require('timers');
|
||||
const { confirm } = Modal;
|
||||
const { exec } = require('child_process');
|
||||
const fs = require('fs').promises;
|
||||
|
|
@ -435,6 +436,7 @@ const Meeting: React.FC = () => {
|
|||
if (!data) {
|
||||
setIsScreenCapture(bool => {
|
||||
if (!bool) {
|
||||
if (role.ID.includes(userInfo.roleId)) {
|
||||
confirm({
|
||||
title: '提示',
|
||||
icon: <ExclamationCircleFilled />,
|
||||
|
|
@ -456,6 +458,9 @@ const Meeting: React.FC = () => {
|
|||
showSingIn()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
showSingIn()
|
||||
}
|
||||
}
|
||||
return bool
|
||||
})
|
||||
|
|
@ -914,12 +919,18 @@ const Meeting: React.FC = () => {
|
|||
observer?.unobserve(element);
|
||||
});
|
||||
const observerObject = new IntersectionObserver(async (entries: IntersectionObserverEntry[], _observer: IntersectionObserver) => {
|
||||
setIsScreenCapture((bool: boolean) => {
|
||||
entries.forEach(async (entry) => {
|
||||
if (entry.target.id !== user.uid) {
|
||||
await agora.muteRemoteVideoStreamEx(Number(entry.target.id), !entry.isIntersecting)
|
||||
await agora.muteRemoteVideoStreamEx(Number(entry.target.id), bool ? true : !entry.isIntersecting)
|
||||
}
|
||||
});
|
||||
await agora.muteRemoteVideoStreamEx(Number(currentVideoId), false)
|
||||
return bool
|
||||
})
|
||||
setIsScreenCapture((bool: boolean) => {
|
||||
agora.muteRemoteVideoStreamEx(Number(currentVideoId), bool)
|
||||
return bool
|
||||
})
|
||||
}, { threshold: 0, root: document.getElementById('videoView') });
|
||||
setObserver(observerObject)
|
||||
elements.forEach(element => {
|
||||
|
|
@ -1611,11 +1622,11 @@ const Meeting: React.FC = () => {
|
|||
}
|
||||
// 退出房间
|
||||
const leaveChannel = async (bool: boolean = true): Promise<void> => {
|
||||
await stopScreenCapture()
|
||||
await stopRecorderMedia()
|
||||
if (bool) {
|
||||
await getLeave()
|
||||
}
|
||||
await stopScreenCapture()
|
||||
await agora.leaveChannel()
|
||||
setTimeout(() => {
|
||||
if (userInfo.isAnonymous) {
|
||||
|
|
@ -1623,11 +1634,20 @@ const Meeting: React.FC = () => {
|
|||
} else {
|
||||
navigate('/home/index')
|
||||
}
|
||||
}, 0)
|
||||
}, 1000)
|
||||
}
|
||||
// 分享屏幕
|
||||
const clickSharedScreen = async (): Promise<void> => {
|
||||
let data = sharedScreenList.find((item: any) => item.sourceId === sharedScreenItem.sourceId)
|
||||
const elements = document.querySelectorAll('.intersectionObserver-view');
|
||||
if (elements.length) {
|
||||
elements.forEach(item => {
|
||||
if (item.id !== userInfo.uid) {
|
||||
agora.muteRemoteVideoStreamEx(Number(item.id), true)
|
||||
}
|
||||
});
|
||||
agora.setSubscribeVideoBlocklist([Number(user.screenShareId)], 1)
|
||||
}
|
||||
if (data) {
|
||||
const footerListTemplate = [...footerList]
|
||||
footerListTemplate[footerListIndex.itemIndex][footerListIndex.rowIndex].title = '停止共享'
|
||||
|
|
@ -2667,7 +2687,7 @@ const Meeting: React.FC = () => {
|
|||
</div>
|
||||
</div>
|
||||
:
|
||||
<div className={styles.meetingUserVideoList} style={{ width: statusList.userVideo ? '100vw' : '500px' }}>
|
||||
<div className={styles.meetingUserVideoList} style={{ width: statusList.userVideo ? '500px' : '500px' }}>
|
||||
<div className={styles.meetingUserVideoListTitle}>
|
||||
<span>会议监控</span>
|
||||
<img src={ImageUrl.icon18} alt="" onClick={() => {
|
||||
|
|
@ -2837,6 +2857,21 @@ const Meeting: React.FC = () => {
|
|||
</label>
|
||||
<span>{row.title}</span>
|
||||
</div>
|
||||
case '录制':
|
||||
case '录制中':
|
||||
if (role.ID.includes(user.roleId)) {
|
||||
return <div
|
||||
className='drag'
|
||||
onClick={() => changeStatusList(row, itemIndex, rowIndex)}
|
||||
onMouseDown={() => changeFooterListSelect(row, itemIndex, rowIndex, true)}
|
||||
onMouseUp={() => changeFooterListSelect(row, itemIndex, rowIndex, false)}
|
||||
onMouseLeave={() => changeFooterListSelect(row, itemIndex, rowIndex, false)}
|
||||
key={rowIndex}>
|
||||
{row.select ? <img src={row.iconSelect} alt="" /> : <img src={row.active ? row.iconActive : row.icon} alt="" />}
|
||||
<span>{row.title}</span>
|
||||
</div>
|
||||
}
|
||||
return null
|
||||
default:
|
||||
return <div
|
||||
className='drag'
|
||||
|
|
|
|||
|
|
@ -21,12 +21,14 @@ import {
|
|||
BeautyOptions,
|
||||
ColorEnhanceOptions,
|
||||
LowlightEnhanceOptions,
|
||||
VirtualBackgroundSource
|
||||
VirtualBackgroundSource,
|
||||
AudienceLatencyLevelType
|
||||
} from "agora-electron-sdk";
|
||||
import { GetRoomRtcToken, GetAgoraConf } from "@/api/Home/Index";
|
||||
import { storage } from '@/utils';
|
||||
import { role } from "@/config/role";
|
||||
import path from "path";
|
||||
const os = require("os");
|
||||
const option: any = {
|
||||
appId: '',
|
||||
token: '',
|
||||
|
|
@ -44,6 +46,7 @@ export const agora = {
|
|||
rtcEngine = createAgoraRtcEngine();
|
||||
await rtcEngine.initialize({
|
||||
appId: data,
|
||||
logConfig: { filePath: path.resolve(os.homedir(), "./agorasdk.log") }
|
||||
});
|
||||
if (bool) {
|
||||
await agora.setDeviceManager()
|
||||
|
|
@ -213,6 +216,9 @@ export const agora = {
|
|||
// 本地加入
|
||||
setupLocalVideo: async (item: any) => {
|
||||
if (item.view?.childNodes.length === 1 || item.type) {
|
||||
if (String(item.uid).length === 9) {
|
||||
return
|
||||
}
|
||||
await rtcEngine.setupLocalVideo({
|
||||
renderMode: agora.getRrenderMode(item.uid),
|
||||
sourceType: item.sourceType,
|
||||
|
|
@ -302,6 +308,7 @@ export const agora = {
|
|||
publishMicrophoneTrack: true,//设置是否发布麦克风采集到的音频
|
||||
publishCameraTrack: true,//设置是否发布摄像头采集的视频
|
||||
publishScreenTrack: false,//设置是否发布屏幕采集的视频
|
||||
audienceLatencyLevel: bool ? AudienceLatencyLevelType.AudienceLatencyLevelUltraLowLatency : AudienceLatencyLevelType.AudienceLatencyLevelLowLatency,
|
||||
})
|
||||
},
|
||||
// 设置接收大小流
|
||||
|
|
@ -342,6 +349,7 @@ export const agora = {
|
|||
publishMicrophoneTrack: false,//设置是否发布麦克风采集到的音频
|
||||
publishCameraTrack: true,//设置是否发布摄像头采集的视频
|
||||
publishScreenTrack: false,//设置是否发布屏幕采集的视频
|
||||
audienceLatencyLevel: bool ? AudienceLatencyLevelType.AudienceLatencyLevelLowLatency : AudienceLatencyLevelType.AudienceLatencyLevelUltraLowLatency,
|
||||
}
|
||||
);
|
||||
await rtcEngine.setDualStreamModeEx(
|
||||
|
|
@ -365,6 +373,10 @@ export const agora = {
|
|||
muteRemoteVideoStreamEx: async (uid: number, mute: boolean) => {
|
||||
await rtcEngine.muteRemoteVideoStreamEx(uid, mute, { channelId: option.channelId, localUid: Number(option.uid) })
|
||||
},
|
||||
// 设置视频订阅黑名单。
|
||||
setSubscribeVideoBlocklist: async (uidList: number[], uidNumber: number) => {
|
||||
await rtcEngine.setSubscribeVideoBlocklist(uidList, uidNumber)
|
||||
},
|
||||
// 取消或恢复订阅指定远端用户的音频流
|
||||
muteRemoteVideoStream: async (uid: number, mute: boolean) => {
|
||||
rtcEngine.muteRemoteVideoStream(uid, mute)
|
||||
|
|
@ -396,6 +408,7 @@ export const agora = {
|
|||
publishMicrophoneTrack: publishMicrophoneTrack,//设置是否发布麦克风采集到的音频
|
||||
publishCameraTrack: publishCameraTrack,//设置是否发布摄像头采集的视频
|
||||
publishScreenTrack: false,//设置是否发布屏幕采集的视频
|
||||
audienceLatencyLevel: data ? AudienceLatencyLevelType.AudienceLatencyLevelUltraLowLatency : AudienceLatencyLevelType.AudienceLatencyLevelLowLatency,
|
||||
})
|
||||
},
|
||||
// 取消或恢复发布本地视频流
|
||||
|
|
@ -408,6 +421,7 @@ export const agora = {
|
|||
publishMicrophoneTrack: publishMicrophoneTrack,//设置是否发布麦克风采集到的音频
|
||||
publishCameraTrack: publishCameraTrack,//设置是否发布摄像头采集的视频
|
||||
publishScreenTrack: false,//设置是否发布屏幕采集的视频
|
||||
audienceLatencyLevel: data ? AudienceLatencyLevelType.AudienceLatencyLevelUltraLowLatency : AudienceLatencyLevelType.AudienceLatencyLevelLowLatency,
|
||||
})
|
||||
},
|
||||
// 摄像头采集
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ export default defineConfig({
|
|||
BeautyOptions,
|
||||
ColorEnhanceOptions,
|
||||
LowlightEnhanceOptions,
|
||||
VirtualBackgroundSource
|
||||
VirtualBackgroundSource,
|
||||
AudienceLatencyLevelType
|
||||
} = require("agora-electron-sdk")
|
||||
export {
|
||||
createAgoraRtcEngine,
|
||||
|
|
@ -101,7 +102,8 @@ export default defineConfig({
|
|||
BeautyOptions,
|
||||
ColorEnhanceOptions,
|
||||
LowlightEnhanceOptions,
|
||||
VirtualBackgroundSource
|
||||
VirtualBackgroundSource,
|
||||
AudienceLatencyLevelType
|
||||
}
|
||||
`,
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue