Add right click context menu on all text inputs #1486

Merged
dan1d merged 3 commits from right-click-menu-context into master 2018-05-29 21:57:38 +02:00
5 changed files with 63 additions and 84 deletions
Showing only changes of commit 86876d6a19 - Show all commits

View file

@ -3,7 +3,6 @@ import isDev from 'electron-is-dev';
import windowStateKeeper from 'electron-window-state';
import setupBarMenu from './menu/setupBarMenu';
import setupContextMenu from './menu/setupContextMenu';
export default appState => {
// Get primary display dimensions from Electron.
@ -73,7 +72,6 @@ export default appState => {
}
setupBarMenu();
setupContextMenu(window);
window.on('close', event => {
if (!appState.isQuitting && !appState.autoUpdateAccepted) {

View file

@ -1,27 +0,0 @@
// @flow
import { Menu, BrowserWindow } from 'electron';
import isDev from 'electron-is-dev';
export default (rendererWindow: BrowserWindow) => {
rendererWindow.webContents.on('context-menu', (e, params) => {
const { x, y } = params;
const template = [{ role: 'cut' }, { role: 'copy' }, { role: 'paste' }];
const developmentTemplateAddition = [
{ type: 'separator' },
{
label: 'Inspect element',
click: () => {
rendererWindow.inspectElement(x, y);
},
},
];
if (isDev) {
template.push(...developmentTemplateAddition);
}
Menu.buildFromTemplate(template).popup();
});
};

View file

@ -9,6 +9,7 @@ import FilePrice from 'component/filePrice';
import UriIndicator from 'component/uriIndicator';
import * as icons from 'constants/icons';
import classnames from 'classnames';
import { openCopyLinkMenu } from '../../util/contextMenu';
// TODO: iron these out
type Props = {
@ -60,6 +61,9 @@ class FileCard extends React.PureComponent<Props> {
const thumbnail = metadata && metadata.thumbnail ? metadata.thumbnail : null;
const shouldObscureNsfw = obscureNsfw && metadata && metadata.nsfw;
const isRewardContent = claim && rewardedContentClaimIds.includes(claim.claim_id);
const handleContextMenu = event => {
openCopyLinkMenu(uri, event);
};
// We should be able to tab through cards
/* eslint-disable jsx-a11y/click-events-have-key-events */
@ -72,6 +76,7 @@ class FileCard extends React.PureComponent<Props> {
'card--link': !pending,
'card--pending': pending,
})}
onContextMenu={handleContextMenu}
>
<CardMedia nsfw={shouldObscureNsfw} thumbnail={thumbnail} />
<div className="card-media__internal-links">{showPrice && <FilePrice uri={uri} />}</div>

View file

@ -16,7 +16,7 @@ import 'scss/all.scss';
import store from 'store';
import app from './app';
import analytics from './analytics';
import getMenu from './util/contextMenu';
import { initContextMenu } from './util/contextMenu';
const { autoUpdater } = remote.require('electron-updater');
@ -96,7 +96,7 @@ document.addEventListener('click', event => {
}
});
document.addEventListener('contextmenu', getMenu);
document.addEventListener('contextmenu', initContextMenu);
const init = () => {
autoUpdater.on('update-downloaded', () => {
@ -132,7 +132,7 @@ const init = () => {
ReactDOM.render(
<Provider store={store}>
<div>
<App />
<App onContextMenu={e => openContextMenu(e)} />
<SnackBar />
</div>
</Provider>,

View file

@ -1,65 +1,68 @@
import { clipboard, remote } from 'electron';
import isDev from 'electron-is-dev';
function textInputTemplate(target) {
const somethingSelected = target.selectionStart < target.selectionEnd;
const hasValue = target.value.length > 0;
// Native Electron selectAll role does not work
function selectAll() {
target.selectionStart = 0;
target.selectionEnd = target.value.length + 1;
}
const template = [
{ label: 'Cut', accelerator: 'CmdOrCtrl+X', role: 'cut', enabled: somethingSelected },
{ label: 'Copy', accelerator: 'CmdOrCtrl+C', role: 'copy', enabled: somethingSelected },
function injectDevelopmentTemplate(event, templates) {
if (!isDev) return templates;
const { screenX, screenY } = event;
const separator = { type: 'separator' };
const developmentTemplateAddition = [
{
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
role: 'paste',
enabled: clipboard.readText().length > 0,
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectAll',
enabled: hasValue,
click: selectAll,
label: 'Inspect element',
accelerator: 'CmdOrCtrl+Shift+I',
click: () => {
remote.getCurrentWindow().inspectElement(screenX, screenY);
},
},
];
return template;
}
function getTemplate(target) {
const { type } = target;
if (target.matches('input') && (type === 'text' || type === 'number')) {
return textInputTemplate(target);
if (templates.length > 0) {
templates.push(separator);
}
return [];
templates.push(...developmentTemplateAddition);
return templates;
}
export default event => {
event.preventDefault();
const { target } = event;
const template = getTemplate(target);
if (isDev) {
const { screenX, screenY } = event;
const separator = { type: 'separator' };
const developmentTemplateAddition = [
export function openContextMenu(event, templates = [], addDefaultTemplates = true) {
if (addDefaultTemplates) {
const { value } = event.target;
const inputTemplates = [
{ label: 'Cut', accelerator: 'CmdOrCtrl+X', role: 'cut' },
{ label: 'Copy', accelerator: 'CmdOrCtrl+C', role: 'copy' },
{
label: 'Inspect element',
accelerator: 'CmdOrCtrl+Shift+I',
click: () => {
remote.getCurrentWindow().inspectElement(screenX, screenY);
},
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
role: 'paste',
enabled: clipboard.readText().length > 0,
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectall',
enabled: !!value,
},
];
if (template.length > 0) {
template.push(separator);
}
template.push(...developmentTemplateAddition);
templates.push(...inputTemplates);
}
remote.Menu.buildFromTemplate(template).popup();
};
injectDevelopmentTemplate(event, templates);
remote.Menu.buildFromTemplate(templates).popup();
}
export function openCopyLinkMenu(text, event) {
const templates = [
{
label: 'Copy link',
click: () => {
clipboard.writeText(text);
},
},
];
openContextMenu(event, templates, false);
}
export function initContextMenu(event) {
const { type } = event.target;
if (event.target.matches('input') && (type === 'text' || type === 'number')) {
openContextMenu(event);
} else {
event.preventDefault();
}
}