diff --git a/README.md b/README.md index 2c9011c0..4ee62350 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,9 @@ ## Installation -``` -gitee: https://gitee.com/xiguapi027/pear-rec -github: https://github.com/027xiguapi/pear-rec -``` +> gitee: https://gitee.com/xiguapi027/pear-rec +> +> github: https://github.com/027xiguapi/pear-rec ## Usage diff --git a/README.zh-CN.md b/README.zh-CN.md index cc2986c8..9291c9c8 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -25,9 +25,9 @@ ## 简介 -> pear-rec(梨子 rec) 是一个跨平台的截图、录屏、录音、录像软件。 +> pear-rec(梨子 rec) 是一个跨平台的截图、录屏、录音、录像、录制(动图)gif、查看图片、查看视频、查看音频和修改图片的软件。 > -> pear-rec(pear rec) 是基于 react + electron + vite + viewerjs + plyr + aplayer + react-screenshots 的一个项目。 +> pear-rec(pear rec) 是基于 react + electron + vite + viewerjs + plyr + aplayer + react-screenshots + tui-image-editor + gif.js 的一个项目。 > > 更多功能和 api 可以查看[官网(https://027xiguapi.github.io/pear-rec)](https://027xiguapi.github.io/pear-rec) 或 [https://xiguapi027.gitee.io/pear-rec](https://xiguapi027.gitee.io/pear-rec) @@ -37,10 +37,9 @@ ## 下载地址 -``` -gitee: https://gitee.com/xiguapi027/pear-rec -github: https://github.com/027xiguapi/pear-rec -``` +> gitee: https://gitee.com/xiguapi027/pear-rec +> +> github: https://github.com/027xiguapi/pear-rec ## 源码运行&编译 @@ -129,6 +128,7 @@ pnpm run build:desktop - [x] 图片编辑(tui-image-editor) - [x] 视频预览(plyr) - [x] 音频预览(aplayer) +- [x] 动图(gif)编辑(gif.js) - [x] 基本设置 - [x] 用户 uuid - [x] 保存地址 diff --git a/package.json b/package.json index 54fed347..f72cf4f0 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "only-build:web": "pnpm run -C packages/web build", "watch:web": "pnpm run -C packages/web watch", "project:web": "pnpm run -C packages/web build && node tools/copy-files-web2server.js", - "dev:server": "pnpm run -C packages/server start:dev", + "dev:server": "pnpm run -C packages/server dev", "build:server": "pnpm run -C packages/server build", "dev:docs": "pnpm run -C packages/docs dev", "build:docs": "pnpm run -C packages/docs build", diff --git a/packages/desktop/CHANGELOG.md b/packages/desktop/CHANGELOG.md index a66dc99d..bede3b23 100644 --- a/packages/desktop/CHANGELOG.md +++ b/packages/desktop/CHANGELOG.md @@ -1,5 +1,9 @@ # @pear-rec/desktop +## 1.3.6 + +feat: 修改GIF + ## 1.3.5 feat: 增加服务子进程 diff --git a/packages/desktop/electron/main/ipcMain.ts b/packages/desktop/electron/main/ipcMain.ts index eef4b371..6d9c437e 100644 --- a/packages/desktop/electron/main/ipcMain.ts +++ b/packages/desktop/electron/main/ipcMain.ts @@ -13,6 +13,7 @@ import * as settingWin from '../win/settingWin'; import * as recordsWin from '../win/recordsWin'; import * as pinImageWin from '../win/pinImageWin'; import * as recorderFullScreenWin from '../win/recorderFullScreenWin'; +import * as editGifWin from '../win/editGifWin'; import * as utils from './utils'; import { editConfig } from '@pear-rec/server/src/config'; @@ -102,9 +103,9 @@ function initIpcMain() { recorderScreenWin.focusRecorderScreenWin(); }); // 录屏截图 - ipcMain.on('cs:open-win', () => { + ipcMain.on('cs:open-win', (e, search) => { clipScreenWin.closeClipScreenWin(); - clipScreenWin.openClipScreenWin(); + clipScreenWin.openClipScreenWin(search); }); ipcMain.on('cs:close-win', () => { clipScreenWin.closeClipScreenWin(); @@ -196,8 +197,16 @@ function initIpcMain() { ipcMain.on('ei:open-win', (e, search) => { editImageWin.openEditImageWin(search); }); + // 动图编辑 + ipcMain.on('eg:close-win', () => { + editGifWin.closeEditGifWin(); + }); + ipcMain.on('eg:open-win', (e, search) => { + editGifWin.openEditGifWin(search); + }); // 视频音频展示; ipcMain.on('vv:open-win', (e, search) => { + viewVideoWin.closeViewVideoWin(); viewVideoWin.openViewVideoWin(search); }); ipcMain.on('vv:close-win', () => { diff --git a/packages/desktop/electron/preload/electronAPI.ts b/packages/desktop/electron/preload/electronAPI.ts index 72395f6e..7be4cef8 100644 --- a/packages/desktop/electron/preload/electronAPI.ts +++ b/packages/desktop/electron/preload/electronAPI.ts @@ -35,7 +35,7 @@ contextBridge.exposeInMainWorld('electronAPI', { handleRsGetEndRecord: (callback: any) => ipcRenderer.on('rs:get-end-record', callback), //csWin - sendCsOpenWin: () => ipcRenderer.send('cs:open-win'), + sendCsOpenWin: (search?: any) => ipcRenderer.send('cs:open-win', search), sendCsCloseWin: () => ipcRenderer.send('cs:close-win'), sendCsHideWin: () => ipcRenderer.send('cs:hide-win'), sendCsMinimizeWin: () => ipcRenderer.send('cs:minimize-win'), @@ -47,6 +47,7 @@ contextBridge.exposeInMainWorld('electronAPI', { sendCsSetBounds: (bounds: any) => { ipcRenderer.send('cs:set-bounds', bounds); }, + //rvWin sendRvCloseWin: () => ipcRenderer.send('rv:close-win'), sendRvOpenWin: () => ipcRenderer.send('rv:open-win'), @@ -74,7 +75,10 @@ contextBridge.exposeInMainWorld('electronAPI', { //eiWin sendEiCloseWin: () => ipcRenderer.send('ei:close-win'), sendEiOpenWin: (search?: string) => ipcRenderer.send('ei:open-win', search), - sendEiSaveImg: (imgUrl: string) => ipcRenderer.send('ei:save-img', imgUrl), + + //egWin + sendEgCloseWin: () => ipcRenderer.send('eg:close-win'), + sendEgOpenWin: (search?: string) => ipcRenderer.send('eg:open-win', search), //vvWin sendVvOpenWin: (search?: string) => ipcRenderer.send('vv:open-win', search), diff --git a/packages/desktop/electron/win/clipScreenWin.ts b/packages/desktop/electron/win/clipScreenWin.ts index 5aebb140..4f12f5a6 100644 --- a/packages/desktop/electron/win/clipScreenWin.ts +++ b/packages/desktop/electron/win/clipScreenWin.ts @@ -64,13 +64,13 @@ function showClipScreenWin() { clipScreenWin?.show(); } -function openClipScreenWin() { +function openClipScreenWin(search?: any) { if (!clipScreenWin || clipScreenWin?.isDestroyed()) { clipScreenWin = createClipScreenWin(); } clipScreenWin?.show(); - openRecorderScreenWin(); + openRecorderScreenWin(search); } function getBoundsClipScreenWin() { diff --git a/packages/desktop/electron/win/editGifWin.ts b/packages/desktop/electron/win/editGifWin.ts new file mode 100644 index 00000000..1b815567 --- /dev/null +++ b/packages/desktop/electron/win/editGifWin.ts @@ -0,0 +1,45 @@ +import { BrowserWindow, dialog, shell, DownloadItem, WebContents } from 'electron'; +import { join, dirname } from 'node:path'; +import { ICON, DIST, preload, url, WEB_URL } from '../main/contract'; + +const editGifHtml = join(DIST, './editGif.html'); +let editGifWin: BrowserWindow | null = null; + +function createEditGifWin(search?: any): BrowserWindow { + editGifWin = new BrowserWindow({ + title: 'pear-rec 动图编辑', + icon: ICON, + height: 768, + width: 1024, + autoHideMenuBar: true, // 自动隐藏菜单栏 + webPreferences: { + preload, + }, + }); + + const videoUrl = search?.videoUrl || ''; + + // editGifWin.webContents.openDevTools(); + if (url) { + editGifWin.loadURL(WEB_URL + `editGif.html?videoUrl=${videoUrl}`); + } else { + editGifWin.loadFile(editGifHtml, { + search: `?videoUrl=${videoUrl}`, + }); + } + + return editGifWin; +} + +function openEditGifWin(search?: any) { + if (!editGifWin || editGifWin?.isDestroyed()) { + editGifWin = createEditGifWin(search); + } + editGifWin.show(); +} + +function closeEditGifWin() { + editGifWin?.close(); +} + +export { createEditGifWin, openEditGifWin, closeEditGifWin }; diff --git a/packages/desktop/electron/win/recorderScreenWin.ts b/packages/desktop/electron/win/recorderScreenWin.ts index 0413b76a..3426c17a 100644 --- a/packages/desktop/electron/win/recorderScreenWin.ts +++ b/packages/desktop/electron/win/recorderScreenWin.ts @@ -34,10 +34,12 @@ function createRecorderScreenWin(search?: any): BrowserWindow { }); recorderScreenWin?.setResizable(false); if (url) { - recorderScreenWin.loadURL(WEB_URL + `recorderScreen.html`); + recorderScreenWin.loadURL(WEB_URL + `recorderScreen.html?type=${search?.type || ''}`); // recorderScreenWin.webContents.openDevTools(); } else { - recorderScreenWin.loadFile(recorderScreenHtml); + recorderScreenWin.loadFile(recorderScreenHtml, { + search: `?type=${search?.type || ''}`, + }); } recorderScreenWin.on('move', () => { @@ -54,12 +56,6 @@ function createRecorderScreenWin(search?: any): BrowserWindow { return recorderScreenWin; } -async function recorderScreen(rsFilePath: string) { - // closeRecorderScreenWin(); - // setHistoryVideo(rsFilePath); - shell.showItemInFolder(rsFilePath); -} - // 打开关闭录屏窗口 function closeRecorderScreenWin() { recorderScreenWin?.isDestroyed() || recorderScreenWin?.close(); diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 98bc5d25..02484481 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@pear-rec/desktop", - "version": "1.3.4", + "version": "1.3.6", "main": "dist-electron/main/index.js", "description": "pear-rec", "author": "027xiguapi", diff --git a/packages/server/package.json b/packages/server/package.json index 729084ac..36a74f09 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -6,7 +6,7 @@ "webpack": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", - "start:dev": "nest start --watch", + "dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main" }, diff --git a/packages/server/src/util/upload.middleware.ts b/packages/server/src/util/upload.middleware.ts index 1aca13a1..12f691be 100644 --- a/packages/server/src/util/upload.middleware.ts +++ b/packages/server/src/util/upload.middleware.ts @@ -30,7 +30,7 @@ export class UploadMiddleware implements MulterOptionsFactory { rs: 'webm', ra: 'webm', ei: 'png', - gif: 'gif', + eg: 'gif', }; const type = req.body.type; const fileType = fileTypeMap[type] || 'webm'; diff --git a/packages/web/CHANGELOG.md b/packages/web/CHANGELOG.md index a16b2079..c4ff3cc5 100644 --- a/packages/web/CHANGELOG.md +++ b/packages/web/CHANGELOG.md @@ -1,5 +1,9 @@ # @pear-rec/web +## 1.3.9 + +feat: 修改GIF + ## 1.3.8 fix: 修改图片和钉图打不开bug diff --git a/packages/web/src/components/card/recordScreenCard.tsx b/packages/web/src/components/card/recordScreenCard.tsx index 123f2af7..2b2737a8 100644 --- a/packages/web/src/components/card/recordScreenCard.tsx +++ b/packages/web/src/components/card/recordScreenCard.tsx @@ -1,18 +1,34 @@ import React, { useImperativeHandle, forwardRef } from 'react'; import { useTranslation } from 'react-i18next'; import { CameraOutlined, DownOutlined } from '@ant-design/icons'; -import { Card, Space, Button } from 'antd'; +import type { MenuProps } from 'antd'; +import { Card, Space, Button, Dropdown } from 'antd'; const RecordScreenCard = forwardRef((props: any, ref: any) => { useImperativeHandle(ref, () => ({})); const { t } = useTranslation(); - function handleClipScreen() { + const items: MenuProps['items'] = [ + { + label: '录屏', + key: 'video', + }, + { + label: 'GIF', + key: 'gif', + }, + ]; + + const onClick: MenuProps['onClick'] = ({ key }) => { + handleClipScreenClick(key); + }; + + function handleClipScreenClick(type) { if (window.isElectron) { - window.electronAPI.sendCsOpenWin(); + window.electronAPI.sendCsOpenWin({ type }); window.electronAPI.sendMaCloseWin(); } else { - location.href = '/recorderScreen.html'; + location.href = `/recorderScreen.html?type=${type}`; } } @@ -31,9 +47,12 @@ const RecordScreenCard = forwardRef((props: any, ref: any) => { {t('home.fullScreen')}