107 lines
2.7 KiB
TypeScript
107 lines
2.7 KiB
TypeScript
import {
|
|
MenuItemConstructorOptions,
|
|
shell,
|
|
BrowserWindow,
|
|
Menu,
|
|
clipboard,
|
|
PopupOptions
|
|
} from 'electron';
|
|
import { URL } from 'url';
|
|
|
|
function popupContextMenu(
|
|
window: BrowserWindow,
|
|
isDevelopment: boolean,
|
|
props: Electron.ContextMenuParams
|
|
) {
|
|
const editFlags = props.editFlags;
|
|
const hasText = props.selectionText.trim().length > 0;
|
|
const roleEnabled = (flag: keyof Electron.EditFlags) => editFlags[flag] && hasText;
|
|
|
|
// Not using the `enable` nor `visible` properties of MenuConstructorOptions
|
|
// As they do not appear to work w/ Electron 1.8.4 on Mac OS X
|
|
let ctxMenuTmpl: MenuItemConstructorOptions[] = [];
|
|
|
|
if (roleEnabled('canCut') && props.isEditable) {
|
|
ctxMenuTmpl.push({
|
|
accelerator: 'CmdOrCtrl+X',
|
|
role: 'cut'
|
|
});
|
|
}
|
|
|
|
if (roleEnabled('canCopy') && hasText) {
|
|
ctxMenuTmpl.push({
|
|
accelerator: 'CmdOrCtrl+C',
|
|
role: 'copy'
|
|
});
|
|
}
|
|
|
|
// For some reason, editFlags.canCopy is often false but the keyboard shortcut to paste still works
|
|
// let's only check if the currently focused element is editable
|
|
if (props.isEditable) {
|
|
ctxMenuTmpl.push({
|
|
accelerator: 'CmdOrCtrl+V',
|
|
role: 'paste'
|
|
});
|
|
}
|
|
|
|
if (props.linkURL && props.mediaType === 'none') {
|
|
ctxMenuTmpl = ctxMenuTmpl.concat([
|
|
{ type: 'separator' },
|
|
{
|
|
id: 'copyLink',
|
|
label: 'Copy Link',
|
|
click() {
|
|
if (process.platform === 'darwin') {
|
|
clipboard.writeBookmark(props.linkText, props.linkURL);
|
|
} else {
|
|
clipboard.writeText(props.linkURL);
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: 'openLink',
|
|
label: 'Open Link in Browser',
|
|
click() {
|
|
// Only allow HTTPS urls to actually be opened
|
|
const url = new URL(props.linkURL);
|
|
if (url.protocol === 'https:') {
|
|
shell.openExternal(props.linkURL);
|
|
} else {
|
|
console.warn(
|
|
`Blocked request to open new window '${props.linkURL}', only HTTPS links are allowed`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
]);
|
|
}
|
|
|
|
// add the Inspect Element button
|
|
if (isDevelopment) {
|
|
ctxMenuTmpl = ctxMenuTmpl.concat([
|
|
{ type: 'separator' },
|
|
{
|
|
label: 'Inspect Element',
|
|
click: () => {
|
|
window.webContents.inspectElement(props.x, props.y);
|
|
if (window.webContents.isDevToolsOpened()) {
|
|
window.webContents.devToolsWebContents.focus();
|
|
}
|
|
}
|
|
}
|
|
]);
|
|
}
|
|
|
|
const ctxMenu = Menu.buildFromTemplate(ctxMenuTmpl);
|
|
|
|
const popupOpts: PopupOptions = {
|
|
window,
|
|
x: props.x,
|
|
y: props.y
|
|
};
|
|
|
|
ctxMenu.popup(popupOpts);
|
|
}
|
|
|
|
export default popupContextMenu;
|