新窗口
This commit is contained in:
parent
d25a6f7d88
commit
05330d2af3
36
main.js
36
main.js
|
|
@ -12,7 +12,7 @@ const {
|
||||||
} = require('electron');
|
} = require('electron');
|
||||||
const path = require('node:path')
|
const path = require('node:path')
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const {autoUpdater, CancellationToken} = require('electron-updater');
|
const { autoUpdater, CancellationToken } = require('electron-updater');
|
||||||
const cancellationToken = new CancellationToken()
|
const cancellationToken = new CancellationToken()
|
||||||
app.allowRendererProcessReuse = false;
|
app.allowRendererProcessReuse = false;
|
||||||
let mainWindow = null;
|
let mainWindow = null;
|
||||||
|
|
@ -34,7 +34,7 @@ class AppWindow extends BrowserWindow {
|
||||||
backgroundColor: '#00000000',
|
backgroundColor: '#00000000',
|
||||||
transparent: true,
|
transparent: true,
|
||||||
};
|
};
|
||||||
const finalConfig = {...basicConfig, ...config};
|
const finalConfig = { ...basicConfig, ...config };
|
||||||
super(finalConfig);
|
super(finalConfig);
|
||||||
const env = process.argv.find((arg) => arg.startsWith('--env='))?.split('=')[1];
|
const env = process.argv.find((arg) => arg.startsWith('--env='))?.split('=')[1];
|
||||||
if (env === 'development') {
|
if (env === 'development') {
|
||||||
|
|
@ -247,7 +247,7 @@ app.on('ready', () => {
|
||||||
mainWindow.setMinimumSize(config.width, config.height);
|
mainWindow.setMinimumSize(config.width, config.height);
|
||||||
// 设置最大尺寸
|
// 设置最大尺寸
|
||||||
const primaryDisplay = screen.getPrimaryDisplay()
|
const primaryDisplay = screen.getPrimaryDisplay()
|
||||||
const {width, height} = primaryDisplay.workAreaSize
|
const { width, height } = primaryDisplay.workAreaSize
|
||||||
if (config.key === 'login') {
|
if (config.key === 'login') {
|
||||||
mainWindow.setMaximumSize(config.width, config.height);
|
mainWindow.setMaximumSize(config.width, config.height);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -256,11 +256,37 @@ app.on('ready', () => {
|
||||||
// 设置窗口尺寸
|
// 设置窗口尺寸
|
||||||
mainWindow.setSize(config.width, config.height)
|
mainWindow.setSize(config.width, config.height)
|
||||||
// 设置窗口位置使其居中于当前屏幕
|
// 设置窗口位置使其居中于当前屏幕
|
||||||
const display = screen.getDisplayMatching({...mainWindow.getBounds()});
|
const display = screen.getDisplayMatching({ ...mainWindow.getBounds() });
|
||||||
const x = Math.round((display.workArea.width - mainWindow.getSize()[0]) / 2);
|
const x = Math.round((display.workArea.width - mainWindow.getSize()[0]) / 2);
|
||||||
const y = Math.round((display.workArea.height - mainWindow.getSize()[1]) / 2);
|
const y = Math.round((display.workArea.height - mainWindow.getSize()[1]) / 2);
|
||||||
mainWindow.setPosition(x, y);
|
mainWindow.setPosition(x, y);
|
||||||
});
|
});
|
||||||
|
// 打开新窗口
|
||||||
|
ipcMain.handle('oepnWindow', (event, data) => {
|
||||||
|
const newWindow = new BrowserWindow({
|
||||||
|
width: 1200,
|
||||||
|
height: 800,
|
||||||
|
maxWidth: 1200,
|
||||||
|
minHeight: 800,
|
||||||
|
webPreferences: {
|
||||||
|
contextIsolation: false,
|
||||||
|
nodeIntegration: true,
|
||||||
|
enableRemoteModule: true,
|
||||||
|
nodeIntegrationInWorker: true,
|
||||||
|
allowMediaDevices: true,
|
||||||
|
preload: path.join(__dirname, 'preload.js')
|
||||||
|
},
|
||||||
|
frame: false,
|
||||||
|
backgroundColor: '#00000000',
|
||||||
|
transparent: true,
|
||||||
|
});
|
||||||
|
newWindow.loadURL(data.url);
|
||||||
|
newWindow.webContents.on('before-input-event', (event, input) => {
|
||||||
|
if (input.key === 'F12') {
|
||||||
|
newWindow.webContents.openDevTools()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
|
// 检测更新,在你想要检查更新的时候执行,renderer事件触发后的操作自行编写
|
||||||
|
|
@ -283,7 +309,7 @@ function updateHandle() {
|
||||||
sendUpdateMessage(message.checking)
|
sendUpdateMessage(message.checking)
|
||||||
})
|
})
|
||||||
autoUpdater.on('update-available', function (info) {
|
autoUpdater.on('update-available', function (info) {
|
||||||
let messageStr = JSON.stringify({type: '0'})
|
let messageStr = JSON.stringify({ type: '0' })
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
sendUpdateMessage(messageStr)
|
sendUpdateMessage(messageStr)
|
||||||
}, 5000)
|
}, 5000)
|
||||||
|
|
|
||||||
|
|
@ -57,4 +57,8 @@ window.electron = {
|
||||||
downFile: (callback) => {
|
downFile: (callback) => {
|
||||||
ipcRenderer.on('downFile', callback)
|
ipcRenderer.on('downFile', callback)
|
||||||
},
|
},
|
||||||
|
// 打开新窗口
|
||||||
|
oepnWindow: (data) => {
|
||||||
|
ipcRenderer.invoke('oepnWindow', data)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
233
src/App.tsx
233
src/App.tsx
|
|
@ -17,6 +17,7 @@ import { PostLogin } from "@/api/Login";
|
||||||
import agora from "@/utils/package/agora";
|
import agora from "@/utils/package/agora";
|
||||||
import QuitTips from "@/components/QuitTips";
|
import QuitTips from "@/components/QuitTips";
|
||||||
import { GetLeave } from "@/api/Meeting";
|
import { GetLeave } from "@/api/Meeting";
|
||||||
|
import UserVideo from "./page/UserVideo";
|
||||||
const fs = require('fs').promises;
|
const fs = require('fs').promises;
|
||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
|
|
@ -31,29 +32,127 @@ const App: React.FC = () => {
|
||||||
});
|
});
|
||||||
const [spinning, setSpinning] = useState(false);
|
const [spinning, setSpinning] = useState(false);
|
||||||
const [isState, setIsState] = useState(true);
|
const [isState, setIsState] = useState(true);
|
||||||
useEffect(() => {
|
const urlWindow = ['#/userVideo']
|
||||||
let userInfo = JSON.parse(storage.getItem('user') as string)
|
if (urlWindow.indexOf(location.hash) === -1) {
|
||||||
let loginInfo = JSON.parse(storage.getItem('login') as string)
|
useEffect(() => {
|
||||||
if (userInfo) {
|
let userInfo = JSON.parse(storage.getItem('user') as string)
|
||||||
if (loginInfo && loginInfo.isAutoLogin) {
|
let loginInfo = JSON.parse(storage.getItem('login') as string)
|
||||||
PostLogin({
|
if (userInfo) {
|
||||||
account: loginInfo.account,
|
if (loginInfo && loginInfo.isAutoLogin) {
|
||||||
pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex)
|
PostLogin({
|
||||||
}).then(async (res) => {
|
account: loginInfo.account,
|
||||||
if (res.code === 200) {
|
pwd: CryptoJS.MD5(loginInfo.password).toString(CryptoJS.enc.Hex)
|
||||||
storage.setItem('user', JSON.stringify(res.data))
|
}).then(async (res) => {
|
||||||
toSrc('/home')
|
if (res.code === 200) {
|
||||||
await startSignalr()
|
storage.setItem('user', JSON.stringify(res.data))
|
||||||
} else {
|
toSrc('/home')
|
||||||
toSrc('/login')
|
await startSignalr()
|
||||||
}
|
} else {
|
||||||
})
|
toSrc('/login')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
toSrc('/login')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
toSrc('/login')
|
toSrc('/login')
|
||||||
}
|
}
|
||||||
} else {
|
window.addEventListener('resize', handleResize);
|
||||||
toSrc('/login')
|
window.addEventListener('online', handleNetworkChange);
|
||||||
}
|
window.addEventListener('offline', handleNetworkChange);
|
||||||
|
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);
|
||||||
|
window.removeEventListener('online', handleNetworkChange);
|
||||||
|
window.removeEventListener('offline', handleNetworkChange);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
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: '', //本地录制保存路径
|
||||||
|
shareFilesPath: '', //共享文件保存路径
|
||||||
|
isShareSavePath: true, //是否下载钱询问每个文件保存的位置
|
||||||
|
closeSetting: 'hide', //关闭按钮设置
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
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(() => {
|
||||||
if (import.meta.env.VITE_ENV !== 'development') {
|
if (import.meta.env.VITE_ENV !== 'development') {
|
||||||
document.addEventListener('keydown', (event) => {
|
document.addEventListener('keydown', (event) => {
|
||||||
if ((event.ctrlKey || event.metaKey) && event.key === 'r') {
|
if ((event.ctrlKey || event.metaKey) && event.key === 'r') {
|
||||||
|
|
@ -64,100 +163,7 @@ const App: React.FC = () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
window.addEventListener('resize', handleResize);
|
|
||||||
window.addEventListener('online', handleNetworkChange);
|
|
||||||
window.addEventListener('offline', handleNetworkChange);
|
|
||||||
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);
|
|
||||||
window.removeEventListener('online', handleNetworkChange);
|
|
||||||
window.removeEventListener('offline', handleNetworkChange);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
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: '', //本地录制保存路径
|
|
||||||
shareFilesPath: '', //共享文件保存路径
|
|
||||||
isShareSavePath: true, //是否下载钱询问每个文件保存的位置
|
|
||||||
closeSetting: 'hide', //关闭按钮设置
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
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])
|
|
||||||
const handleResize = (): void => {
|
const handleResize = (): void => {
|
||||||
setWindowSize({
|
setWindowSize({
|
||||||
width: window.innerWidth,
|
width: window.innerWidth,
|
||||||
|
|
@ -260,6 +266,7 @@ const App: React.FC = () => {
|
||||||
</Route>
|
</Route>
|
||||||
<Route path='/login' element={<Login />} />
|
<Route path='/login' element={<Login />} />
|
||||||
<Route path='/meeting' element={<Meeting />} />
|
<Route path='/meeting' element={<Meeting />} />
|
||||||
|
<Route path='/userVideo' element={<UserVideo />} />
|
||||||
<Route path='*' element={<NotFound />} />
|
<Route path='*' element={<NotFound />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
<Spin spinning={spinning} fullscreen />
|
<Spin spinning={spinning} fullscreen />
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,9 @@ const Index: React.FC = () => {
|
||||||
<Button type="primary"
|
<Button type="primary"
|
||||||
iconPosition={'end'}
|
iconPosition={'end'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
// window.electron.oepnWindow({
|
||||||
|
// url: location.origin + '/#/userVideo'
|
||||||
|
// })
|
||||||
joinSettingRef.current.changeModal(item.roomNum)
|
joinSettingRef.current.changeModal(item.roomNum)
|
||||||
}}
|
}}
|
||||||
icon={<img src={ImageUrl.icon9} alt="" />}
|
icon={<img src={ImageUrl.icon9} alt="" />}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { useEffect } from "react";
|
||||||
const NotFound: React.FC = () => {
|
const NotFound: React.FC = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
});
|
}, []);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="notfound"></div>
|
<div className="notfound"></div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
.userVideo {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #1F2022;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
import styles from '@/page/UserVideo/index.module.scss'
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
const UserVideo: React.FC = () => {
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles.userVideo}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserVideo
|
||||||
|
|
@ -14,6 +14,7 @@ export interface IElectronAPI {
|
||||||
quit: () => any;
|
quit: () => any;
|
||||||
downFile: (callBack: Function) => void;
|
downFile: (callBack: Function) => void;
|
||||||
quitAndInstall: (callBack: Function) => void;
|
quitAndInstall: (callBack: Function) => void;
|
||||||
|
oepnWindow: (data: any) => any;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue