272 lines
12 KiB
TypeScript
272 lines
12 KiB
TypeScript
import { useEffect, useRef, useState } from "react";
|
|
import '@/utils/styles/App.scss'
|
|
import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
|
|
import Home from '@/page/Home/index'
|
|
import Index from '@/page/Home/Index/index'
|
|
import User from '@/page/Home/User/index'
|
|
import Login from '@/page/Login/index'
|
|
import Meeting from '@/page/Meeting/index'
|
|
import NotFound from '@/page/NotFound/index'
|
|
import { storage } from '@/utils'
|
|
import { message, Spin } from "antd";
|
|
import { onOtherSignalr, onStop, startSignalr } from "@/utils/package/signalr";
|
|
import JoinMeetingModal from "@/components/JoinMeetingModal";
|
|
import UpdateModal from "@/components/UpdateModal";
|
|
import * as CryptoJS from 'crypto-js';
|
|
import { PostLogin } from "@/api/Login";
|
|
import { agora } from "@/utils/package/agora";
|
|
import QuitTips from "@/components/QuitTips";
|
|
import { GetLeave } from "@/api/Meeting";
|
|
import path from "path";
|
|
import ShareScreenWindow from "@/page/Meeting/ShareScreenWindow";
|
|
import UserListWindow from "@/page/Meeting/UserListWindow";
|
|
import ChatSmallWindow from "@/page/Meeting/ChatSmallWindow";
|
|
import ChatBigWindow from "@/page/Meeting/ChatBigWindow";
|
|
import CurrentSpeakUserWindow from "@/page/Meeting/CurrentSpeakUserWindow";
|
|
import NoticeWindow from "@/page/Meeting/NoticeWindow";
|
|
const fs = require('fs').promises;
|
|
const { exec } = require('child_process');
|
|
const App: React.FC = () => {
|
|
const navigate = useNavigate();
|
|
const { state } = useLocation();
|
|
const joinMeetingModalRef = useRef<any>();
|
|
const updateModalRef = useRef<any>();
|
|
const quitTipsRef = useRef<any>();
|
|
const [_windowSize, setWindowSize] = useState({
|
|
width: window.innerWidth,
|
|
height: window.innerHeight,
|
|
});
|
|
const [spinning, setSpinning] = useState(false);
|
|
const [isState, setIsState] = useState(true);
|
|
const urlHashArr = ['#/userListWindow', '#/shareScreenWindow', '#/chatSmallWindow', '#/chatBigWindow', '#/currentSpeakUserWindow', '#/noticeWindow']
|
|
if (urlHashArr.indexOf(location.hash) == -1) {
|
|
useEffect(() => {
|
|
let userInfo = JSON.parse(storage.getItem('user') as string)
|
|
let loginInfo = JSON.parse(storage.getItem('login') as string)
|
|
if (userInfo && !userInfo.isAnonymous) {
|
|
if (loginInfo && loginInfo.isAutoLogin) {
|
|
PostLogin({
|
|
account: loginInfo.account,
|
|
pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex)
|
|
}).then(async (res) => {
|
|
if (res.code === 200) {
|
|
storage.setItem('user', JSON.stringify(res.data))
|
|
storage.setItem('userLogin', true)
|
|
toSrc('/home')
|
|
await startSignalr()
|
|
} else {
|
|
toSrc('/login')
|
|
}
|
|
})
|
|
} else {
|
|
toSrc('/login')
|
|
}
|
|
} else {
|
|
toSrc('/login')
|
|
}
|
|
window.addEventListener('resize', handleResize);
|
|
const originalSetItem = window.localStorage.setItem;
|
|
window.localStorage.setItem = function (key, value) {
|
|
originalSetItem.call(this, key, value);
|
|
const event = new Event('customStorageChange') as any;
|
|
event.key = key
|
|
event.value = value
|
|
window.dispatchEvent(event);
|
|
};
|
|
window.addEventListener('customStorageChange', handleCustomStorageChange);
|
|
return () => {
|
|
window.removeEventListener('resize', handleResize);
|
|
window.removeEventListener('customStorageChange', handleCustomStorageChange);
|
|
};
|
|
}, []);
|
|
useEffect(() => {
|
|
window.electron.downFile(async (_e: any, data: any) => {
|
|
const response = await fetch(data.filePath);
|
|
const arrayBuffer = await response.arrayBuffer();
|
|
const buffer = Buffer.from(arrayBuffer);
|
|
fs.writeFile(`${data.downFilePaths}${data.fileName}`, buffer, {});
|
|
message.success(`下载成功!文件已保存至:${data.downFilePaths}`)
|
|
await fs.access(data.downFilePaths, fs.constants.F_OK);
|
|
if (process.platform === 'win32') {
|
|
exec(`explorer "${data.downFilePaths}"`);
|
|
} else if (process.platform === 'darwin') {
|
|
exec(`open "${data.downFilePaths}"`);
|
|
}
|
|
})
|
|
window.electron.onFilePath(async (_e: any, filePath: string, key: string) => {
|
|
const setting = await JSON.parse(storage.getItem('setting') as string)
|
|
if (key === 'recordingFilesPath') {
|
|
setting.recordingFilesPath = filePath
|
|
} else {
|
|
setting.shareFilesPath = filePath
|
|
}
|
|
storage.setItem('setting', JSON.stringify(setting))
|
|
})
|
|
window.electron.quitAndInstall(async (_e: any) => {
|
|
leaveChannel()
|
|
})
|
|
}, [])
|
|
useEffect(() => {
|
|
window.electron.onUpdate((_e: any, data: any) => {
|
|
if (location.hash.indexOf('/meeting') === -1) {
|
|
updateModalRef.current.changeModal(data)
|
|
}
|
|
})
|
|
if (!storage.getItem('setting')) {
|
|
storage.setItem('setting', JSON.stringify({
|
|
videoDeviceId: '', //摄像头id
|
|
ecordingDeviceId: "", //输入设备id
|
|
playBackDeviceId: "", //输出设备id
|
|
ecordingVolume: '', //输入音量
|
|
playBackVolume: '', //输出音量
|
|
autoEcordingVolume: true, //是否自动调整麦克风音量
|
|
recordingFilesPath: path.resolve(__dirname, '../../Downloads') + '\\', //本地录制保存路径
|
|
shareFilesPath: path.resolve(__dirname, '../../Downloads/') + '\\', //共享文件保存路径
|
|
isShareSavePath: true, //是否下载钱询问每个文件保存的位置
|
|
closeSetting: 'hide', //关闭按钮设置
|
|
isAINoiseReduction: true, //是否开启ai降噪
|
|
aINoiseReduction: 1, // 降噪模式
|
|
isRecordingTips: true, //是否开启录制提示
|
|
}))
|
|
}
|
|
if (!storage.getItem('openChildWindow')) {
|
|
storage.setItem('openChildWindow', JSON.stringify({}))
|
|
}
|
|
}, [])
|
|
useEffect(() => {
|
|
if (isState) {
|
|
setIsState(false)
|
|
window.electron.onQuit(async () => {
|
|
if (location.hash.indexOf('/login') === 1) {
|
|
window.electron.quit()
|
|
} else {
|
|
if (storage.getItem('isTips') === 'true') {
|
|
const setting = JSON.parse(storage.getItem('setting') as string)
|
|
if (setting.closeSetting === 'hide') {
|
|
window.electron.setViewStatus(setting.closeSetting)
|
|
} else {
|
|
window.electron.quit()
|
|
}
|
|
} else {
|
|
quitTipsRef.current.changeModal()
|
|
}
|
|
}
|
|
})
|
|
}
|
|
storage.setItem('stateInfo', JSON.stringify(state))
|
|
}, [state])
|
|
useEffect(() => {
|
|
if (location.href.indexOf('/login') !== -1) {
|
|
onStop()
|
|
}
|
|
}, [navigate])
|
|
}
|
|
useEffect(() => {
|
|
document.addEventListener('keydown', (event) => {
|
|
if (event.key === 'F11') {
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
}, [])
|
|
const handleResize = (): void => {
|
|
setWindowSize({
|
|
width: window.innerWidth,
|
|
height: window.innerHeight,
|
|
});
|
|
window.electron.getIsMaximized().then((res: boolean) => {
|
|
const dom = document.getElementById('root') as HTMLElement;
|
|
dom.style.borderRadius = res ? '0px' : '10px'
|
|
})
|
|
};
|
|
|
|
const onEventSignalr = (): void => {
|
|
onOtherSignalr(async (item: any) => {
|
|
switch (item.key) {
|
|
case 'Invitation':
|
|
window.electron.joinNotification({
|
|
body: item.roomName,
|
|
name: item.InviterName,
|
|
})
|
|
joinMeetingModalRef.current.changeModal(item)
|
|
break;
|
|
case 'ForceLogout':
|
|
if (item.msg) {
|
|
message.error(item.msg)
|
|
}
|
|
await leaveChannel(true)
|
|
toSrc('/login')
|
|
break;
|
|
}
|
|
})
|
|
}
|
|
const toSrc = (path: string): void => {
|
|
window.electron.getWindowSize().then((res: any) => {
|
|
switch (path) {
|
|
case '/login':
|
|
storage.setItem('userLogin', false)
|
|
navigate('/login')
|
|
break;
|
|
case '/home':
|
|
window.electron.setMainWindowSize({
|
|
width: Math.ceil(res.width / 1.5),
|
|
height: Math.ceil(res.height / 1.3),
|
|
})
|
|
navigate('/home')
|
|
break;
|
|
}
|
|
})
|
|
};
|
|
const leaveChannel = async (bool?: boolean): Promise<void> => {
|
|
if (location.hash.indexOf('/meeting') === 1) {
|
|
const data = JSON.parse(localStorage.stateInfo);
|
|
if (!bool) {
|
|
await GetLeave({
|
|
roomNum: data.channelId,
|
|
})
|
|
}
|
|
await agora.leaveChannel()
|
|
}
|
|
};
|
|
const handleCustomStorageChange = (e: any): void => {
|
|
if (e.key === 'loading') {
|
|
setSpinning(Boolean(e.value))
|
|
} else if (e.key === 'isSignalr') {
|
|
if (Boolean(e.value)) {
|
|
onEventSignalr()
|
|
}
|
|
} else if (e.key === 'userLogin') {
|
|
if (!Boolean(e.value)) {
|
|
storage.removeItem('user')
|
|
navigate('/login')
|
|
}
|
|
}
|
|
};
|
|
return (
|
|
<>
|
|
<Routes>
|
|
<Route path='/' element={<Home />} />
|
|
<Route path='/home' element={<Home />}>
|
|
<Route path='/home' element={<Navigate to='/home/index' />} />
|
|
<Route path='/home/index' element={<Index />} />
|
|
<Route path='/home/user' element={<User />} />
|
|
</Route>
|
|
<Route path='/login' element={<Login />} />
|
|
<Route path='/meeting' element={<Meeting />} />
|
|
<Route path='/shareScreenWindow' element={<ShareScreenWindow />} />
|
|
<Route path='/userListWindow' element={<UserListWindow />} />
|
|
<Route path='/chatSmallWindow' element={<ChatSmallWindow />} />
|
|
<Route path='/chatBigWindow' element={<ChatBigWindow />} />
|
|
<Route path='/currentSpeakUserWindow' element={<CurrentSpeakUserWindow />} />
|
|
<Route path='/noticeWindow' element={<NoticeWindow />} />
|
|
<Route path='*' element={<NotFound />} />
|
|
</Routes>
|
|
<Spin spinning={spinning} fullscreen />
|
|
<JoinMeetingModal ref={joinMeetingModalRef} />
|
|
<UpdateModal ref={updateModalRef} />
|
|
<QuitTips ref={quitTipsRef} />
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default App
|