diff --git a/package.json b/package.json index f942d4494..0aa6ba8c2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "email-securely-app", "description": "Unofficial desktop app for E2E encrypted email providers", - "version": "1.5.3", + "version": "1.5.4", "author": "Vladimir Yakovlev ", "license": "MIT", "homepage": "https://github.com/vladimiry/email-securely-app", diff --git a/src/electron-main/index.spec.ts b/src/electron-main/index.spec.ts index 6ff143ed7..94a3e923d 100644 --- a/src/electron-main/index.spec.ts +++ b/src/electron-main/index.spec.ts @@ -39,7 +39,7 @@ test.serial("workflow", async (t) => { t.true(m["./api"].initApi.calledWithExactly(t.context.ctx), `"initApi" called`); t.true(m["./api"].initApi.calledAfter(m["./session"].clearDefaultSessionCaches), `"initApi" called after "clearDefaultSessionCaches"`); - t.true(m["./web-content-context-menu"].initWebContentContextMenu.calledWithExactly(t.context.ctx), `"initWebContentContextMenu" called`); + t.true(m["./web-content-context-menu"].initWebContentContextMenu.calledWithExactly(), `"initWebContentContextMenu" called`); t.true(m["./web-content-context-menu"].initWebContentContextMenu.calledBefore(m["./window"].initBrowserWindow), `"initWebContentContextMenu" called before "initBrowserWindow"`); t.true(m["./web-content-context-menu"].initWebContentContextMenu.calledBefore(m["./tray"].initTray), `"initWebContentContextMenu" called before "initTray"`); diff --git a/src/electron-main/index.ts b/src/electron-main/index.ts index f6a9b10e3..4fc08cf15 100644 --- a/src/electron-main/index.ts +++ b/src/electron-main/index.ts @@ -43,7 +43,7 @@ app.on("ready", async () => { const endpoints = await initApi(ctx); const {checkForUpdatesAndNotify} = await endpoints.readConfig().toPromise(); - initWebContentContextMenu(ctx); + initWebContentContextMenu(); const uiContext = ctx.uiContext = { browserWindow: await initBrowserWindow(ctx, endpoints), diff --git a/src/electron-main/web-content-context-menu.ts b/src/electron-main/web-content-context-menu.ts index 8b48b2cbe..aa0b4ca22 100644 --- a/src/electron-main/web-content-context-menu.ts +++ b/src/electron-main/web-content-context-menu.ts @@ -1,66 +1,54 @@ -import {ContextMenuParams, Event, Menu, PopupOptions, WebContents, app, clipboard} from "electron"; +import {ContextMenuParams, Event, Menu, MenuItemConstructorOptions, WebContents, app, clipboard} from "electron"; import {platform} from "os"; -import {Context} from "./model"; - -const selectionMenu = Menu.buildFromTemplate([ - {role: "copy"}, - {type: "separator"}, - {role: "selectall"}, -]); -const inputMenu = Menu.buildFromTemplate([ - {role: "undo"}, - {role: "redo"}, - {type: "separator"}, - {role: "cut"}, - {role: "copy"}, - {role: "paste"}, - {type: "separator"}, - {role: "selectall"}, -]); - -export function initWebContentContextMenu(ctx: Context) { - const contextMenuEventArgs = [ - "context-menu", - (e: Event, props: ContextMenuParams) => { - const {selectionText, isEditable, linkURL, linkText} = props; - const popupOptions: PopupOptions = {window: ctx.uiContext && ctx.uiContext.browserWindow}; - - if (!popupOptions.window) { - return; - } - - if (isEditable) { - inputMenu.popup(popupOptions); - return; - } - - if (linkURL) { - const linkMenu = Menu.buildFromTemplate([{ - label: isEmailHref(linkURL) ? "Copy Email Address" : "Copy Link Address", - click() { - const url = extractEmailIfEmailHref(linkURL); - if (platform() === "darwin") { - clipboard.writeBookmark(linkText, url); - } else { - clipboard.writeText(url); - } - }, - }]); - linkMenu.popup(popupOptions); - return; - } - - if (selectionText && selectionText.trim()) { - selectionMenu.popup(popupOptions); - } - }, - ]; - const webContentsCreatedHandler = (webContents: WebContents) => { - webContents.removeListener.apply(webContents, contextMenuEventArgs); - webContents.on.apply(webContents, contextMenuEventArgs); - }; - +const emptyArray = Object.freeze([]); + +const contextMenuEventSubscriptionArgs = [ + "context-menu", + ({sender: webContents}: Event, {editFlags, linkURL, linkText}: ContextMenuParams) => { + const template: MenuItemConstructorOptions[] = []; + + if (linkURL) { + template.push({ + label: isEmailHref(linkURL) ? "Copy Email Address" : "Copy Link Address", + click() { + if (platform() === "darwin") { + clipboard.writeBookmark(linkText, extractEmailIfEmailHref(linkURL)); + } else { + clipboard.writeText(extractEmailIfEmailHref(linkURL)); + } + }, + }); + } else { + template.push(...[ + // TODO use "role" based "cut/copy/paste" actions, currently these actions don't work properly + // track the respective issue https://github.com/electron/electron/issues/15219 + ...(editFlags.canCut ? [{label: "Cut", click: () => webContents.cut()}] : emptyArray), + ...(editFlags.canCopy ? [{label: "Copy", click: () => webContents.copy()}] : emptyArray), + ...(editFlags.canPaste ? [{label: "Paste", click: () => webContents.paste()}] : emptyArray), + ]); + + // TODO "selectall" context menu action doesn't work properly (works well only on login page) + // if (editFlags.canSelectAll) { + // if (template.length) { + // template.push(separatorItem); + // } + // template.push({role: "selectall"}); + // } + } + + if (template.length) { + Menu.buildFromTemplate(template).popup({}); + } + }, +]; + +const webContentsCreatedHandler = (webContents: WebContents) => { + webContents.removeListener.apply(webContents, contextMenuEventSubscriptionArgs); + webContents.on.apply(webContents, contextMenuEventSubscriptionArgs); +}; + +export function initWebContentContextMenu() { app.on("browser-window-created", (event, {webContents}) => webContentsCreatedHandler(webContents)); app.on("web-contents-created", (webContentsCreatedEvent, webContents) => webContentsCreatedHandler(webContents)); }