Allow zooming on Desktop
## Issue Closes 4501 `Font size` ## New behavior The Desktop app can now zoom the same way as browsers: - Zoom In: "Ctrl+=" or "Ctrl+numpadPlus" or "Ctrl+WheelUp" - Zoom Out: "Ctrl+-" or "Ctrl+numpadMinus" or "Ctrl+WheelDown" - Zoom Reset: "Ctrl+0" or "Ctrl+numpad0" ## Code changes (1) Electron provides this functionality through the `zoomIn|zoomOut|resetZoom` roles in the Menu, so it would have been a quick job. However, given that Electron currently does not support having multiple accelerators for one item, we can't add `Ctrl+WheelUp` to the mix and would have to implement our own handler and use `webFrame`. Given that we need to add code anyways, we handle both keyboard and mouse cases through the same handler, hence the existence of `zoomWindow.js`. It also provides the opportunity to few a few quirks with Electron's default implementation (e.g. stuck at both extremes) (2) I recall there is another Issue for adding keyboard shortcuts. Given that these shortcuts are universally used in browsers, they are probably "reserved", so shouldn't clash with that task.
This commit is contained in:
parent
2754c962a4
commit
bc19503419
5 changed files with 130 additions and 0 deletions
|
@ -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))
|
- 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 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))
|
- 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
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { app, Menu, shell } from 'electron';
|
import { app, Menu, shell } from 'electron';
|
||||||
|
import { changeZoomFactor, ZOOM } from 'util/zoomWindow';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const template = [
|
const template = [
|
||||||
|
@ -22,6 +23,38 @@ export default () => {
|
||||||
label: 'View',
|
label: 'View',
|
||||||
submenu: [
|
submenu: [
|
||||||
{ role: 'reload' },
|
{ 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',
|
label: 'Developer',
|
||||||
submenu: [{ role: 'forcereload' }, { role: 'toggledevtools' }],
|
submenu: [{ role: 'forcereload' }, { role: 'toggledevtools' }],
|
||||||
|
|
|
@ -17,6 +17,9 @@ import Nag from 'component/common/nag';
|
||||||
import REWARDS from 'rewards';
|
import REWARDS from 'rewards';
|
||||||
import usePersistedState from 'effects/use-persisted-state';
|
import usePersistedState from 'effects/use-persisted-state';
|
||||||
import FileDrop from 'component/fileDrop';
|
import FileDrop from 'component/fileDrop';
|
||||||
|
// @if TARGET='app'
|
||||||
|
import { changeZoomFactor, ZOOM } from 'util/zoomWindow';
|
||||||
|
// @endif
|
||||||
// @if TARGET='web'
|
// @if TARGET='web'
|
||||||
import OpenInAppLink from 'web/component/openInAppLink';
|
import OpenInAppLink from 'web/component/openInAppLink';
|
||||||
import YoutubeWelcome from 'web/component/youtubeReferralWelcome';
|
import YoutubeWelcome from 'web/component/youtubeReferralWelcome';
|
||||||
|
@ -172,6 +175,52 @@ function App(props: Props) {
|
||||||
return () => window.removeEventListener('keydown', handleKeyPress);
|
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(() => {
|
useEffect(() => {
|
||||||
if (referredRewardAvailable && sanitizedReferrerParam && isRewardApproved) {
|
if (referredRewardAvailable && sanitizedReferrerParam && isRewardApproved) {
|
||||||
setReferrer(sanitizedReferrerParam, true);
|
setReferrer(sanitizedReferrerParam, true);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import SnackBar from 'component/snackBar';
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
import SplashScreen from 'component/splash';
|
import SplashScreen from 'component/splash';
|
||||||
import * as ACTIONS from 'constants/action_types';
|
import * as ACTIONS from 'constants/action_types';
|
||||||
|
import { changeZoomFactor } from 'util/zoomWindow';
|
||||||
// @endif
|
// @endif
|
||||||
import { ipcRenderer, remote, shell } from 'electron';
|
import { ipcRenderer, remote, shell } from 'electron';
|
||||||
import moment from 'moment';
|
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;
|
const { dock } = remote.app;
|
||||||
|
|
||||||
ipcRenderer.on('window-is-focused', () => {
|
ipcRenderer.on('window-is-focused', () => {
|
||||||
|
|
42
ui/util/zoomWindow.js
Normal file
42
ui/util/zoomWindow.js
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue