diff --git a/browser/src/App.tsx b/browser/src/App.tsx
index 2c11e7a..c79e2f9 100644
--- a/browser/src/App.tsx
+++ b/browser/src/App.tsx
@@ -10,7 +10,12 @@ import { Keyboard } from '@/components/keyboard';
import { Menu } from '@/components/menu';
import { Mouse } from '@/components/mouse';
import { VirtualKeyboard } from '@/components/virtual-keyboard';
-import { resolutionAtom, serialStateAtom, videoStateAtom } from '@/jotai/device.ts';
+import {
+ resolutionAtom,
+ serialStateAtom,
+ videoScaleAtom,
+ videoStateAtom
+} from '@/jotai/device.ts';
import { isKeyboardEnableAtom } from '@/jotai/keyboard.ts';
import { mouseStyleAtom } from '@/jotai/mouse.ts';
import { camera } from '@/libs/camera';
@@ -23,6 +28,7 @@ const App = () => {
const isBigScreen = useMediaQuery({ minWidth: 850 });
const mouseStyle = useAtomValue(mouseStyleAtom);
+ const videoScale = useAtomValue(videoScaleAtom);
const videoState = useAtomValue(videoStateAtom);
const serialState = useAtomValue(serialStateAtom);
const isKeyboardEnable = useAtomValue(isKeyboardEnableAtom);
@@ -107,7 +113,13 @@ const App = () => {
diff --git a/browser/src/components/menu/video/index.tsx b/browser/src/components/menu/video/index.tsx
index 8b78ed9..dd44766 100644
--- a/browser/src/components/menu/video/index.tsx
+++ b/browser/src/components/menu/video/index.tsx
@@ -3,11 +3,13 @@ import { MonitorIcon } from 'lucide-react';
import { Device } from './device.tsx';
import { Resolution } from './resolution.tsx';
+import { Scale } from './scale.tsx';
export const Video = () => {
const content = (
+
);
diff --git a/browser/src/components/menu/video/scale.tsx b/browser/src/components/menu/video/scale.tsx
new file mode 100644
index 0000000..d21f5e3
--- /dev/null
+++ b/browser/src/components/menu/video/scale.tsx
@@ -0,0 +1,58 @@
+import { ReactElement, useEffect } from 'react'
+import { Popover, Slider } from 'antd'
+import { useAtom } from 'jotai'
+import { ScalingIcon } from 'lucide-react'
+import { useTranslation } from 'react-i18next'
+
+import { videoScaleAtom } from '@/jotai/device.ts';
+import * as storage from '@/libs/storage';
+
+export const Scale = (): ReactElement => {
+ const { t } = useTranslation()
+
+ const [videoScale, setVideoScale] = useAtom(videoScaleAtom)
+
+ useEffect(() => {
+ const scale = storage.getVideoScale()
+ if (scale) {
+ setVideoScale(scale)
+ }
+ }, [])
+
+ async function updateScale(scale: number): Promise {
+ setVideoScale(scale)
+ storage.setVideoScale(scale)
+ }
+
+ const content = (
+
+ x0.5,
+ 1: x1.0,
+ 1.5: x1.5,
+ 2: x2.0
+ }}
+ range={false}
+ included={false}
+ min={0.5}
+ max={2}
+ step={0.1}
+ defaultValue={videoScale}
+ onChange={updateScale}
+ />
+
+ )
+
+ return (
+
+
+
+
+
+
{t('video.scale')}
+
+
+ )
+}
diff --git a/browser/src/i18n/locales/be.ts b/browser/src/i18n/locales/be.ts
index 094db16..b149e92 100644
--- a/browser/src/i18n/locales/be.ts
+++ b/browser/src/i18n/locales/be.ts
@@ -24,6 +24,7 @@ const be = {
},
video: {
resolution: 'Resolutie',
+ scale: 'Schaal',
customResolution: 'Aangepast',
device: 'Toestel',
custom: {
@@ -62,5 +63,5 @@ const be = {
}
}
};
-
- export default be;
\ No newline at end of file
+
+ export default be;
diff --git a/browser/src/i18n/locales/de.ts b/browser/src/i18n/locales/de.ts
index 79dbb70..94cde68 100644
--- a/browser/src/i18n/locales/de.ts
+++ b/browser/src/i18n/locales/de.ts
@@ -24,6 +24,7 @@ const de = {
},
video: {
resolution: 'Auflösung',
+ scale: 'Skalierung',
customResolution: 'Benutzerdefiniert',
device: 'Gerät',
custom: {
@@ -62,5 +63,5 @@ const de = {
}
}
};
-
- export default de;
\ No newline at end of file
+
+ export default de;
diff --git a/browser/src/i18n/locales/en.ts b/browser/src/i18n/locales/en.ts
index 59ea63b..3a8fd9f 100644
--- a/browser/src/i18n/locales/en.ts
+++ b/browser/src/i18n/locales/en.ts
@@ -24,6 +24,7 @@ const en = {
},
video: {
resolution: 'Resolution',
+ scale: 'Scale',
customResolution: 'Custom',
device: 'Device',
custom: {
diff --git a/browser/src/i18n/locales/ko.ts b/browser/src/i18n/locales/ko.ts
index e07fbcc..d1be2ed 100644
--- a/browser/src/i18n/locales/ko.ts
+++ b/browser/src/i18n/locales/ko.ts
@@ -24,6 +24,7 @@ const ko = {
},
video: {
resolution: '해상도',
+ scale: '배율',
customResolution: '사용자 정의',
device: '장치',
custom: {
diff --git a/browser/src/i18n/locales/nl.ts b/browser/src/i18n/locales/nl.ts
index abab0ea..634f79b 100644
--- a/browser/src/i18n/locales/nl.ts
+++ b/browser/src/i18n/locales/nl.ts
@@ -24,6 +24,7 @@ const nl = {
},
video: {
resolution: 'Resolutie',
+ scale: 'Schaal',
customResolution: 'Aangepast',
device: 'Apparaat',
custom: {
@@ -62,5 +63,5 @@ const nl = {
}
}
};
-
- export default nl;
\ No newline at end of file
+
+ export default nl;
diff --git a/browser/src/i18n/locales/ru.ts b/browser/src/i18n/locales/ru.ts
index c1ee4c8..44012d9 100644
--- a/browser/src/i18n/locales/ru.ts
+++ b/browser/src/i18n/locales/ru.ts
@@ -24,6 +24,7 @@ const ru = {
},
video: {
resolution: 'Разрешение',
+ scale: 'Масштаб',
customResolution: 'Пользовательское',
device: 'Видеоустройство',
custom: {
diff --git a/browser/src/i18n/locales/zh.ts b/browser/src/i18n/locales/zh.ts
index e7f1f85..8ac32ea 100644
--- a/browser/src/i18n/locales/zh.ts
+++ b/browser/src/i18n/locales/zh.ts
@@ -22,6 +22,7 @@ const zh = {
},
video: {
resolution: '分辨率',
+ scale: '缩放',
customResolution: '自定义',
device: '设备',
custom: {
diff --git a/browser/src/jotai/device.ts b/browser/src/jotai/device.ts
index a768ee3..195dc28 100644
--- a/browser/src/jotai/device.ts
+++ b/browser/src/jotai/device.ts
@@ -10,6 +10,8 @@ export const resolutionAtom = atom({
height: 1080
});
+export const videoScaleAtom = atom(1.0)
+
export const videoDeviceIdAtom = atom('');
export const videoStateAtom = atom('disconnected');
diff --git a/browser/src/libs/storage/index.ts b/browser/src/libs/storage/index.ts
index 9397942..4098771 100644
--- a/browser/src/libs/storage/index.ts
+++ b/browser/src/libs/storage/index.ts
@@ -4,6 +4,7 @@ const LANGUAGE_KEY = 'nanokvm-usb-language';
const VIDEO_DEVICE_ID_KEY = 'nanokvm-usb-video-device-id';
const VIDEO_RESOLUTION_KEY = 'nanokvm-usb-video-resolution';
const CUSTOM_RESOLUTION_KEY = 'nanokvm-usb-custom-resolution';
+const VIDEO_SCALE_KEY = 'nanokvm-usb-video-scale'
const IS_MENU_OPEN_KEY = 'nanokvm-is-menu-open';
const MOUSE_STYLE_KEY = 'nanokvm-usb-mouse-style';
const MOUSE_MODE_KEY = 'nanokvm-usb-mouse-mode';
@@ -56,6 +57,18 @@ export function removeCustomResolutions() {
localStorage.removeItem(CUSTOM_RESOLUTION_KEY);
}
+export function getVideoScale(): number | null {
+ const scale = localStorage.getItem(VIDEO_SCALE_KEY)
+ if (scale && Number(scale)) {
+ return Number(scale)
+ }
+ return null
+}
+
+export function setVideoScale(scale: number): void {
+ localStorage.setItem(VIDEO_SCALE_KEY, String(scale))
+}
+
export function getIsMenuOpen(): boolean {
const state = localStorage.getItem(IS_MENU_OPEN_KEY);
if (!state) {