split webContents context handling into own file, as main was growing

add handlers for editable fields, with Cut Copy Paste Undo Redo etc
add Copy Image feature to all images, working on not only the download
buttons now

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
This commit is contained in:
Michael Telatynski 2017-05-25 12:42:53 +01:00
parent 7d59742a22
commit c4c78c9b3e
2 changed files with 128 additions and 58 deletions

View file

@ -24,11 +24,11 @@ const check_squirrel_hooks = require('./squirrelhooks');
if (check_squirrel_hooks()) return; if (check_squirrel_hooks()) return;
const electron = require('electron'); const electron = require('electron');
const url = require('url');
const tray = require('./tray'); const tray = require('./tray');
const VectorMenu = require('./vectormenu'); const VectorMenu = require('./vectormenu');
const webContentsHandler = require('./webcontents-handler');
const windowStateKeeper = require('electron-window-state'); const windowStateKeeper = require('electron-window-state');
@ -42,60 +42,12 @@ try {
// Continue with the defaults (ie. an empty config) // Continue with the defaults (ie. an empty config)
} }
const PERMITTED_URL_SCHEMES = [
'http:',
'https:',
'mailto:',
];
const UPDATE_POLL_INTERVAL_MS = 60 * 60 * 1000; const UPDATE_POLL_INTERVAL_MS = 60 * 60 * 1000;
const INITIAL_UPDATE_DELAY_MS = 30 * 1000; const INITIAL_UPDATE_DELAY_MS = 30 * 1000;
let mainWindow = null; let mainWindow = null;
let appQuitting = false; let appQuitting = false;
function safeOpenURL(target) {
// openExternal passes the target to open/start/xdg-open,
// so put fairly stringent limits on what can be opened
// (for instance, open /bin/sh does indeed open a terminal
// with a shell, albeit with no arguments)
const parsed_url = url.parse(target);
if (PERMITTED_URL_SCHEMES.indexOf(parsed_url.protocol) > -1) {
// explicitly use the URL re-assembled by the url library,
// so we know the url parser has understood all the parts
// of the input string
const new_target = url.format(parsed_url);
electron.shell.openExternal(new_target);
}
}
function onWindowOrNavigate(ev, target) {
// always prevent the default: if something goes wrong,
// we don't want to end up opening it in the electron
// app, as we could end up opening any sort of random
// url in a window that has node scripting access.
ev.preventDefault();
safeOpenURL(target);
}
function onLinkContextMenu(ev, params) {
const popup_menu = new electron.Menu();
popup_menu.append(new electron.MenuItem({
label: params.linkURL,
click() {
safeOpenURL(params.linkURL);
},
}));
popup_menu.append(new electron.MenuItem({
label: 'Copy Link Address',
click() {
electron.clipboard.writeText(params.linkURL);
},
}));
popup_menu.popup();
ev.preventDefault();
}
function installUpdate() { function installUpdate() {
// for some reason, quitAndInstall does not fire the // for some reason, quitAndInstall does not fire the
// before-quit event, so we need to set the flag here. // before-quit event, so we need to set the flag here.
@ -259,15 +211,7 @@ electron.app.on('ready', () => {
} }
}); });
mainWindow.webContents.on('new-window', onWindowOrNavigate); webContentsHandler(mainWindow.webContents);
mainWindow.webContents.on('will-navigate', onWindowOrNavigate);
mainWindow.webContents.on('context-menu', function(ev, params) {
if (params.linkURL) {
onLinkContextMenu(ev, params);
}
});
mainWindowState.manage(mainWindow); mainWindowState.manage(mainWindow);
}); });

View file

@ -0,0 +1,126 @@
const {clipboard, nativeImage, Menu, MenuItem, shell} = require('electron');
const url = require('url');
let webContents;
const PERMITTED_URL_SCHEMES = [
'http:',
'https:',
'mailto:',
];
function safeOpenURL(target) {
// openExternal passes the target to open/start/xdg-open,
// so put fairly stringent limits on what can be opened
// (for instance, open /bin/sh does indeed open a terminal
// with a shell, albeit with no arguments)
const parsedUrl = url.parse(target);
if (PERMITTED_URL_SCHEMES.indexOf(parsedUrl.protocol) > -1) {
// explicitly use the URL re-assembled by the url library,
// so we know the url parser has understood all the parts
// of the input string
const newTarget = url.format(parsedUrl);
shell.openExternal(newTarget);
}
}
function onWindowOrNavigate(ev, target) {
// always prevent the default: if something goes wrong,
// we don't want to end up opening it in the electron
// app, as we could end up opening any sort of random
// url in a window that has node scripting access.
ev.preventDefault();
safeOpenURL(target);
}
function onLinkContextMenu(ev, params) {
const url = params.linkURL || params.srcURL;
const popupMenu = new Menu();
popupMenu.append(new MenuItem({
label: url,
click() {
safeOpenURL(url);
},
}));
if (params.mediaType && params.mediaType === 'image' && !url.startsWith('file://')) {
popupMenu.append(new MenuItem({
label: 'Copy Image',
click() {
if (url.startsWith('data:')) {
clipboard.writeImage(nativeImage.createFromDataURL(url));
} else {
ev.sender.copyImageAt(params.x, params.y);
}
},
}));
}
popupMenu.append(new MenuItem({
label: 'Copy Link Address',
click() {
clipboard.writeText(url);
},
}));
popupMenu.popup();
ev.preventDefault();
}
function _CutCopyPasteSelectContextMenus(params) {
return [{
role: 'cut',
enabled: params.editFlags.canCut,
}, {
role: 'copy',
enabled: params.editFlags.canCopy,
}, {
role: 'paste',
enabled: params.editFlags.canPaste,
}, {
role: 'pasteandmatchstyle',
enabled: params.editFlags.canPaste,
}, {
role: 'selectall',
enabled: params.editFlags.canSelectAll,
}];
}
function onSelectedContextMenu(ev, params) {
const items = _CutCopyPasteSelectContextMenus(params);
const popupMenu = Menu.buildFromTemplate(items);
popupMenu.popup();
ev.preventDefault();
}
function onEditableContextMenu(ev, params) {
const items = [
{ role: 'undo' },
{ role: 'redo', enabled: params.editFlags.canRedo },
{ type: 'separator' },
].concat(_CutCopyPasteSelectContextMenus(params));
const popupMenu = Menu.buildFromTemplate(items);
popupMenu.popup();
ev.preventDefault();
}
module.exports = (_webContents) => {
webContents = _webContents;
webContents.on('new-window', onWindowOrNavigate);
webContents.on('will-navigate', onWindowOrNavigate);
webContents.on('context-menu', function(ev, params) {
if (params.linkURL || params.srcURL) {
onLinkContextMenu(ev, params);
} else if (params.selectionText) {
onSelectedContextMenu(ev, params);
} else if (params.isEditable) {
onEditableContextMenu(ev, params);
}
});
};