diff --git a/src/main/createWindow.js b/src/main/createWindow.js index 738ab792a..764003c65 100644 --- a/src/main/createWindow.js +++ b/src/main/createWindow.js @@ -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) { diff --git a/src/main/menu/setupContextMenu.js b/src/main/menu/setupContextMenu.js deleted file mode 100644 index 658ac731a..000000000 --- a/src/main/menu/setupContextMenu.js +++ /dev/null @@ -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(); - }); -}; diff --git a/src/renderer/component/fileCard/view.jsx b/src/renderer/component/fileCard/view.jsx index eae87deaa..3655c7c61 100644 --- a/src/renderer/component/fileCard/view.jsx +++ b/src/renderer/component/fileCard/view.jsx @@ -1,6 +1,6 @@ // @flow import * as React from 'react'; -import { normalizeURI } from 'lbry-redux'; +import { normalizeURI, convertToShareLink } from 'lbry-redux'; import Button from 'component/button'; import CardMedia from 'component/cardMedia'; import TruncatedText from 'component/common/truncated-text'; @@ -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 { 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(convertToShareLink(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 { 'card--link': !pending, 'card--pending': pending, })} + onContextMenu={handleContextMenu} >
{showPrice && }
diff --git a/src/renderer/index.js b/src/renderer/index.js index c82db3287..c19790f06 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -16,6 +16,7 @@ import 'scss/all.scss'; import store from 'store'; import app from './app'; import analytics from './analytics'; +import { initContextMenu } from './util/contextMenu'; const { autoUpdater } = remote.require('electron-updater'); @@ -95,6 +96,8 @@ document.addEventListener('click', event => { } }); +document.addEventListener('contextmenu', initContextMenu); + const init = () => { autoUpdater.on('update-downloaded', () => { app.store.dispatch(doAutoUpdate()); @@ -129,7 +132,7 @@ const init = () => { ReactDOM.render(
- + openContextMenu(e)} />
, diff --git a/src/renderer/util/contextMenu.js b/src/renderer/util/contextMenu.js new file mode 100644 index 000000000..79f47da5b --- /dev/null +++ b/src/renderer/util/contextMenu.js @@ -0,0 +1,68 @@ +import { clipboard, remote } from 'electron'; +import isDev from 'electron-is-dev'; + +function injectDevelopmentTemplate(event, templates) { + if (!isDev) return templates; + const { screenX, screenY } = event; + const separator = { type: 'separator' }; + const developmentTemplateAddition = [ + { + label: 'Inspect element', + accelerator: 'CmdOrCtrl+Shift+I', + click: () => { + remote.getCurrentWindow().inspectElement(screenX, screenY); + }, + }, + ]; + if (templates.length > 0) { + templates.push(separator); + } + templates.push(...developmentTemplateAddition); + return templates; +} + +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: 'Paste', + accelerator: 'CmdOrCtrl+V', + role: 'paste', + enabled: clipboard.readText().length > 0, + }, + { + label: 'Select All', + accelerator: 'CmdOrCtrl+A', + role: 'selectall', + enabled: !!value, + }, + ]; + templates.push(...inputTemplates); + } + + 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(); + } +}