From ad71057a088aaa11da486e32df4aef913bc5bd4d Mon Sep 17 00:00:00 2001 From: Alice Gaudon Date: Fri, 10 Jan 2020 16:36:06 +0100 Subject: [PATCH] Add fully featured context menu in service webviews --- resources/js/index.js | 3 +- resources/js/service-webview.js | 126 ++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 resources/js/service-webview.js diff --git a/resources/js/index.js b/resources/js/index.js index a05384e..84ec886 100644 --- a/resources/js/index.js +++ b/resources/js/index.js @@ -225,7 +225,8 @@ function loadService(serviceId, service) { service.view = document.createElement('webview'); service.view.setAttribute('src', service.url); service.view.setAttribute('partition', 'persist:service_' + service.partition); - service.view.setAttribute('autosize', "true"); + service.view.setAttribute('autosize', 'true'); + service.view.setAttribute('preload', 'js/service-webview.js'); // Append element to DOM document.querySelector('#services').appendChild(service.view); diff --git a/resources/js/service-webview.js b/resources/js/service-webview.js new file mode 100644 index 0000000..53cf596 --- /dev/null +++ b/resources/js/service-webview.js @@ -0,0 +1,126 @@ +const { + remote, + clipboard, +} = require('electron'); +const { + Menu, + MenuItem, +} = remote; + +const webContents = remote.getCurrentWebContents(); +webContents.on('context-menu', (event, props) => { + const menu = new Menu(); + const {editFlags} = props; + + // linkURL + if (props.linkURL.length > 0) { + if (menu.items.length > 0) { + menu.append(new MenuItem({type: 'separator'})); + } + + menu.append(new MenuItem({ + label: 'Copy link URL', + click: () => { + clipboard.writeText(props.linkURL); + }, + })); + menu.append(new MenuItem({ + label: 'Open URL in default browser', + click: () => { + window.open(props.linkURL, '_blank'); + }, + })); + } + + // Image + if (props.hasImageContents) { + if (menu.items.length > 0) { + menu.append(new MenuItem({type: 'separator'})); + } + + menu.append(new MenuItem({ + label: 'Copy image', + click: () => { + webContents.copyImageAt(props.x, props.y); + }, + })); + + menu.append(new MenuItem({ + label: 'Save image as', + click: () => { + webContents.downloadURL(props.srcURL); + }, + })); + } + + // Text clipboard + if (editFlags.canUndo || editFlags.canRedo || editFlags.canCut || editFlags.canCopy || editFlags.canPaste || editFlags.canDelete) { + if (menu.items.length > 0) { + menu.append(new MenuItem({type: 'separator'})); + } + if (editFlags.canUndo) { + menu.append(new MenuItem({ + label: 'Undo', + role: 'undo', + })); + } + if (editFlags.canRedo) { + menu.append(new MenuItem({ + label: 'Redo', + role: 'redo', + })); + } + + if (menu.items.length > 0) { + menu.append(new MenuItem({type: 'separator'})); + } + menu.append(new MenuItem({ + label: 'Cut', + role: 'cut', + enabled: editFlags.canCut, + })); + menu.append(new MenuItem({ + label: 'Copy', + role: 'copy', + enabled: editFlags.canCopy, + })); + menu.append(new MenuItem({ + label: 'Paste', + role: 'paste', + enabled: editFlags.canPaste, + })); + menu.append(new MenuItem({ + label: 'Delete', + role: 'delete', + enabled: editFlags.canDelete, + })); + } + + if (editFlags.canSelectAll) { + if (menu.items.length > 0) { + menu.append(new MenuItem({type: 'separator'})); + } + + menu.append(new MenuItem({ + label: 'Select all', + role: 'selectAll', + })); + } + + // Inspect element + if (menu.items.length > 0) { + menu.append(new MenuItem({type: 'separator'})); + } + + menu.append(new MenuItem({ + label: 'Inspect element', + click: () => { + webContents.inspectElement(props.x, props.y); + }, + })); + + + menu.popup({ + window: remote.getCurrentWindow(), + }); +}); \ No newline at end of file