diff --git a/CHANGELOG.md b/CHANGELOG.md index e1026b5f2..1b033f672 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - New channel create/edit page ([#4445](https://github.com/lbryio/lbry-desktop/pull/4445)) - Add dialog to copy various types of links for a claim _community pr!_ ([#4474](https://github.com/lbryio/lbry-desktop/pull/4474)) - Add password reset link to settings page for logged in users _community pr!_ ([#4473](https://github.com/lbryio/lbry-desktop/pull/4473)) +- Allow zooming on Desktop _community pr!_ ([#4513](https://github.com/lbryio/lbry-desktop/pull/4513)) ### Changed diff --git a/electron/menu/setupBarMenu.js b/electron/menu/setupBarMenu.js index 794430a0c..26f9bd602 100644 --- a/electron/menu/setupBarMenu.js +++ b/electron/menu/setupBarMenu.js @@ -1,4 +1,5 @@ import { app, Menu, shell } from 'electron'; +import { changeZoomFactor, ZOOM } from 'util/zoomWindow'; export default () => { const template = [ @@ -22,6 +23,38 @@ export default () => { label: 'View', submenu: [ { role: 'reload' }, + { + label: 'Zoom', + submenu: [ + { + label: 'Zoom In', + accelerator: 'CmdOrCtrl+=', + click: (menuItem, browserWindow) => { + if (browserWindow) { + browserWindow.webContents.send('zoom-window', ZOOM.INCREMENT); + } + }, + }, + { + label: 'Zoom Out', + accelerator: 'CmdOrCtrl+-', + click: (menuItem, browserWindow) => { + if (browserWindow) { + browserWindow.webContents.send('zoom-window', ZOOM.DECREMENT); + } + }, + }, + { + label: 'Reset Zoom', + accelerator: 'CmdOrCtrl+0', + click: (menuItem, browserWindow) => { + if (browserWindow) { + browserWindow.webContents.send('zoom-window', ZOOM.RESET); + } + }, + }, + ], + }, { label: 'Developer', submenu: [{ role: 'forcereload' }, { role: 'toggledevtools' }], diff --git a/ui/component/app/view.jsx b/ui/component/app/view.jsx index f61bded1e..1241f334c 100644 --- a/ui/component/app/view.jsx +++ b/ui/component/app/view.jsx @@ -17,6 +17,9 @@ import Nag from 'component/common/nag'; import REWARDS from 'rewards'; import usePersistedState from 'effects/use-persisted-state'; import FileDrop from 'component/fileDrop'; +// @if TARGET='app' +import { changeZoomFactor, ZOOM } from 'util/zoomWindow'; +// @endif // @if TARGET='web' import OpenInAppLink from 'web/component/openInAppLink'; import YoutubeWelcome from 'web/component/youtubeReferralWelcome'; @@ -172,6 +175,52 @@ function App(props: Props) { return () => window.removeEventListener('keydown', handleKeyPress); }, []); + // Enable ctrl +/- zooming on Desktop. + // @if TARGET='app' + useEffect(() => { + const handleKeyPress = e => { + if (e.ctrlKey && !e.shiftKey) { + switch (e.code) { + case 'NumpadAdd': + case 'Equal': + e.preventDefault(); + changeZoomFactor(ZOOM.INCREMENT); + break; + case 'NumpadSubtract': + case 'Minus': + e.preventDefault(); + changeZoomFactor(ZOOM.DECREMENT); + break; + case 'Numpad0': + case 'Digit0': + e.preventDefault(); + changeZoomFactor(ZOOM.RESET); + break; + default: + // Do nothing + break; + } + } + }; + window.addEventListener('keydown', handleKeyPress); + return () => window.removeEventListener('keydown', handleKeyPress); + }, []); + + useEffect(() => { + const handleWheel = e => { + if (e.ctrlKey && !e.shiftKey) { + if (e.deltaY < 0) { + changeZoomFactor(ZOOM.INCREMENT); + } else { + changeZoomFactor(ZOOM.DECREMENT); + } + } + }; + window.addEventListener('wheel', handleWheel); + return () => window.removeEventListener('wheel', handleWheel); + }, []); + // @endif + useEffect(() => { if (referredRewardAvailable && sanitizedReferrerParam && isRewardApproved) { setReferrer(sanitizedReferrerParam, true); diff --git a/ui/index.jsx b/ui/index.jsx index 68b566aab..b4bb646af 100644 --- a/ui/index.jsx +++ b/ui/index.jsx @@ -6,6 +6,7 @@ import SnackBar from 'component/snackBar'; // @if TARGET='app' import SplashScreen from 'component/splash'; import * as ACTIONS from 'constants/action_types'; +import { changeZoomFactor } from 'util/zoomWindow'; // @endif import { ipcRenderer, remote, shell } from 'electron'; import moment from 'moment'; @@ -193,6 +194,10 @@ ipcRenderer.on('open-menu', (event, uri) => { } }); +ipcRenderer.on('zoom-window', (event, action) => { + changeZoomFactor(action); +}); + const { dock } = remote.app; ipcRenderer.on('window-is-focused', () => { diff --git a/ui/util/zoomWindow.js b/ui/util/zoomWindow.js new file mode 100644 index 000000000..84f843e33 --- /dev/null +++ b/ui/util/zoomWindow.js @@ -0,0 +1,42 @@ +import { webFrame } from 'electron'; +const isDev = process.env.NODE_ENV !== 'production'; + +export const ZOOM = { + INCREMENT: 'INCREMENT', + DECREMENT: 'DECREMENT', + RESET: 'RESET', +}; + +function getNextZoomFactor(curFactor, isIncreasing) { + const zoomTable = [0.25, 0.33, 0.5, 0.67, 0.75, 0.8, 0.9, 1.0, 1.1, 1.25, 1.5, 1.75, 2.0, 2.5, 3.0]; + + curFactor = curFactor.toPrecision(3); + let i = zoomTable.length; + while (curFactor < zoomTable[--i]) {} + + if (isIncreasing) { + return zoomTable[Math.min(zoomTable.length - 1, i + 1)]; + } else { + return zoomTable[Math.max(0, i - 1)]; + } +} + +export function changeZoomFactor(action) { + const ZOOM_DFLT_FACTOR = 1.0; + const curFactor = webFrame.getZoomFactor(); + + switch (action) { + case ZOOM.INCREMENT: + webFrame.setZoomFactor(getNextZoomFactor(curFactor, true)); + break; + case ZOOM.DECREMENT: + webFrame.setZoomFactor(getNextZoomFactor(curFactor, false)); + break; + case ZOOM.RESET: + webFrame.setZoomFactor(ZOOM_DFLT_FACTOR); + break; + default: + if (isDev) throw new Error('changeZoomFactor: unexpected action'); + break; + } +}