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 zlib = require('zlib');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const config = require('./package.json');
|
const config = require('./package.json');
|
||||||
|
const electronMenu = require("./electron-menu");
|
||||||
const spawn = require("child_process").spawn;
|
const spawn = require("child_process").spawn;
|
||||||
|
|
||||||
const isMac = process.platform === 'darwin'
|
const isMac = process.platform === 'darwin'
|
||||||
@ -58,6 +59,7 @@ function createMainWindow() {
|
|||||||
openExternal(url)
|
openExternal(url)
|
||||||
return {action: 'deny'}
|
return {action: 'deny'}
|
||||||
})
|
})
|
||||||
|
electronMenu.webContentsMenu(mainWindow.webContents)
|
||||||
|
|
||||||
if (devloadUrl) {
|
if (devloadUrl) {
|
||||||
mainWindow.loadURL(devloadUrl).then(_ => {
|
mainWindow.loadURL(devloadUrl).then(_ => {
|
||||||
@ -158,6 +160,7 @@ function createSubWindow(args) {
|
|||||||
openExternal(url)
|
openExternal(url)
|
||||||
return {action: 'deny'}
|
return {action: 'deny'}
|
||||||
})
|
})
|
||||||
|
electronMenu.webContentsMenu(browser.webContents)
|
||||||
|
|
||||||
if (devloadUrl) {
|
if (devloadUrl) {
|
||||||
browser.loadURL(devloadUrl + '#' + (args.hash || args.path)).then(_ => {
|
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}
|
* @param args {path}
|
||||||
@ -475,6 +489,28 @@ ipcMain.on('copyBase64Image', (event, args) => {
|
|||||||
event.returnValue = "ok"
|
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
|
* @param args
|
||||||
|
|||||||
@ -138,6 +138,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -610,6 +610,7 @@ export default {
|
|||||||
|
|
||||||
navStyle: {},
|
navStyle: {},
|
||||||
|
|
||||||
|
operateClient: {x: 0, y: 0},
|
||||||
operateVisible: false,
|
operateVisible: false,
|
||||||
operatePreventScroll: 0,
|
operatePreventScroll: 0,
|
||||||
operateCopys: [],
|
operateCopys: [],
|
||||||
@ -2335,6 +2336,7 @@ export default {
|
|||||||
top: `${projectRect.top + this.windowScrollY}px`,
|
top: `${projectRect.top + this.windowScrollY}px`,
|
||||||
height: projectRect.height + 'px',
|
height: projectRect.height + 'px',
|
||||||
}
|
}
|
||||||
|
this.operateClient = {x: event.clientX, y: event.clientY};
|
||||||
this.operateVisible = true;
|
this.operateVisible = true;
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -2440,9 +2442,7 @@ export default {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 'image':
|
case 'image':
|
||||||
if (this.$Electron) {
|
if (this.$Electron) {
|
||||||
this.getBase64Image(value).then(base64 => {
|
this.$Electron.sendMessage('copyImageAt', this.operateClient);
|
||||||
this.$Electron.sendMessage('copyBase64Image', {base64});
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user