WGShare.Client.Electron/src/components/StupWizard/index.tsx

542 lines
20 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import styles from '@/components/StupWizard/index.module.scss'
import ImageUrl from '@/utils/package/ImageUrl';
import { Button, Checkbox, Empty, Input, Modal, Popover, Select, Slider, message } from 'antd';
import { useState, useImperativeHandle, forwardRef, useEffect } from "react";
import agora from '@/utils/package/agora'
import { CloseOutlined, LoadingOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import { storage } from '@/utils';
import path from 'path';
const fs = require('fs').promises;
const { exec } = require('child_process');
const StupWizard = forwardRef((props: any, ref: any) => {
useImperativeHandle(ref, () => ({
changeModal: () => {
agora.init()
setIsStupWizard(true)
}
}))
const [list, setList] = useState([
{
title: '视频',
icon: ImageUrl.icon39,
iconActive: ImageUrl.icon39Active,
active: true,
},
{
title: '音频',
icon: ImageUrl.icon40,
iconActive: ImageUrl.icon40Active,
active: false,
},
{
title: '录制',
icon: ImageUrl.icon41,
iconActive: ImageUrl.icon41Active,
active: false,
},
{
title: '共享文件',
icon: ImageUrl.icon42,
iconActive: ImageUrl.icon42Active,
active: false,
}
])
const [isStupWizard, setIsStupWizard] = useState(false);
return (
<>
<Modal
title=""
open={isStupWizard}
footer={null}
closable={false}
destroyOnClose={true}
centered
width={'70vw'}
className='modal-padding'>
<div className={styles.stupWizard}>
<div className={styles.stupWizardLeft}>
{list.map((row: any, index: number) => {
return (
<div key={index} className={`${row.active ? styles.active : ''}`} onClick={async () => {
const newList = [...list];
newList.forEach(item => item.active = false);
newList[index].active = true;
setList(newList)
agora.stopPlaybackDeviceTest()
agora.stopRecordingDeviceTest()
}}>
<img src={row.active ? row.iconActive : row.icon} alt="" />
<span>{row.title}</span>
</div>
)
})}
</div>
<div className={styles.stupWizardRight}>
<CloseOutlined style={{
position: 'absolute',
color: 'white',
right: '20px',
top: '16px',
cursor: 'pointer'
}}
onClick={() => {
agora.release()
setIsStupWizard(false)
}}
/>
{list[0].active ? <VideoComponents /> : null}
{list[1].active ? <AudioComponents /> : null}
{list[2].active ? <RecordingComponents /> : null}
{list[3].active ? <FileComponents /> : null}
</div>
</div>
</Modal>
</>
)
})
const VideoComponents = () => {
const [videoDeviceManager, setVideoDeviceManager] = useState<any>({
list: [],
item: null,
});
useEffect(() => {
getVideoDeviceList()
}, []);
const getVideoDeviceList = async (): Promise<void> => {
const setting = await JSON.parse(storage.getItem('setting') as string)
const userInfo = JSON.parse(storage.getItem('user') as string)
agora.getVideoDeviceManager().then(async (res) => {
const { item, list } = res
if ((!setting.videoDeviceId && item) || (!(list.find((item: any) => item.deviceId === setting.videoDeviceId)) && item)) {
setting.videoDeviceId = item
}
if (!list.length) {
setting.videoDeviceId = ''
}
storage.setItem('setting', JSON.stringify(setting))
setVideoDeviceManager({
list: list.map((row: any) => {
return {
value: row.deviceId,
label: row.deviceName
}
}),
item: setting.videoDeviceId ? setting.videoDeviceId : item || null,
})
if (setting.videoDeviceId && list.length) {
await agora.setVideoDeviceManager(setting.videoDeviceId)
await agora.startPreview('videoPreview', Number(userInfo.account))
}
})
}
return (
<>
<div>
<span></span>
<div className={styles.videoComponents}>
{
videoDeviceManager.item ?
<div>
<div id='videoPreview'>
<LoadingOutlined style={{
position: 'absolute',
color: 'white',
right: '50%',
fontSize: '30px',
top: '50%',
}} />
</div>
</div> :
<div>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<Empty description={'未检测到摄像头'} />
</div>
</div>
}
<div>
<span></span>
<Popover
content={
<span
style={{
color: 'white'
}}>
</span>
}
title=""
>
<QuestionCircleOutlined style={{
color: 'white',
cursor: 'pointer',
marginRight: '10px'
}} />
</Popover>
<Select
placeholder={videoDeviceManager.list.length ? '请选择设备' : '未检测到摄像头'}
options={videoDeviceManager.list} style={{ flexGrow: 1, marginRight: '10px' }}
value={videoDeviceManager.item} onChange={async (e) => {
const setting = await JSON.parse(storage.getItem('setting') as string)
setting.videoDeviceId = e;
storage.setItem('setting', JSON.stringify(setting))
setVideoDeviceManager({
...videoDeviceManager,
item: e
})
agora.setVideoDeviceManager(e)
}} />
</div>
</div>
</div>
</>
)
}
const AudioComponents = () => {
const [audioDeviceManager, setAudioDeviceManager] = useState<any>({
playBackList: [],
ecordingList: [],
playBackItem: null,
ecordingItem: null,
playBackVolume: 0,
playBackActive: false,
ecordingActive: false,
ecordingVolume: 0,
autoEcordingVolume: true,
});
useEffect(() => {
getAudioMediaList()
agora.registerEventHandler({
onAudioVolumeIndication: (percentage: number) => {
const dom = document.getElementById('deviceTest') as any;
if (dom) {
dom.style.width = `${percentage}%`
}
}
})
}, []);
const getAudioMediaList = async (): Promise<void> => {
const { playBackList, ecordingList, playBackItem, ecordingItem, ecordingVolume } = await agora.getAudioMediaList();
const setting = await JSON.parse(storage.getItem('setting') as string)
if ((!setting.ecordingDeviceId && ecordingItem.deviceId) || (!(ecordingList.find((item: any) => item.deviceId === setting.ecordingDeviceId)) && ecordingItem.deviceId)) {
setting.ecordingDeviceId = ecordingItem.deviceId
}
if ((!setting.playBackDeviceId && playBackItem.deviceId) || (!(playBackList.find((item: any) => item.deviceId === setting.playBackDeviceId)) && playBackItem.deviceId)) {
setting.playBackDeviceId = playBackItem.deviceId
}
if (!ecordingList.length) {
setting.ecordingDeviceId = ''
}
if (!playBackList.length) {
setting.playBackDeviceId = ''
}
if (!setting.ecordingVolume) {
setting.ecordingVolume = ecordingVolume;
}
if (!setting.playBackVolume) {
setting.playBackVolume = 127;
}
storage.setItem('setting', JSON.stringify(setting))
setAudioDeviceManager({
...audioDeviceManager,
playBackList: playBackList.map((row: any) => {
return {
value: row.deviceId,
label: row.deviceName
}
}),
ecordingList: ecordingList.map((row: any) => {
return {
value: row.deviceId,
label: row.deviceName
}
}),
playBackItem: setting.playBackDeviceId ? setting.playBackDeviceId : playBackItem.deviceId || null,
ecordingItem: setting.ecordingDeviceId ? setting.ecordingDeviceId : ecordingItem.deviceId || null,
ecordingVolume: setting.ecordingVolume,
playBackVolume: setting.playBackVolume,
autoEcordingVolume: setting.autoEcordingVolume
})
}
return (
<>
<div>
<span></span>
<div className={styles.audioComponents}>
<div>
<div className={styles.audioComponentsSelect}>
<span></span>
<Select
placeholder={audioDeviceManager.ecordingList.length ? '请选择设备' : '未检测到麦克风'}
options={audioDeviceManager.ecordingList} style={{ flexGrow: 1 }}
value={audioDeviceManager.ecordingItem} onChange={async (e) => {
const setting = await JSON.parse(storage.getItem('setting') as string)
setting.ecordingDeviceId = e;
storage.setItem('setting', JSON.stringify(setting))
setAudioDeviceManager({
...audioDeviceManager,
ecordingItem: e
})
agora.setRecordingDevice(e)
}} />;
{audioDeviceManager.ecordingActive ? <div onClick={() => {
agora.stopRecordingDeviceTest()
setAudioDeviceManager({
...audioDeviceManager,
playBackActive: false,
ecordingActive: false,
})
}}></div> : <div onClick={() => {
agora.stopPlaybackDeviceTest()
agora.startRecordingDeviceTest(100)
setAudioDeviceManager({
...audioDeviceManager,
playBackActive: false,
ecordingActive: true,
})
}}></div>}
</div>
{audioDeviceManager.ecordingActive ? <div className={styles.audioComponentsVolume}>
<img src={ImageUrl.icon36} alt="" />
<div>
<img src={ImageUrl.icon34} alt="" />
<div id='deviceTest'>
<img src={ImageUrl.icon35} alt="" />
</div>
</div>
</div> : null}
<div className={styles.audioComponentsSlider}>
<span></span>
<Slider value={audioDeviceManager.ecordingVolume} style={{ flexGrow: 1 }} max={255} onChange={async (e) => {
const setting = await JSON.parse(storage.getItem('setting') as string)
setting.ecordingVolume = e;
storage.setItem('setting', JSON.stringify(setting))
await agora.setRecordingDeviceVolume(e)
setAudioDeviceManager({
...audioDeviceManager,
ecordingVolume: e,
})
}} disabled={!audioDeviceManager.ecordingItem} />
</div>
<div>
<Checkbox onChange={async (e) => {
const setting = await JSON.parse(storage.getItem('setting') as string)
setting.autoEcordingVolume = e.target.checked;
storage.setItem('setting', JSON.stringify(setting))
setAudioDeviceManager({
...audioDeviceManager,
autoEcordingVolume: e.target.checked
})
}} checked={audioDeviceManager.autoEcordingVolume}></Checkbox>
</div>
</div>
<div>
<div className={styles.audioComponentsSelect}>
<span></span>
<Select
placeholder={audioDeviceManager.playBackList.length ? '请选择设备' : '未检测到麦克风'}
options={audioDeviceManager.playBackList} style={{ flexGrow: 1 }}
value={audioDeviceManager.playBackItem} onChange={async (e) => {
const setting = await JSON.parse(storage.getItem('setting') as string)
setting.playBackDeviceId = e;
storage.setItem('setting', JSON.stringify(setting))
setAudioDeviceManager({
...audioDeviceManager,
playBackItem: e
})
agora.setPlaybackDevice(e)
}} />;
{audioDeviceManager.playBackActive ? <div onClick={() => {
agora.stopPlaybackDeviceTest()
setAudioDeviceManager({
...audioDeviceManager,
playBackActive: false,
ecordingActive: false,
})
}}></div> : <div onClick={() => {
agora.stopRecordingDeviceTest()
agora.startPlaybackDeviceTest()
setAudioDeviceManager({
...audioDeviceManager,
playBackActive: true,
ecordingActive: false,
})
}}></div>}
</div>
{audioDeviceManager.playBackActive ? <div className={styles.audioComponentsVolume}>
<img src={ImageUrl.icon36} alt="" />
<div>
<img src={ImageUrl.icon34} alt="" />
<div id='deviceTest'>
<img src={ImageUrl.icon35} alt="" />
</div>
</div>
</div> : null}
<div className={styles.audioComponentsSlider}>
<span></span>
<Slider value={audioDeviceManager.playBackVolume} style={{ flexGrow: 1 }} max={255} onChange={async (e) => {
const setting = await JSON.parse(storage.getItem('setting') as string)
setting.playBackVolume = e;
storage.setItem('setting', JSON.stringify(setting))
agora.setPlaybackDeviceVolume(e)
setAudioDeviceManager({
...audioDeviceManager,
playBackVolume: e,
})
}} disabled={!audioDeviceManager.playBackItem} />
</div>
</div>
</div>
</div>
</>
)
}
const RecordingComponents = () => {
const [filePath, setFilePath] = useState('')
useEffect(() => {
const setting = JSON.parse(storage.getItem('setting') as string)
if (!setting.recordingFilesPath) {
setting.recordingFilesPath = path.dirname(process.execPath) + '\\';
setFilePath(setting.recordingFilesPath)
storage.setItem('setting', JSON.stringify(setting))
} else {
setFilePath(setting.recordingFilesPath);
}
window.addEventListener('customStorageChange', handleCustomStorageChange);
return () => {
window.removeEventListener('customStorageChange', handleCustomStorageChange);
};
}, [])
const handleCustomStorageChange = (e: any): void => {
if (e.key === 'setting') {
const setting = JSON.parse(storage.getItem('setting') as string)
setFilePath(setting.recordingFilesPath)
}
};
return (
<>
<div>
<span></span>
<div className={styles.recordingComponents}>
<span></span>
<div>
<span></span>
<Input
placeholder="请填入文件路径"
style={{ margin: '0 14px', flexGrow: 1 }}
value={filePath}
onChange={async (e) => {
const setting = await JSON.parse(storage.getItem('setting') as string)
setting.recordingFilesPath = e.target.value;
storage.setItem('setting', JSON.stringify(setting))
setFilePath(e.target.value)
}}
/>
<Button type="primary" onClick={() => {
window.electron.selectFilePath({
key: 'recordingFilesPath',
})
}} style={{ backgroundColor: '#31353A', marginRight: '10px' }}></Button>
<Button type="primary" onClick={async () => {
try {
await fs.access(filePath, fs.constants.F_OK);
if (process.platform === 'win32') {
exec(`explorer "${filePath}"`);
} else if (process.platform === 'darwin') {
exec(`open "${filePath}"`);
}
} catch (error: any) {
if (error.code === 'ENOENT') {
message.error('文件夹不存在!')
} else {
message.error(error)
}
}
}} style={{ backgroundColor: '#31353A' }}></Button>
</div>
</div>
</div>
</>
)
}
const FileComponents = () => {
const [filePath, setFilePath] = useState('')
const [isShareSavePath, setIsShareSavePath] = useState(true)
useEffect(() => {
const setting = JSON.parse(storage.getItem('setting') as string)
if (!setting.shareFilesPath) {
setting.shareFilesPath = path.dirname(process.execPath) + '\\';
setFilePath(setting.shareFilesPath)
storage.setItem('setting', JSON.stringify(setting))
} else {
setFilePath(setting.shareFilesPath);
}
setIsShareSavePath(setting.isShareSavePath)
window.addEventListener('customStorageChange', handleCustomStorageChange);
return () => {
window.removeEventListener('customStorageChange', handleCustomStorageChange);
};
}, [])
const handleCustomStorageChange = (e: any): void => {
if (e.key === 'setting') {
const setting = JSON.parse(storage.getItem('setting') as string)
setFilePath(setting.shareFilesPath)
}
};
return (
<>
<div>
<span></span>
<div className={styles.fileComponents}>
<span></span>
<div>
<span></span>
<Input
placeholder="请填入保存目录"
style={{ margin: '0 14px', flexGrow: 1 }}
value={filePath}
onChange={async (e) => {
const setting = await JSON.parse(storage.getItem('setting') as string)
setting.shareFilesPath = e.target.value;
storage.setItem('setting', JSON.stringify(setting))
setFilePath(e.target.value)
}}
/>
<Button type="primary" onClick={() => {
window.electron.selectFilePath({
key: 'shareFilesPath',
})
}} style={{ backgroundColor: '#31353A', marginRight: '10px' }}></Button>
<Button type="primary" onClick={async () => {
try {
await fs.access(filePath, fs.constants.F_OK);
if (process.platform === 'win32') {
exec(`explorer "${filePath}"`);
} else if (process.platform === 'darwin') {
exec(`open "${filePath}"`);
}
} catch (error: any) {
if (error.code === 'ENOENT') {
message.error('文件夹不存在!')
} else {
message.error(error)
}
}
}} style={{ backgroundColor: '#31353A' }}></Button>
</div>
<div>
<Checkbox onChange={async (e) => {
const setting = await JSON.parse(storage.getItem('setting') as string)
setting.isShareSavePath = e.target.checked;
storage.setItem('setting', JSON.stringify(setting))
setIsShareSavePath(e.target.checked)
}} checked={isShareSavePath}></Checkbox>
</div>
</div>
</div>
</>
)
}
export default StupWizard