mirror of
https://github.com/kuaifan/dootask.git
synced 2026-02-15 03:57:38 +00:00
perf: 优化桌面端邮件图片菜单
This commit is contained in:
parent
4a75844c98
commit
2b88764c7e
154
electron/electron-menu.js
vendored
Normal file
154
electron/electron-menu.js
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
const {
|
||||
clipboard,
|
||||
nativeImage,
|
||||
Menu,
|
||||
MenuItem,
|
||||
dialog,
|
||||
shell,
|
||||
} = require('electron')
|
||||
const fs = require('fs')
|
||||
const url = require('url')
|
||||
const {pipeline} = require('stream')
|
||||
|
||||
const MAILTO_PREFIX = "mailto:";
|
||||
|
||||
const PERMITTED_URL_SCHEMES = ["http:", "https:", MAILTO_PREFIX];
|
||||
|
||||
const electronMenu = {
|
||||
language: {
|
||||
openInBrowser: "在浏览器中打开",
|
||||
saveImageAs: "图片存储为...",
|
||||
copyImage: "复制图片",
|
||||
copyEmailAddress: "复制电子邮件地址",
|
||||
copyLinkAddress: "复制链接地址",
|
||||
copyImageAddress: "复制图片地址",
|
||||
failedToSaveImage: "图片保存失败",
|
||||
theImageFailedToSave: "图片无法保存",
|
||||
},
|
||||
|
||||
setLanguage(language) {
|
||||
this.language = Object.assign(this.language, language);
|
||||
},
|
||||
|
||||
safeOpenURL(target) {
|
||||
const parsedUrl = url.parse(target);
|
||||
if (PERMITTED_URL_SCHEMES.includes(parsedUrl.protocol)) {
|
||||
const newTarget = url.format(parsedUrl);
|
||||
shell.openExternal(newTarget).then(r => {
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async saveImageAs(url, params) {
|
||||
const targetFileName = params.suggestedFilename || params.altText || "image.png";
|
||||
const {filePath} = await dialog.showSaveDialog({
|
||||
defaultPath: targetFileName,
|
||||
});
|
||||
|
||||
if (!filePath) return; // user cancelled dialog
|
||||
|
||||
try {
|
||||
if (url.startsWith("data:")) {
|
||||
await electronMenu.writeNativeImage(filePath, nativeImage.createFromDataURL(url));
|
||||
} else {
|
||||
const resp = await fetch(url);
|
||||
if (!resp.ok) throw new Error(`unexpected response ${resp.statusText}`);
|
||||
if (!resp.body) throw new Error(`unexpected response has no body ${resp.statusText}`);
|
||||
pipeline(resp.body, fs.createWriteStream(filePath));
|
||||
}
|
||||
} catch (err) {
|
||||
await dialog.showMessageBox({
|
||||
type: "error",
|
||||
title: electronMenu.language.failedToSaveImage,
|
||||
message: electronMenu.language.theImageFailedToSave,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
writeNativeImage(filePath, img) {
|
||||
switch (filePath.split(".").pop()?.toLowerCase()) {
|
||||
case "jpg":
|
||||
case "jpeg":
|
||||
return fs.promises.writeFile(filePath, img.toJPEG(100));
|
||||
case "bmp":
|
||||
return fs.promises.writeFile(filePath, img.toBitmap());
|
||||
case "png":
|
||||
default:
|
||||
return fs.promises.writeFile(filePath, img.toPNG());
|
||||
}
|
||||
},
|
||||
|
||||
webContentsMenu(webContents) {
|
||||
webContents.on("context-menu", function (e, params) {
|
||||
if (params.linkURL || params.srcURL) {
|
||||
const url = params.linkURL || params.srcURL;
|
||||
const popupMenu = new Menu();
|
||||
|
||||
if (!url.startsWith("blob:")) {
|
||||
popupMenu.append(
|
||||
new MenuItem({
|
||||
label: electronMenu.language.openInBrowser,
|
||||
accelerator: "o",
|
||||
click() {
|
||||
electronMenu.safeOpenURL(url);
|
||||
},
|
||||
}),
|
||||
);
|
||||
if (params.hasImageContents) {
|
||||
popupMenu.append(
|
||||
new MenuItem({
|
||||
label: electronMenu.language.saveImageAs,
|
||||
accelerator: "s",
|
||||
click: async function () {
|
||||
await electronMenu.saveImageAs(url, params);
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.hasImageContents) {
|
||||
popupMenu.append(
|
||||
new MenuItem({
|
||||
label: electronMenu.language.copyImage,
|
||||
accelerator: "c",
|
||||
click() {
|
||||
webContents.copyImageAt(params.x, params.y);
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (!url.startsWith("blob:")) {
|
||||
if (url.startsWith(MAILTO_PREFIX)) {
|
||||
popupMenu.append(
|
||||
new MenuItem({
|
||||
label: electronMenu.language.copyEmailAddress,
|
||||
accelerator: "a",
|
||||
click() {
|
||||
clipboard.writeText(url.substring(MAILTO_PREFIX.length));
|
||||
},
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
popupMenu.append(
|
||||
new MenuItem({
|
||||
label: params.hasImageContents ? electronMenu.language.copyImageAddress : electronMenu.language.copyLinkAddress,
|
||||
accelerator: "a",
|
||||
click() {
|
||||
clipboard.writeText(url);
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (popupMenu.items.length > 0) {
|
||||
popupMenu.popup({});
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
module.exports = electronMenu;
|
||||
36
electron/electron.js
vendored
36
electron/electron.js
vendored
@ -11,6 +11,7 @@ const crc = require('crc');
|
||||
const zlib = require('zlib');
|
||||
const utils = require('./utils');
|
||||
const config = require('./package.json');
|
||||
const electronMenu = require("./electron-menu");
|
||||
const spawn = require("child_process").spawn;
|
||||
|
||||
const isMac = process.platform === 'darwin'
|
||||
@ -58,6 +59,7 @@ function createMainWindow() {
|
||||
openExternal(url)
|
||||
return {action: 'deny'}
|
||||
})
|
||||
electronMenu.webContentsMenu(mainWindow.webContents)
|
||||
|
||||
if (devloadUrl) {
|
||||
mainWindow.loadURL(devloadUrl).then(_ => {
|
||||
@ -158,6 +160,7 @@ function createSubWindow(args) {
|
||||
openExternal(url)
|
||||
return {action: 'deny'}
|
||||
})
|
||||
electronMenu.webContentsMenu(browser.webContents)
|
||||
|
||||
if (devloadUrl) {
|
||||
browser.loadURL(devloadUrl + '#' + (args.hash || args.path)).then(_ => {
|
||||
@ -257,6 +260,17 @@ app.on('browser-window-focus', () => {
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 设置菜单语言包
|
||||
* @param args {path}
|
||||
*/
|
||||
ipcMain.on('setMenuLanguage', (event, args) => {
|
||||
if (utils.isJson(args)) {
|
||||
electronMenu.setLanguage(args)
|
||||
}
|
||||
event.returnValue = "ok"
|
||||
})
|
||||
|
||||
/**
|
||||
* 打开文件
|
||||
* @param args {path}
|
||||
@ -475,6 +489,28 @@ ipcMain.on('copyBase64Image', (event, args) => {
|
||||
event.returnValue = "ok"
|
||||
})
|
||||
|
||||
/**
|
||||
* 复制图片根据坐标
|
||||
* @param args
|
||||
*/
|
||||
ipcMain.on('copyImageAt', (event, args) => {
|
||||
try {
|
||||
event.sender.copyImageAt(args.x, args.y);
|
||||
} catch (e) {
|
||||
// log.error(e)
|
||||
}
|
||||
event.returnValue = "ok"
|
||||
})
|
||||
|
||||
/**
|
||||
* 保存图片
|
||||
* @param args
|
||||
*/
|
||||
ipcMain.on('saveImageAt', async (event, args) => {
|
||||
await electronMenu.saveImageAs(args.url, args.params)
|
||||
event.returnValue = "ok"
|
||||
})
|
||||
|
||||
/**
|
||||
* 绑定截图快捷键
|
||||
* @param args
|
||||
|
||||
@ -138,6 +138,7 @@
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -610,6 +610,7 @@ export default {
|
||||
|
||||
navStyle: {},
|
||||
|
||||
operateClient: {x: 0, y: 0},
|
||||
operateVisible: false,
|
||||
operatePreventScroll: 0,
|
||||
operateCopys: [],
|
||||
@ -2335,6 +2336,7 @@ export default {
|
||||
top: `${projectRect.top + this.windowScrollY}px`,
|
||||
height: projectRect.height + 'px',
|
||||
}
|
||||
this.operateClient = {x: event.clientX, y: event.clientY};
|
||||
this.operateVisible = true;
|
||||
})
|
||||
},
|
||||
@ -2440,9 +2442,7 @@ export default {
|
||||
switch (type) {
|
||||
case 'image':
|
||||
if (this.$Electron) {
|
||||
this.getBase64Image(value).then(base64 => {
|
||||
this.$Electron.sendMessage('copyBase64Image', {base64});
|
||||
})
|
||||
this.$Electron.sendMessage('copyImageAt', this.operateClient);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user