diff --git a/packages/desktop/electron/main/config.ts b/packages/desktop/electron/main/config.ts
deleted file mode 100644
index c17a72d6..00000000
--- a/packages/desktop/electron/main/config.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-import jsonfile from 'jsonfile';
-import * as fs from 'node:fs';
-import { v5 as uuidv5 } from 'uuid';
-import dayjs from 'dayjs';
-import { PEAR_FILES_PATH, CONFIG_FILE_PATH, DEFAULT_CONFIG_FILE_PATH } from './contract';
-
-export function initConfig() {
- if (!fs.existsSync(PEAR_FILES_PATH)) {
- fs.mkdirSync(PEAR_FILES_PATH, { recursive: true });
- }
- fs.access(DEFAULT_CONFIG_FILE_PATH, fs.constants.F_OK, (err) => {
- if (err) {
- initDefaultConfig();
- return;
- }
- });
-}
-
-function initDefaultConfig() {
- const defaultConfig = {
- user: {
- uuid: uuidv5('https://www.w3.org/', uuidv5.URL),
- userName: `pear-rec:user`,
- userType: 1,
- createdAt: dayjs().format(),
- },
- isProxy: false,
- proxyPort: '7890',
- language: 'zh',
- filePath: PEAR_FILES_PATH,
- openAtLogin: false,
- serverPath: 'http://localhost:9190/',
- };
- jsonfile.writeFileSync(CONFIG_FILE_PATH, defaultConfig, {
- spaces: 2,
- EOL: '\r\n',
- });
- jsonfile.writeFileSync(DEFAULT_CONFIG_FILE_PATH, defaultConfig, {
- spaces: 2,
- EOL: '\r\n',
- });
-}
-
-export function getConfig() {
- try {
- let config = jsonfile.readFileSync(CONFIG_FILE_PATH) || {};
- return config;
- } catch (err) {
- console.log('getConfig :', err);
- }
-}
-
-export function getDefaultConfig() {
- try {
- let defaultConfig = jsonfile.readFileSync(DEFAULT_CONFIG_FILE_PATH) || {};
- return defaultConfig;
- } catch (err) {
- console.log('getConfig :', err);
- }
-}
-
-export function resetConfig() {
- try {
- let defaultConfig = jsonfile.readFileSync(DEFAULT_CONFIG_FILE_PATH) || {};
- jsonfile.writeFileSync(CONFIG_FILE_PATH, defaultConfig, {
- spaces: 2,
- EOL: '\r\n',
- });
- return defaultConfig;
- } catch (err) {
- console.log('getConfig :', err);
- }
-}
-
-export function editConfig(key: string, value: any, cb?: Function) {
- try {
- let config = jsonfile.readFileSync(CONFIG_FILE_PATH) || {};
- config[key] = value;
- jsonfile
- .writeFile(CONFIG_FILE_PATH, config, {
- spaces: 2,
- EOL: '\r\n',
- })
- .then(() => {
- cb && cb();
- });
- return config;
- } catch (err) {
- console.log('editConfig :', err);
- }
-}
-
-export function editUser(key: string, value: string, cb?: Function) {
- try {
- jsonfile.readFile(CONFIG_FILE_PATH).then((config) => {
- const user = config.user;
- user[key] = value;
- jsonfile.writeFile(CONFIG_FILE_PATH, { user: user }, { spaces: 2, EOL: '\r\n' }).then(() => {
- cb && cb();
- });
- });
- } catch (err) {
- console.log('editUser :', err);
- }
-}
diff --git a/packages/desktop/electron/main/contract.ts b/packages/desktop/electron/main/contract.ts
index b6fa4b44..fc5ab801 100644
--- a/packages/desktop/electron/main/contract.ts
+++ b/packages/desktop/electron/main/contract.ts
@@ -7,6 +7,9 @@ process.env.DIST = path.join(process.env.DIST_ELECTRON, '../dist');
export const url = import.meta.env.VITE_DEV_SERVER_URL;
export const WEB_URL = import.meta.env.VITE_WEB_URL;
export const VITE_API_URL = import.meta.env.VITE_API_URL;
+// export const url = 'http://127.0.0.1:7777/';
+// export const WEB_URL = 'http://127.0.0.1:9191/';
+// export const VITE_API_URL = 'http://127.0.0.1:9190/';
export const preload = path.join(__dirname, '../preload/index.js');
export const DIST_ELECTRON = path.join(__dirname, '../');
diff --git a/packages/desktop/electron/main/index.ts b/packages/desktop/electron/main/index.ts
index d9aef56e..9d3794fc 100644
--- a/packages/desktop/electron/main/index.ts
+++ b/packages/desktop/electron/main/index.ts
@@ -2,15 +2,14 @@ import { app, BrowserWindow, shell, ipcMain } from 'electron';
import { release } from 'node:os';
import * as mainWin from '../win/mainWin';
import { initTray } from './tray';
-import './ipcMain';
import { update } from './update';
import { registerFileProtocol } from './protocol';
import { registerGlobalShortcut, unregisterAllGlobalShortcut } from './globalShortcut';
-import { initConfig } from './config';
-import initApp from '@pear-rec/server/src';
+import { initConfig, getConfig } from '@pear-rec/server/src/config';
+import './ipcMain';
+import '@pear-rec/server/src';
-initApp();
-const config = initConfig();
+initConfig();
// The built directory structure
//
@@ -44,11 +43,11 @@ async function createWindow() {
}
app.whenReady().then(() => {
+ const config = getConfig();
registerFileProtocol();
createWindow();
initTray(config.language);
registerGlobalShortcut();
- // Apply electron-updater
update();
});
diff --git a/packages/desktop/electron/main/ipcMain.ts b/packages/desktop/electron/main/ipcMain.ts
index 01a21c2f..eef4b371 100644
--- a/packages/desktop/electron/main/ipcMain.ts
+++ b/packages/desktop/electron/main/ipcMain.ts
@@ -14,7 +14,7 @@ import * as recordsWin from '../win/recordsWin';
import * as pinImageWin from '../win/pinImageWin';
import * as recorderFullScreenWin from '../win/recorderFullScreenWin';
import * as utils from './utils';
-import { editConfig } from './config';
+import { editConfig } from '@pear-rec/server/src/config';
const selfWindws = async () =>
await Promise.all(
@@ -159,6 +159,9 @@ function initIpcMain() {
ipcMain.handle('ss:get-desktop-capturer-source', async () => {
return [...(await desktopCapturer.getSources({ types: ['screen'] })), ...(await selfWindws())];
});
+ ipcMain.on('ss:copy-img', (e, imgUrl) => {
+ shotScreenWin.copyImg(imgUrl);
+ });
// 图片展示
ipcMain.on('vi:open-win', (e, search) => {
viewImageWin.openViewImageWin(search);
diff --git a/packages/desktop/electron/preload/electronAPI.ts b/packages/desktop/electron/preload/electronAPI.ts
index f05c006e..9991e0c9 100644
--- a/packages/desktop/electron/preload/electronAPI.ts
+++ b/packages/desktop/electron/preload/electronAPI.ts
@@ -59,6 +59,7 @@ contextBridge.exposeInMainWorld('electronAPI', {
sendSsDownloadImg: (imgUrl: string) => ipcRenderer.send('ss:download-img', imgUrl),
sendSsSaveImg: (imgUrl: string) => ipcRenderer.send('ss:save-img', imgUrl),
sendSsOpenExternal: (tabUrl: string) => ipcRenderer.send('ss:open-external', tabUrl),
+ sendSsCopyImg: (imgUrl: string) => ipcRenderer.send('ss:copy-img', imgUrl),
//viWin
sendViCloseWin: () => ipcRenderer.send('vi:close-win'),
diff --git a/packages/desktop/electron/win/pinImageWin.ts b/packages/desktop/electron/win/pinImageWin.ts
index a85f16d6..67230999 100644
--- a/packages/desktop/electron/win/pinImageWin.ts
+++ b/packages/desktop/electron/win/pinImageWin.ts
@@ -42,9 +42,7 @@ function closePinImageWin() {
}
function openPinImageWin(search?: any) {
- if (!pinImageWin || pinImageWin?.isDestroyed()) {
- pinImageWin = createPinImageWin(search);
- }
+ pinImageWin = createPinImageWin(search);
pinImageWin?.show();
}
diff --git a/packages/desktop/electron/win/shotScreenWin.ts b/packages/desktop/electron/win/shotScreenWin.ts
index 33713860..52cdd905 100644
--- a/packages/desktop/electron/win/shotScreenWin.ts
+++ b/packages/desktop/electron/win/shotScreenWin.ts
@@ -137,4 +137,5 @@ export {
maximizeShotScreenWin,
unmaximizeShotScreenWin,
downloadURLShotScreenWin,
+ copyImg,
};
diff --git a/packages/desktop/package.json b/packages/desktop/package.json
index f727825e..4e2ee113 100644
--- a/packages/desktop/package.json
+++ b/packages/desktop/package.json
@@ -43,4 +43,4 @@
"engines": {
"node": "^14.18.0 || >=16.0.0"
}
-}
+}
\ No newline at end of file
diff --git a/packages/screenshot/src/Screenshots/icons/iconfont.scss b/packages/screenshot/src/Screenshots/icons/iconfont.scss
index 3b5003b9..4c353741 100644
--- a/packages/screenshot/src/Screenshots/icons/iconfont.scss
+++ b/packages/screenshot/src/Screenshots/icons/iconfont.scss
@@ -1,78 +1,88 @@
@font-face {
- font-family: "screenshots-icon"; /* Project id 572327 */
- src: url("iconfont.woff2") format("woff2"),
- url("iconfont.woff") format("woff"), url("iconfont.ttf") format("truetype");
+ font-family: 'screenshots-icon'; /* Project id 572327 */
+ src: url('iconfont.woff2') format('woff2'), url('iconfont.woff') format('woff'),
+ url('iconfont.ttf') format('truetype');
}
-[class^="icon-"],
-[class*=" icon-"] {
- font-family: "screenshots-icon" !important;
- font-style: normal;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
+[class^='icon-'],
+[class*=' icon-'] {
+ font-family: 'screenshots-icon' !important;
+ font-style: normal;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
}
.icon-ok:before {
- content: "\e001";
+ content: '\e001';
}
.icon-cancel:before {
- content: "\e002";
+ content: '\e002';
}
.icon-save:before {
- content: "\e003";
+ content: '\e003';
}
.icon-redo:before {
- content: "\e004";
+ content: '\e004';
}
.icon-undo:before {
- content: "\e005";
+ content: '\e005';
}
.icon-mosaic:before {
- content: "\e006";
+ content: '\e006';
}
.icon-text:before {
- content: "\e007";
+ content: '\e007';
}
.icon-brush:before {
- content: "\e008";
+ content: '\e008';
}
.icon-arrow:before {
- content: "\e009";
+ content: '\e009';
}
.icon-ellipse:before {
- content: "\e00a";
+ content: '\e00a';
}
.icon-rectangle:before {
- content: "\e00b";
+ content: '\e00b';
}
.icon-scan:before {
- content: "";
- background: transparent url(/imgs/svg/scan.svg) no-repeat 0px 0px;
- background-size: 22px;
- background-position: center;
- width: 35px;
- height: 35px;
- display: inline-block;
+ content: '';
+ background: transparent url(/imgs/svg/scan.svg) no-repeat 0px 0px;
+ background-size: 22px;
+ background-position: center;
+ width: 35px;
+ height: 35px;
+ display: inline-block;
}
.icon-search:before {
- content: "";
- background: transparent url(/imgs/svg/search.svg) no-repeat 0px 0px;
- background-size: 22px;
- background-position: center;
- width: 35px;
- height: 35px;
- display: inline-block;
+ content: '';
+ background: transparent url(/imgs/svg/search.svg) no-repeat 0px 0px;
+ background-size: 22px;
+ background-position: center;
+ width: 35px;
+ height: 35px;
+ display: inline-block;
+}
+
+.icon-pin:before {
+ content: '';
+ background: transparent url(/imgs/svg/pin.svg) no-repeat 0px 0px;
+ background-size: 22px;
+ background-position: center;
+ width: 35px;
+ height: 35px;
+ display: inline-block;
}
diff --git a/packages/screenshot/src/Screenshots/operations/Pin/index.tsx b/packages/screenshot/src/Screenshots/operations/Pin/index.tsx
new file mode 100644
index 00000000..50b6e0e1
--- /dev/null
+++ b/packages/screenshot/src/Screenshots/operations/Pin/index.tsx
@@ -0,0 +1,37 @@
+import React, { ReactElement, useCallback } from 'react';
+import useStore from '../../hooks/useStore';
+import useCall from '../../hooks/useCall';
+import useCanvasContextRef from '../../hooks/useCanvasContextRef';
+import useHistory from '../../hooks/useHistory';
+import useReset from '../../hooks/useReset';
+import ScreenshotsButton from '../../ScreenshotsButton';
+import composeImage from '../../composeImage';
+
+export default function Pin(): ReactElement {
+ const { image, width, height, history, bounds, lang } = useStore();
+ const canvasContextRef = useCanvasContextRef();
+ const [, historyDispatcher] = useHistory();
+ const call = useCall();
+ const reset = useReset();
+
+ const onClick = useCallback(() => {
+ historyDispatcher.clearSelect();
+ setTimeout(() => {
+ if (!canvasContextRef.current || !image || !bounds) {
+ return;
+ }
+ composeImage({
+ image,
+ width,
+ height,
+ history,
+ bounds,
+ }).then((blob) => {
+ call('onPin', blob, bounds);
+ reset();
+ });
+ });
+ }, [canvasContextRef, historyDispatcher, image, width, height, history, bounds, call, reset]);
+
+ return ;
+}
diff --git a/packages/screenshot/src/Screenshots/operations/Scan/index.tsx b/packages/screenshot/src/Screenshots/operations/Scan/index.tsx
index 4dfb0f5f..164f4419 100644
--- a/packages/screenshot/src/Screenshots/operations/Scan/index.tsx
+++ b/packages/screenshot/src/Screenshots/operations/Scan/index.tsx
@@ -1,62 +1,46 @@
-import React, { ReactElement, useCallback } from "react";
-import QrScanner from "qr-scanner";
-import useStore from "../../hooks/useStore";
-import useCall from "../../hooks/useCall";
-import useCanvasContextRef from "../../hooks/useCanvasContextRef";
-import useHistory from "../../hooks/useHistory";
-import useReset from "../../hooks/useReset";
-import ScreenshotsButton from "../../ScreenshotsButton";
-import composeImage from "../../composeImage";
+import React, { ReactElement, useCallback } from 'react';
+import QrScanner from 'qr-scanner';
+import useStore from '../../hooks/useStore';
+import useCall from '../../hooks/useCall';
+import useCanvasContextRef from '../../hooks/useCanvasContextRef';
+import useHistory from '../../hooks/useHistory';
+import useReset from '../../hooks/useReset';
+import ScreenshotsButton from '../../ScreenshotsButton';
+import composeImage from '../../composeImage';
-export default function Ok(): ReactElement {
- const { image, width, height, history, bounds, lang } = useStore();
- const canvasContextRef = useCanvasContextRef();
- const [, historyDispatcher] = useHistory();
- const call = useCall();
- const reset = useReset();
+export default function Scan(): ReactElement {
+ const { image, width, height, history, bounds, lang } = useStore();
+ const canvasContextRef = useCanvasContextRef();
+ const [, historyDispatcher] = useHistory();
+ const call = useCall();
+ const reset = useReset();
- const onClick = useCallback(() => {
- historyDispatcher.clearSelect();
- setTimeout(() => {
- if (!canvasContextRef.current || !image || !bounds) {
- return;
- }
- composeImage({
- image,
- width,
- height,
- history,
- bounds,
- }).then(async (blob) => {
- try {
- const result = await QrScanner.scanImage(blob);
- if (result) {
- call("onScan", result);
- }
- } catch (error) {
- console.error("Error:", error);
- }
+ const onClick = useCallback(() => {
+ historyDispatcher.clearSelect();
+ setTimeout(() => {
+ if (!canvasContextRef.current || !image || !bounds) {
+ return;
+ }
+ composeImage({
+ image,
+ width,
+ height,
+ history,
+ bounds,
+ }).then(async (blob) => {
+ try {
+ const result = await QrScanner.scanImage(blob);
+ if (result) {
+ call('onScan', result);
+ }
+ } catch (error) {
+ console.error('Error:', error);
+ }
- reset();
- });
- });
- }, [
- canvasContextRef,
- historyDispatcher,
- image,
- width,
- height,
- history,
- bounds,
- call,
- reset,
- ]);
+ reset();
+ });
+ });
+ }, [canvasContextRef, historyDispatcher, image, width, height, history, bounds, call, reset]);
- return (
-
- );
+ return ;
}
diff --git a/packages/screenshot/src/Screenshots/operations/Search/index.tsx b/packages/screenshot/src/Screenshots/operations/Search/index.tsx
index 160eb52b..5be43a3c 100644
--- a/packages/screenshot/src/Screenshots/operations/Search/index.tsx
+++ b/packages/screenshot/src/Screenshots/operations/Search/index.tsx
@@ -1,53 +1,39 @@
-import React, { ReactElement, useCallback } from "react";
-import useStore from "../../hooks/useStore";
-import useCall from "../../hooks/useCall";
-import useCanvasContextRef from "../../hooks/useCanvasContextRef";
-import useHistory from "../../hooks/useHistory";
-import useReset from "../../hooks/useReset";
-import ScreenshotsButton from "../../ScreenshotsButton";
-import composeImage from "../../composeImage";
+import React, { ReactElement, useCallback } from 'react';
+import useStore from '../../hooks/useStore';
+import useCall from '../../hooks/useCall';
+import useCanvasContextRef from '../../hooks/useCanvasContextRef';
+import useHistory from '../../hooks/useHistory';
+import useReset from '../../hooks/useReset';
+import ScreenshotsButton from '../../ScreenshotsButton';
+import composeImage from '../../composeImage';
-export default function Ok(): ReactElement {
- const { image, width, height, history, bounds, lang } = useStore();
- const canvasContextRef = useCanvasContextRef();
- const [, historyDispatcher] = useHistory();
- const call = useCall();
- const reset = useReset();
+export default function Search(): ReactElement {
+ const { image, width, height, history, bounds, lang } = useStore();
+ const canvasContextRef = useCanvasContextRef();
+ const [, historyDispatcher] = useHistory();
+ const call = useCall();
+ const reset = useReset();
- const onClick = useCallback(() => {
- historyDispatcher.clearSelect();
- setTimeout(() => {
- if (!canvasContextRef.current || !image || !bounds) {
- return;
- }
- composeImage({
- image,
- width,
- height,
- history,
- bounds,
- }).then((blob) => {
- call("onSearch", blob);
- reset();
- });
- });
- }, [
- canvasContextRef,
- historyDispatcher,
- image,
- width,
- height,
- history,
- bounds,
- call,
- reset,
- ]);
+ const onClick = useCallback(() => {
+ historyDispatcher.clearSelect();
+ setTimeout(() => {
+ if (!canvasContextRef.current || !image || !bounds) {
+ return;
+ }
+ composeImage({
+ image,
+ width,
+ height,
+ history,
+ bounds,
+ }).then((blob) => {
+ call('onSearch', blob);
+ reset();
+ });
+ });
+ }, [canvasContextRef, historyDispatcher, image, width, height, history, bounds, call, reset]);
- return (
-
- );
+ return (
+
+ );
}
diff --git a/packages/screenshot/src/Screenshots/operations/index.ts b/packages/screenshot/src/Screenshots/operations/index.ts
index 753be650..dc2d8a48 100644
--- a/packages/screenshot/src/Screenshots/operations/index.ts
+++ b/packages/screenshot/src/Screenshots/operations/index.ts
@@ -1,32 +1,34 @@
-import Ok from "./Ok";
-import Cancel from "./Cancel";
-import Save from "./Save";
-import Redo from "./Redo";
-import Undo from "./Undo";
-import Mosaic from "./Mosaic";
-import Text from "./Text";
-import Brush from "./Brush";
-import Arrow from "./Arrow";
-import Ellipse from "./Ellipse";
-import Rectangle from "./Rectangle";
-import Search from "./Search";
-import Scan from "./Scan";
+import Ok from './Ok';
+import Cancel from './Cancel';
+import Save from './Save';
+import Redo from './Redo';
+import Undo from './Undo';
+import Mosaic from './Mosaic';
+import Text from './Text';
+import Brush from './Brush';
+import Arrow from './Arrow';
+import Ellipse from './Ellipse';
+import Rectangle from './Rectangle';
+import Search from './Search';
+import Scan from './Scan';
+import Pin from './Pin';
export default [
- Scan,
- Search,
- "|",
- Rectangle,
- Ellipse,
- Arrow,
- Brush,
- Text,
- Mosaic,
- "|",
- Undo,
- Redo,
- "|",
- Save,
- Cancel,
- Ok,
+ Pin,
+ Scan,
+ Search,
+ '|',
+ Rectangle,
+ Ellipse,
+ Arrow,
+ Brush,
+ Text,
+ Mosaic,
+ '|',
+ Undo,
+ Redo,
+ '|',
+ Save,
+ Cancel,
+ Ok,
];
diff --git a/packages/screenshot/src/Screenshots/zh_CN.ts b/packages/screenshot/src/Screenshots/zh_CN.ts
index e1c1b274..b2327901 100644
--- a/packages/screenshot/src/Screenshots/zh_CN.ts
+++ b/packages/screenshot/src/Screenshots/zh_CN.ts
@@ -1,35 +1,37 @@
export interface Lang {
- magnifier_position_label: string;
- operation_ok_title: string;
- operation_cancel_title: string;
- operation_save_title: string;
- operation_redo_title: string;
- operation_undo_title: string;
- operation_mosaic_title: string;
- operation_text_title: string;
- operation_brush_title: string;
- operation_arrow_title: string;
- operation_ellipse_title: string;
- operation_rectangle_title: string;
- operation_search_title: string;
- operation_scan_title: string;
+ magnifier_position_label: string;
+ operation_ok_title: string;
+ operation_cancel_title: string;
+ operation_save_title: string;
+ operation_redo_title: string;
+ operation_undo_title: string;
+ operation_mosaic_title: string;
+ operation_text_title: string;
+ operation_brush_title: string;
+ operation_arrow_title: string;
+ operation_ellipse_title: string;
+ operation_rectangle_title: string;
+ operation_search_title: string;
+ operation_scan_title: string;
+ operation_pin_title: string;
}
const zhCN: Lang = {
- magnifier_position_label: "坐标",
- operation_ok_title: "确定",
- operation_cancel_title: "取消",
- operation_save_title: "保存",
- operation_redo_title: "重做",
- operation_undo_title: "撤销",
- operation_mosaic_title: "马赛克",
- operation_text_title: "文本",
- operation_brush_title: "画笔",
- operation_arrow_title: "箭头",
- operation_ellipse_title: "椭圆",
- operation_rectangle_title: "矩形",
- operation_search_title: "搜图",
- operation_scan_title: "扫码",
+ magnifier_position_label: '坐标',
+ operation_ok_title: '确定',
+ operation_cancel_title: '取消',
+ operation_save_title: '保存',
+ operation_redo_title: '重做',
+ operation_undo_title: '撤销',
+ operation_mosaic_title: '马赛克',
+ operation_text_title: '文本',
+ operation_brush_title: '画笔',
+ operation_arrow_title: '箭头',
+ operation_ellipse_title: '椭圆',
+ operation_rectangle_title: '矩形',
+ operation_search_title: '搜图',
+ operation_scan_title: '扫码',
+ operation_pin_title: '钉图',
};
export default zhCN;
diff --git a/packages/server/index.d.ts b/packages/server/index.d.ts
deleted file mode 100644
index 0499d1a1..00000000
--- a/packages/server/index.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-export default function initApp();
diff --git a/packages/server/index.ts b/packages/server/index.ts
deleted file mode 100644
index d45ec5bd..00000000
--- a/packages/server/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import initApp from './src';
-
-initApp();
diff --git a/packages/server/package.json b/packages/server/package.json
index ccf3d4a1..26ef4994 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -7,6 +7,7 @@
"scripts": {
"dev": "nodemon index.ts",
"build": "rollup -c",
+ "watch": "rollup -c --watch",
"preview": "node dist/index.js"
},
"author": "027xiguapi",
@@ -35,4 +36,4 @@
"sql.js": "^1.8.0",
"typeorm": "^0.3.17"
}
-}
+}
\ No newline at end of file
diff --git a/packages/server/src/config/index.ts b/packages/server/src/config/index.ts
index 525a540f..93785899 100644
--- a/packages/server/src/config/index.ts
+++ b/packages/server/src/config/index.ts
@@ -72,14 +72,18 @@ export function resetConfig() {
}
}
-export function editConfig(key: string, value: any) {
+export function editConfig(key: string, value: any, cb?: Function) {
try {
let config = jsonfile.readFileSync(CONFIG_FILE_PATH) || {};
config[key] = value;
- jsonfile.writeFileSync(CONFIG_FILE_PATH, config, {
- spaces: 2,
- EOL: '\r\n',
- });
+ jsonfile
+ .writeFile(CONFIG_FILE_PATH, config, {
+ spaces: 2,
+ EOL: '\r\n',
+ })
+ .then(() => {
+ cb && cb();
+ });
return config;
} catch (err) {
console.log('editConfig :', err);
diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts
index 3180af01..f2778dbf 100644
--- a/packages/server/src/index.ts
+++ b/packages/server/src/index.ts
@@ -3,7 +3,7 @@ import cors from 'cors';
import bodyParser from 'body-parser';
import express, { Request, Response } from 'express';
import { AppDataSource } from './dataSource';
-import { AppRoutes } from './route';
+import { AppRoutes } from './route/index';
import { initApi } from './api';
import { initConfig } from './config';
import { PORT } from './contract';
@@ -39,3 +39,5 @@ export default function initApp() {
})
.catch((error) => console.log('TypeORM connection error: ', error));
}
+
+initApp();
diff --git a/packages/server/src/route/index.ts b/packages/server/src/route/index.ts
index 5ce73212..467cf24e 100644
--- a/packages/server/src/route/index.ts
+++ b/packages/server/src/route/index.ts
@@ -1,6 +1,6 @@
-import { UserRoutes } from "./User";
-import { RecordRoutes } from "./Record";
-import { SettingRoutes } from "./Setting";
+import { UserRoutes } from './User';
+import { RecordRoutes } from './Record';
+import { SettingRoutes } from './Setting';
/**
* All application routes.
diff --git a/packages/server/src/util/index.ts b/packages/server/src/util/index.ts
index 37a34587..9601f811 100644
--- a/packages/server/src/util/index.ts
+++ b/packages/server/src/util/index.ts
@@ -22,6 +22,7 @@ export function getImgsByImgUrl(imgUrl: string, isElectron: boolean) {
filePath == imgUrl && (currentIndex = index);
imgs.push({
url: `${getProtocol(isElectron, 'getFile')}${filePath}`,
+ filePath: filePath,
index,
});
index++;
diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json
index f857aa6a..e8ac29be 100644
--- a/packages/server/tsconfig.json
+++ b/packages/server/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "target": "ESNext",
+ "target": "ES5",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true,
diff --git a/packages/web/CHANGELOG.md b/packages/web/CHANGELOG.md
index 139e5015..a3abdec4 100644
--- a/packages/web/CHANGELOG.md
+++ b/packages/web/CHANGELOG.md
@@ -1,5 +1,9 @@
# @pear-rec/web
+## 1.3.5
+
+feat: 截图钉图
+
## 1.3.4
feat: 重置设置、显示快捷键
diff --git a/packages/web/package.json b/packages/web/package.json
index 9abeb8ec..5907ff04 100644
--- a/packages/web/package.json
+++ b/packages/web/package.json
@@ -1,7 +1,7 @@
{
"name": "@pear-rec/web",
"private": true,
- "version": "1.3.2",
+ "version": "1.3.5",
"scripts": {
"dev": "vite",
"build": "rimraf dist && tsc && vite build",
diff --git a/packages/web/public/imgs/svg/pin.svg b/packages/web/public/imgs/svg/pin.svg
new file mode 100644
index 00000000..edbfc6af
--- /dev/null
+++ b/packages/web/public/imgs/svg/pin.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/web/src/components/card/editImageCard.tsx b/packages/web/src/components/card/editImageCard.tsx
index 34ab7ed9..2f1656b8 100644
--- a/packages/web/src/components/card/editImageCard.tsx
+++ b/packages/web/src/components/card/editImageCard.tsx
@@ -10,7 +10,7 @@ const EditImageCard = forwardRef((props: any, ref: any) => {
function handleUploadFile(event) {
const file = event.target.files[0];
if (window.electronAPI) {
- window.electronAPI.sendEiOpenWin({ imgUrl: 'pearrec:///' + file.path });
+ window.electronAPI.sendEiOpenWin({ imgUrl: file.path });
} else {
const imgUrl = window.URL.createObjectURL(file);
Modal.confirm({
diff --git a/packages/web/src/pages/editImage/index.tsx b/packages/web/src/pages/editImage/index.tsx
index 01447aeb..af06612d 100644
--- a/packages/web/src/pages/editImage/index.tsx
+++ b/packages/web/src/pages/editImage/index.tsx
@@ -190,6 +190,9 @@ const EditImage = () => {
const paramsString = location.search;
const searchParams = new URLSearchParams(paramsString);
let imgUrl = searchParams.get('imgUrl');
+ if (imgUrl.substring(0, 4) != 'blob') {
+ imgUrl = `${window.baseURL}getFile?url=${imgUrl}`;
+ }
const instance = new ImageEditor(document.querySelector('#tui-image-editor'), {
includeUI: {
loadImage: {
diff --git a/packages/web/src/pages/main.tsx b/packages/web/src/pages/main.tsx
index 11c3b112..0b2e3f01 100644
--- a/packages/web/src/pages/main.tsx
+++ b/packages/web/src/pages/main.tsx
@@ -6,6 +6,7 @@ export default function initApp(App) {
const userAgent = navigator.userAgent.toLowerCase();
window.isElectron = userAgent.indexOf(' electron/') > -1 ? true : false;
window.isOffline = location.host == 'pear-rec-xiguapi.vercel.app' ? true : false;
+ window.baseURL = import.meta.env.VITE_API_URL;
const container = document.getElementById('root') as HTMLElement;
const root = createRoot(container);
initI18n();
diff --git a/packages/web/src/pages/pinImage/index.tsx b/packages/web/src/pages/pinImage/index.tsx
index a802637e..0fefd0e3 100644
--- a/packages/web/src/pages/pinImage/index.tsx
+++ b/packages/web/src/pages/pinImage/index.tsx
@@ -53,9 +53,14 @@ const PinImage: React.FC = () => {
const paramsString = location.search;
const searchParams = new URLSearchParams(paramsString);
let _imgUrl = searchParams.get('imgUrl') || defaultImg;
+ if (_imgUrl.substring(0, 4) != 'blob') {
+ _imgUrl = `${window.baseURL}getFile?url=${_imgUrl}`;
+ }
+
fetch(_imgUrl)
.then((response) => response.blob()) // 将获取到的图片转为 Blob
.then((blob) => {
+ console.log(blob);
setImgUrl(`url(${URL.createObjectURL(blob)})`);
});
}
diff --git a/packages/web/src/pages/shotScreen/index.tsx b/packages/web/src/pages/shotScreen/index.tsx
index df2235ff..df98c904 100644
--- a/packages/web/src/pages/shotScreen/index.tsx
+++ b/packages/web/src/pages/shotScreen/index.tsx
@@ -114,7 +114,7 @@ function ShotScreen() {
window.isOffline ? saveAs(url, `pear-rec_${+new Date()}.png`) : saveFile(blob);
}, []);
- async function saveFile(blob) {
+ async function saveFile(blob, isPin?) {
try {
const formData = new FormData();
formData.append('type', 'ss');
@@ -122,9 +122,14 @@ function ShotScreen() {
formData.append('file', blob);
const res = (await api.saveFile(formData)) as any;
if (res.code == 0) {
+ copyImg(window.isElectron ? res.data.filePath : blob);
if (window.isElectron) {
window.electronAPI?.sendSsCloseWin();
- window.electronAPI?.sendViOpenWin({ imgUrl: res.data.filePath });
+ isPin
+ ? window.electronAPI?.sendPiOpenWin({
+ imgUrl: res.data.filePath,
+ })
+ : window.electronAPI?.sendViOpenWin({ imgUrl: res.data.filePath });
} else {
Modal.confirm({
title: '图片已保存,是否查看?',
@@ -132,7 +137,9 @@ function ShotScreen() {
okText: t('modal.ok'),
cancelText: t('modal.cancel'),
onOk() {
- location.href = `/viewImage.html?imgUrl=${res.data.filePath}`;
+ location.href = isPin
+ ? `/pinImage.html?imgUrl=${res.data.filePath}`
+ : `/viewImage.html?imgUrl=${res.data.filePath}`;
},
});
}
@@ -142,15 +149,21 @@ function ShotScreen() {
}
}
- async function copyImg(url) {
- const data = await fetch(url);
- const blob = await data.blob();
+ const onPin = useCallback(async (blob) => {
+ const imgUrl = URL.createObjectURL(blob);
+ window.isOffline ? saveAs(imgUrl, `pear-rec_${+new Date()}.png`) : saveFile(blob, true);
+ }, []);
- await navigator.clipboard.write([
- new ClipboardItem({
- [blob.type]: blob,
- }),
- ]);
+ async function copyImg(blob) {
+ if (window.isElectron) {
+ window.electronAPI.sendSsCopyImg(blob);
+ } else {
+ await navigator.clipboard.write([
+ new ClipboardItem({
+ [blob.type]: blob,
+ }),
+ ]);
+ }
}
function handleUploadImg(files) {
@@ -170,6 +183,7 @@ function ShotScreen() {
onOk={onOk}
onSearch={onSearch}
onScan={onScan}
+ onPin={onPin}
/>
) : window.isElectron ? (
<>>
diff --git a/packages/web/src/pages/viewImage/index.tsx b/packages/web/src/pages/viewImage/index.tsx
index 0f0c4868..9159c07a 100644
--- a/packages/web/src/pages/viewImage/index.tsx
+++ b/packages/web/src/pages/viewImage/index.tsx
@@ -20,11 +20,11 @@ const ViewImage = () => {
const { t } = useTranslation();
const api = useApi();
const userApi = useUserApi();
- let viewerRef = useRef();
+ const viewerRef = useRef();
+ const initialViewIndexRef = useRef(0);
const inputRef = useRef(null);
const [user, setUser] = useState({});
const [imgs, setImgs] = useState([]);
- const [initialViewIndex, setInitialViewIndex] = useState(0);
const [isFull, setIsFull] = useState(false);
useEffect(() => {
@@ -62,7 +62,7 @@ const ViewImage = () => {
// 3: width>992px
// 4: width>1200px
inline: true,
- initialViewIndex: initialViewIndex,
+ initialViewIndex: initialViewIndexRef.current,
className: 'viewImgs',
toolbar: {
alwaysOnTopWin: handleToggleAlwaysOnTopWin,
@@ -71,7 +71,7 @@ const ViewImage = () => {
},
scan: async () => {
try {
- const imgUrl = imgs[initialViewIndex]?.url;
+ const imgUrl = imgs[initialViewIndexRef.current]?.url;
const result = await QrScanner.scanImage(imgUrl);
Modal.confirm({
title: '扫码结果',
@@ -94,7 +94,7 @@ const ViewImage = () => {
}
},
search: async () => {
- const imgUrl = imgs[initialViewIndex]?.url;
+ const imgUrl = imgs[initialViewIndexRef.current]?.url;
const blob = await urlToBlob(imgUrl);
const tabUrl = await searchImg(blob, user.isProxy);
if (window.electronAPI) {
@@ -121,7 +121,7 @@ const ViewImage = () => {
window.print();
},
edit: () => {
- const imgUrl = imgs[initialViewIndex]?.url;
+ const imgUrl = imgs[initialViewIndexRef.current]?.filePath;
if (window.electronAPI) {
window.electronAPI.sendViCloseWin();
window.electronAPI.sendEiOpenWin({ imgUrl });
@@ -131,6 +131,9 @@ const ViewImage = () => {
}
},
},
+ viewed: () => {
+ initialViewIndexRef.current = viewer.index;
+ },
}) as any;
viewerRef.current = viewer;
}
@@ -201,15 +204,13 @@ const ViewImage = () => {
}
async function handleToggleAlwaysOnTopWin() {
- const imgUrl = imgs[initialViewIndex]?.url;
+ const imgUrl = imgs[initialViewIndexRef.current]?.filePath;
if (window.isElectron) {
+ window.electronAPI.sendViCloseWin();
window.electronAPI.sendPiOpenWin({ imgUrl });
} else {
window.open(`/pinImage.html?imgUrl=${imgUrl}`);
}
- // const isAlwaysOnTop = await window.electronAPI?.invokeViSetIsAlwaysOnTop();
- // const icon = document.querySelector('.viewer-always-on-top-win');
- // isAlwaysOnTop ? icon.classList.add('current') : icon.classList.remove('current');
}
async function initImgs() {
@@ -218,18 +219,18 @@ const ViewImage = () => {
const imgUrl = searchParams.get('imgUrl') || user.historyImg;
if (imgUrl) {
if (imgUrl.substring(0, 4) == 'blob') {
- setImgs([{ url: imgUrl, index: 0 }]);
+ setImgs([{ url: imgUrl, filePath: imgUrl, index: 0 }]);
} else {
const res = (await api.getImgs(imgUrl)) as any;
if (res.code == 0) {
setImgs(res.data.imgs);
- setInitialViewIndex(res.data.currentIndex);
+ initialViewIndexRef.current = res.data.currentIndex;
} else {
- setImgs([{ url: imgUrl, index: 0 }]);
+ setImgs([{ url: imgUrl, filePath: imgUrl, index: 0 }]);
}
}
} else {
- setImgs([{ url: defaultImg, index: 0 }]);
+ setImgs([{ url: defaultImg, filePath: defaultImg, index: 0 }]);
}
}
@@ -238,7 +239,7 @@ const ViewImage = () => {
const url = window.URL.createObjectURL(selectedFile);
viewerRef.current?.destroy();
setImgs([...imgs, { url: url, index: imgs.length }]);
- setInitialViewIndex(imgs.length);
+ initialViewIndexRef.current = imgs.length;
}
return (
diff --git a/packages/web/src/vite-env.d.ts b/packages/web/src/vite-env.d.ts
index 87e5d24a..137706fe 100644
--- a/packages/web/src/vite-env.d.ts
+++ b/packages/web/src/vite-env.d.ts
@@ -3,17 +3,18 @@
export {};
declare global {
- interface Window {
- electronAPI: any;
- isElectron: boolean;
+ interface Window {
+ electronAPI: any;
+ isElectron: boolean;
isOffline: boolean;
- }
+ baseURL: string;
+ }
}
-declare module "react" {
- interface InputHTMLAttributes extends HTMLAttributes {
- // extends React's HTMLAttributes
- directory?: string;
- webkitdirectory?: string;
- }
+declare module 'react' {
+ interface InputHTMLAttributes extends HTMLAttributes {
+ // extends React's HTMLAttributes
+ directory?: string;
+ webkitdirectory?: string;
+ }
}