diff --git a/packages/desktop/electron/main/constant.ts b/packages/desktop/electron/main/constant.ts
index 2df76c3..7684346 100644
--- a/packages/desktop/electron/main/constant.ts
+++ b/packages/desktop/electron/main/constant.ts
@@ -20,6 +20,7 @@ export const DIST = path.join(DIST_ELECTRON, '../dist');
export const PUBLIC = url ? path.join(DIST_ELECTRON, '../public') : process.env.DIST;
export const ICON = path.join(PUBLIC, './imgs/icons/png/32x32.png');
+export const ICONx2 = path.join(PUBLIC, './imgs/icons/png/64x64.png');
export const DOCS_PATH = path.join(homedir(), 'Documents');
@@ -125,7 +126,7 @@ export const WIN_CONFIG = {
fullscreenable: false, // 窗口是否可以进入全屏状态
alwaysOnTop: true, // 窗口是否永远在别的窗口的上面
skipTaskbar: true,
- // resizable: false,
+ resizable: false,
},
recorderVideo: {
html: path.join(process.env.DIST, 'recorderVideo.html'),
diff --git a/packages/desktop/electron/main/index.ts b/packages/desktop/electron/main/index.ts
index 77ea929..c12e585 100644
--- a/packages/desktop/electron/main/index.ts
+++ b/packages/desktop/electron/main/index.ts
@@ -11,6 +11,7 @@ import { protocolHandle, registerSchemesAsPrivileged } from './protocol';
import { initTray } from './tray';
import { update } from './update';
import { initApp } from './app';
+import { initNotification } from './notification';
initConfig();
initApp();
@@ -58,6 +59,7 @@ app.whenReady().then(() => {
protocolHandle();
createWindow();
initTray(config.language);
+ initNotification();
update();
});
diff --git a/packages/desktop/electron/main/notification.ts b/packages/desktop/electron/main/notification.ts
index 75f063e..fd31520 100644
--- a/packages/desktop/electron/main/notification.ts
+++ b/packages/desktop/electron/main/notification.ts
@@ -1,7 +1,14 @@
import { Notification } from 'electron';
-import { ICON } from './constant';
+import { ICONx2 } from './constant';
-export function showNotification(_options) {
- const options = { icon: ICON, ..._options };
- new Notification(options).show();
+let notification = null;
+
+export function showNotification(options) {
+ notification.title = options.title;
+ notification.body = options.body;
+ notification.show();
+}
+
+export function initNotification() {
+ notification = new Notification({ icon: ICONx2 });
}
diff --git a/packages/desktop/electron/win/recorderScreenWin.ts b/packages/desktop/electron/win/recorderScreenWin.ts
index a6116f4..2c01573 100644
--- a/packages/desktop/electron/win/recorderScreenWin.ts
+++ b/packages/desktop/electron/win/recorderScreenWin.ts
@@ -28,12 +28,14 @@ function createRecorderScreenWin(search?: any): BrowserWindow {
fullscreenable: WIN_CONFIG.recorderScreen.fullscreenable, // 窗口是否可以进入全屏状态
alwaysOnTop: WIN_CONFIG.recorderScreen.alwaysOnTop, // 窗口是否永远在别的窗口的上面
// skipTaskbar: WIN_CONFIG.recorderScreen.skipTaskbar,
- // resizable: WIN_CONFIG.recorderScreen.resizable,
+ resizable: WIN_CONFIG.recorderScreen.resizable,
webPreferences: {
preload,
},
});
+
// recorderScreenWin.webContents.openDevTools();
+
if (url) {
recorderScreenWin.loadURL(WEB_URL + `recorderScreen.html?type=${search?.type || ''}`);
} else {
diff --git a/packages/web/src/components/recorderScreen/Camera.tsx b/packages/web/src/components/recorderScreen/Camera.tsx
new file mode 100644
index 0000000..b857e29
--- /dev/null
+++ b/packages/web/src/components/recorderScreen/Camera.tsx
@@ -0,0 +1,21 @@
+import React, { useState, useRef } from 'react';
+import { useTranslation } from 'react-i18next';
+import { CameraOne } from '@icon-park/react';
+
+const Camera = (props) => {
+ const { t } = useTranslation();
+
+ function handleCamera() {
+ if (window.electronAPI) {
+ window.electronAPI?.sendPvOpenWin();
+ }
+ }
+
+ return (
+
+
+
+ );
+};
+
+export default Camera;
diff --git a/packages/web/src/components/recorderScreen/FullScreen.tsx b/packages/web/src/components/recorderScreen/FullScreen.tsx
index dcb31ec..00e693f 100644
--- a/packages/web/src/components/recorderScreen/FullScreen.tsx
+++ b/packages/web/src/components/recorderScreen/FullScreen.tsx
@@ -6,10 +6,12 @@ const FullScreen = (props) => {
const { t } = useTranslation();
function handleFullRecordScreen() {
- window.electronAPI?.sendRsCloseWin();
- window.electronAPI
- ? window.electronAPI.sendRfsOpenWin()
- : window.open('/recorderFullScreen.html');
+ if (!props.isRecording) {
+ window.electronAPI?.sendRsCloseWin();
+ window.electronAPI
+ ? window.electronAPI.sendRfsOpenWin()
+ : window.open('/recorderFullScreen.html');
+ }
}
return (
diff --git a/packages/web/src/components/recorderScreen/MicMuteRecorder.tsx b/packages/web/src/components/recorderScreen/MicMuteRecorder.tsx
index bfb0703..d436142 100644
--- a/packages/web/src/components/recorderScreen/MicMuteRecorder.tsx
+++ b/packages/web/src/components/recorderScreen/MicMuteRecorder.tsx
@@ -7,7 +7,9 @@ const MuteRecorder = (props) => {
const [isMute, setIsMute] = useState(false); // 标记是否静音
function handleToggleMute() {
- isMute ? unmuteRecording() : muteRecording();
+ if (!props.isRecording) {
+ isMute ? unmuteRecording() : muteRecording();
+ }
}
// 静音录制
diff --git a/packages/web/src/components/recorderScreen/ScreenRecorder.tsx b/packages/web/src/components/recorderScreen/ScreenRecorder.tsx
index 8e162a1..c928a77 100644
--- a/packages/web/src/components/recorderScreen/ScreenRecorder.tsx
+++ b/packages/web/src/components/recorderScreen/ScreenRecorder.tsx
@@ -1,4 +1,4 @@
-import { CameraOutlined, ExclamationCircleFilled, DesktopOutlined } from '@ant-design/icons';
+import { ExclamationCircleFilled } from '@ant-design/icons';
import Timer from '@pear-rec/timer';
import useTimer from '@pear-rec/timer/src/useTimer';
import { mp4StreamToOPFSFile } from '@webav/av-cliper';
@@ -16,6 +16,7 @@ import MicMuteRecorder from './MicMuteRecorder';
import SoundMuteRecorder from './SoundMuteRecorder';
import FullScreen from './FullScreen';
import ShotScreen from './ShotScreen';
+import Camera from './Camera';
import { FFmpeg } from '@ffmpeg/ffmpeg';
import { fetchFile, toBlobURL } from '@ffmpeg/util';
@@ -188,15 +189,40 @@ const ScreenRecorder = (props) => {
mediaRecorder.current = new AVRecorder(recodeMS, { width: size.width, height: size.height });
}
- function handleShotScreen() {
- const { width, height } = props.size;
+ async function handleShotScreen() {
+ const { width, height } = window.isElectron
+ ? await window.electronAPI?.invokeRsGetBoundsClip()
+ : props.size;
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const context = canvas.getContext('2d');
context.drawImage(videoRef.current, 0, 0, canvas.width, canvas.height);
- const url = canvas.toDataURL('image/png');
- saveAs(url, `pear-rec_${+new Date()}.png`);
+ canvas.toBlob((blob) => {
+ saveImg(blob);
+ }, 'image/png');
+ }
+
+ async function saveImg(blob) {
+ try {
+ const fileName = `pear-rec_${+new Date()}.png`;
+ const record = {
+ fileName: fileName,
+ fileData: blob,
+ fileType: 'ss',
+ userId: user.id,
+ createdAt: new Date(),
+ createdBy: user.id,
+ updatedAt: new Date(),
+ updatedBy: user.id,
+ };
+ const recordId = await db.records.add(record);
+ if (recordId) {
+ window.electronAPI?.sendNotification({ title: '截图成功', body: '可以在历史中查看' });
+ }
+ } catch (err) {
+ console.log('截图保存失败', err);
+ }
}
// 开始录制
@@ -316,7 +342,7 @@ const ScreenRecorder = (props) => {
-
+
录制
@@ -330,8 +356,9 @@ const ScreenRecorder = (props) => {
className="timer"
/>
+
-
+
diff --git a/packages/web/src/components/recorderScreen/ShotScreen.tsx b/packages/web/src/components/recorderScreen/ShotScreen.tsx
index 8bb648e..80d0e7a 100644
--- a/packages/web/src/components/recorderScreen/ShotScreen.tsx
+++ b/packages/web/src/components/recorderScreen/ShotScreen.tsx
@@ -6,13 +6,12 @@ const ShotScreen = (props) => {
const { t } = useTranslation();
function handleShotScreen() {
- props.onShotScreen();
- console.log('截图');
+ props.isRecording && props.onShotScreen();
}
return (
diff --git a/packages/web/src/components/recorderScreen/SoundMuteRecorder.tsx b/packages/web/src/components/recorderScreen/SoundMuteRecorder.tsx
index a80384f..3f14c5a 100644
--- a/packages/web/src/components/recorderScreen/SoundMuteRecorder.tsx
+++ b/packages/web/src/components/recorderScreen/SoundMuteRecorder.tsx
@@ -7,7 +7,9 @@ const SoundMuteRecorder = (props) => {
const [isMute, setIsMute] = useState(false); // 标记是否静音
function handleToggleMute() {
- isMute ? unmuteRecording() : muteRecording();
+ if (!props.isRecording) {
+ isMute ? unmuteRecording() : muteRecording();
+ }
}
// 静音录制
diff --git a/packages/web/src/pages/index.scss b/packages/web/src/pages/index.scss
index af2c951..5ea77a7 100644
--- a/packages/web/src/pages/index.scss
+++ b/packages/web/src/pages/index.scss
@@ -148,7 +148,8 @@ table {
.disabled {
opacity: 0.5;
- cursor: not-allowed;
+ // pointer-events: none !important;
+ cursor: not-allowed !important;
}
#root {
diff --git a/packages/web/src/pages/recorderFullScreen/index.tsx b/packages/web/src/pages/recorderFullScreen/index.tsx
index 3c0aee8..666541b 100644
--- a/packages/web/src/pages/recorderFullScreen/index.tsx
+++ b/packages/web/src/pages/recorderFullScreen/index.tsx
@@ -267,13 +267,6 @@ const RecorderScreen = () => {
- {/* }
- className="toolbarIcon settingBtn"
- title={t('nav.setting')}
- onClick={handleOpenSettingWin}
- > */}
}
@@ -288,13 +281,6 @@ const RecorderScreen = () => {
title={t('nav.close')}
onClick={handleCloseWin}
>
- {/* }
- className="toolbarIcon shotScreenBtn"
- title={t('recorderScreen.shotScreen')}
- onClick={handleShotScreen}
- > */}