From ec1023d7efe83cb2e832e5dbba18384c046f6ccf Mon Sep 17 00:00:00 2001 From: David Kramer Date: Sun, 22 Apr 2018 16:48:56 -0700 Subject: [PATCH] Fix #95, #384 - Use electron-context-menu, supporting cut/copy/paste (PR #588) The electron-context-menu package uses the context-menu event emitted by WebContents (API added in Electron 1.0.2) to add a general context menu supporting generic actions (e.g. cut/copy/paste) that can be customized. This change replaces the existing context menu, which relies on adding an event listener in preload.js, with one built using the new package. --- app/package.json | 1 + app/src/components/contextMenu/contextMenu.js | 65 +++++++------------ app/src/components/mainWindow/mainWindow.js | 2 +- app/src/static/preload.js | 26 -------- 4 files changed, 24 insertions(+), 70 deletions(-) diff --git a/app/package.json b/app/package.json index cb3becb..47af71d 100644 --- a/app/package.json +++ b/app/package.json @@ -4,6 +4,7 @@ "description": "Placeholder for the nativefier cli to override with a target url", "main": "lib/main.js", "dependencies": { + "electron-context-menu": "^0.9.1", "electron-dl": "^1.10.0", "electron-window-state": "^4.1.1", "loglevel": "^1.5.1", diff --git a/app/src/components/contextMenu/contextMenu.js b/app/src/components/contextMenu/contextMenu.js index 2538e63..0bf72ba 100644 --- a/app/src/components/contextMenu/contextMenu.js +++ b/app/src/components/contextMenu/contextMenu.js @@ -1,47 +1,26 @@ -// Because we are changing the properties of `mainWindow` in initContextMenu() -/* eslint-disable no-param-reassign */ -import { Menu, ipcMain, shell, clipboard, BrowserWindow } from 'electron'; +import { shell, BrowserWindow } from 'electron'; +import contextMenu from 'electron-context-menu'; -function initContextMenu(mainWindow) { - ipcMain.on('contextMenuOpened', (event, targetHref) => { - const contextMenuTemplate = [ - { - label: 'Open with default browser', - click: () => { - if (targetHref) { - shell.openExternal(targetHref); - } - }, - }, - { - label: 'Open in new window', - click: () => { - if (targetHref) { - new BrowserWindow().loadURL(targetHref); - return; - } - - mainWindow.useDefaultWindowBehaviour = true; - mainWindow.webContents.send('contextMenuClosed'); - }, - }, - { - label: 'Copy link location', - click: () => { - if (targetHref) { - clipboard.writeText(targetHref); - return; - } - - mainWindow.useDefaultWindowBehaviour = true; - mainWindow.webContents.send('contextMenuClosed'); - }, - }, - ]; - - const contextMenu = Menu.buildFromTemplate(contextMenuTemplate); - contextMenu.popup(mainWindow); - mainWindow.contextMenuOpen = true; +function initContextMenu() { + contextMenu({ + prepend: (params) => { + const items = []; + if (params.linkURL) { + items.push({ + label: 'Open Link in Default Browser', + click: () => { + shell.openExternal(params.linkURL); + }, + }); + items.push({ + label: 'Open Link in New Window', + click: () => { + new BrowserWindow().loadURL(params.linkURL); + }, + }); + } + return items; + }, }); } diff --git a/app/src/components/mainWindow/mainWindow.js b/app/src/components/mainWindow/mainWindow.js index ad30bc0..490504b 100644 --- a/app/src/components/mainWindow/mainWindow.js +++ b/app/src/components/mainWindow/mainWindow.js @@ -162,7 +162,7 @@ function createMainWindow(inpOptions, onAppQuit, setDockBadge) { createMenu(menuOptions); if (!options.disableContextMenu) { - initContextMenu(mainWindow); + initContextMenu(); } if (options.userAgent) { diff --git a/app/src/static/preload.js b/app/src/static/preload.js index 3ecea31..0315c7c 100644 --- a/app/src/static/preload.js +++ b/app/src/static/preload.js @@ -25,11 +25,6 @@ function setNotificationCallback(callback) { window.Notification = newNotify; } -function clickSelector(element) { - const mouseEvent = new MouseEvent('click'); - element.dispatchEvent(mouseEvent); -} - function injectScripts() { const needToInject = fs.existsSync(INJECT_JS_PATH); if (!needToInject) { @@ -45,27 +40,6 @@ setNotificationCallback((title, opt) => { }); document.addEventListener('DOMContentLoaded', () => { - window.addEventListener('contextmenu', (event) => { - event.preventDefault(); - let targetElement = event.srcElement; - - // the clicked element is the deepest in the DOM, and may not be the bearing the href - // for example, Google - while (!targetElement.href && targetElement.parentElement) { - targetElement = targetElement.parentElement; - } - const targetHref = targetElement.href; - - if (!targetHref) { - ipcRenderer.once('contextMenuClosed', () => { - clickSelector(event.target); - ipcRenderer.send('cancelNewWindowOverride'); - }); - } - - ipcRenderer.send('contextMenuOpened', targetHref); - }, false); - injectScripts(); });