Skip to content

Commit 06c88c9

Browse files
committed
feature: Zoom Widget for more visual screen scale change
Refs #1326
1 parent c0373ae commit 06c88c9

File tree

4 files changed

+75
-2
lines changed

4 files changed

+75
-2
lines changed

desktop-app/src/renderer/AppContent.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import KeyboardShortcutsManager from './components/KeyboardShortcutsManager';
1313
import { ReleaseNotes } from './components/ReleaseNotes';
1414
import { Sponsorship } from './components/Sponsorship';
1515
import { AboutDialog } from './components/AboutDialog';
16+
import { ZoomWidget } from './components/ZoomWidget/ZoomWidget';
1617

1718
if ((navigator as any).userAgentData.platform === 'Windows') {
1819
import('./titlebar-styles.css');
@@ -23,6 +24,7 @@ const Browser = () => {
2324
<div className="h-screen gap-2 overflow-hidden pt-2">
2425
<ToolBar />
2526
<Previewer />
27+
<ZoomWidget className="absolute bottom-5 right-5 z-50" />
2628
</div>
2729
);
2830
};

desktop-app/src/renderer/components/ToolBar/Menu/Flyout/Zoom.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback } from 'react';
1+
import { useCallback, ReactNode } from 'react';
22
import { useDispatch, useSelector } from 'react-redux';
33
import Button from 'renderer/components/Button';
44
import useKeyboardShortcut, {
@@ -11,7 +11,7 @@ import {
1111
} from 'renderer/store/features/renderer';
1212

1313
interface ZoomButtonProps {
14-
children: React.ReactNode;
14+
children: ReactNode;
1515
onClick: () => void;
1616
}
1717

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { useState, useEffect, FC } from 'react';
2+
import { useDispatch, useSelector } from 'react-redux';
3+
4+
import { selectZoomFactor, zoomReset } from 'renderer/store/features/renderer';
5+
import { Icon } from '@iconify/react';
6+
import cx from 'classnames';
7+
8+
interface ZoomWidgetProps {
9+
className?: string;
10+
}
11+
12+
let timeout = setTimeout(() => {}, 0);
13+
14+
export const ZoomWidget: FC<ZoomWidgetProps> = ({ className = '' }) => {
15+
const zoomfactor = useSelector(selectZoomFactor);
16+
const [isVisible, setIsVisible] = useState<boolean>(false);
17+
const dispatch = useDispatch();
18+
19+
useEffect(() => {
20+
if (zoomfactor === 1) {
21+
setIsVisible(false);
22+
} else {
23+
clearTimeout(timeout);
24+
setIsVisible(true);
25+
timeout = setTimeout(() => {
26+
setIsVisible(false);
27+
}, 5000);
28+
}
29+
30+
return () => {
31+
clearTimeout(timeout);
32+
};
33+
}, [zoomfactor]);
34+
35+
const resetZoom = () => dispatch(zoomReset());
36+
37+
if (isVisible)
38+
return (
39+
<button
40+
type="button"
41+
onClick={resetZoom}
42+
tabIndex={0}
43+
className={cx(
44+
'rounded bg-white p-2 text-sm shadow-lg ring-1 ring-slate-500 !ring-opacity-40 transition duration-700 ease-in-out dark:bg-slate-900 dark:ring-white dark:!ring-opacity-40',
45+
className
46+
)}
47+
>
48+
<span className="w-10 text-center">
49+
Zoom: {Math.ceil(zoomfactor * 100)}%
50+
</span>
51+
<Icon
52+
className="ml-3 mb-1 inline focus:outline-none"
53+
icon="system-uicons:reset"
54+
height={16}
55+
/>
56+
</button>
57+
);
58+
59+
return null;
60+
};

desktop-app/src/renderer/store/features/renderer/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface RendererState {
2323
const zoomSteps = [
2424
0.25, 0.33, 0.5, 0.55, 0.67, 0.75, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2,
2525
];
26+
const zoomDefaultStep = 8;
2627

2728
const urlFromQueryParam = () => {
2829
const params = new URLSearchParams(window.location.search);
@@ -116,6 +117,15 @@ export const rendererSlice = createSlice({
116117
}
117118
}
118119
},
120+
zoomReset: (state) => {
121+
state.zoomFactor = zoomSteps[zoomDefaultStep];
122+
state.individualZoomFactor = zoomSteps[zoomDefaultStep];
123+
window.electron.store.set(
124+
'renderer.individualZoomStepIndex',
125+
zoomDefaultStep
126+
);
127+
window.electron.store.set('renderer.zoomStepIndex', zoomDefaultStep);
128+
},
119129
setRotate: (state, action: PayloadAction<boolean>) => {
120130
state.rotate = action.payload;
121131
},
@@ -147,6 +157,7 @@ export const {
147157
setAddress,
148158
zoomIn,
149159
zoomOut,
160+
zoomReset,
150161
setRotate,
151162
setIsInspecting,
152163
setLayout,

0 commit comments

Comments
 (0)