diff --git a/web/.env.development b/web/.env.development index 0755dc5..a202282 100644 --- a/web/.env.development +++ b/web/.env.development @@ -1,3 +1,3 @@ -VITE_SERVER_IP=192.168.0.65 +VITE_SERVER_IP=192.168.3.69 VITE_SERVER_PORT=80 VITE_WITH_CREDENTIALS=false diff --git a/web/package.json b/web/package.json index 1d9f1b1..5777052 100644 --- a/web/package.json +++ b/web/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@ant-design/icons": "^5.6.1", + "@radix-ui/react-scroll-area": "^1.2.10", "@xterm/addon-attach": "^0.11.0", "@xterm/addon-fit": "^0.10.0", "@xterm/xterm": "^5.5.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 4bb2adc..478ef6b 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@ant-design/icons': specifier: ^5.6.1 version: 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-scroll-area': + specifier: ^1.2.10 + version: 1.2.10(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@xterm/addon-attach': specifier: ^0.11.0 version: 0.11.0(@xterm/xterm@5.5.0) @@ -640,9 +643,15 @@ packages: '@open-draft/until@2.1.0': resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + '@radix-ui/number@1.1.1': + resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} + '@radix-ui/primitive@1.1.0': resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==} + '@radix-ui/primitive@1.1.3': + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} + '@radix-ui/react-compose-refs@1.1.0': resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==} peerDependencies: @@ -652,6 +661,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-context@1.1.1': resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==} peerDependencies: @@ -661,6 +679,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-context@1.1.2': + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-dialog@1.1.2': resolution: {integrity: sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==} peerDependencies: @@ -674,6 +701,15 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-direction@1.1.1': + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-dismissable-layer@1.1.1': resolution: {integrity: sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==} peerDependencies: @@ -744,6 +780,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-presence@1.1.5': + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-primitive@2.0.0': resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==} peerDependencies: @@ -757,6 +806,32 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-scroll-area@1.2.10': + resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-slot@1.1.0': resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==} peerDependencies: @@ -766,6 +841,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-callback-ref@1.1.0': resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} peerDependencies: @@ -775,6 +859,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-callback-ref@1.1.1': + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-controllable-state@1.1.0': resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} peerDependencies: @@ -802,6 +895,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@rc-component/async-validator@5.0.4': resolution: {integrity: sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==} engines: {node: '>=14.x'} @@ -3551,20 +3653,36 @@ snapshots: '@open-draft/until@2.1.0': {} + '@radix-ui/number@1.1.1': {} + '@radix-ui/primitive@1.1.0': {} + '@radix-ui/primitive@1.1.3': {} + '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.12)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: '@types/react': 18.3.12 + '@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.12)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.12 + '@radix-ui/react-context@1.1.1(@types/react@18.3.12)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: '@types/react': 18.3.12 + '@radix-ui/react-context@1.1.2(@types/react@18.3.12)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.12 + '@radix-ui/react-dialog@1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 @@ -3587,6 +3705,12 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-direction@1.1.1(@types/react@18.3.12)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.12 + '@radix-ui/react-dismissable-layer@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.0 @@ -3644,6 +3768,16 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-presence@1.1.5(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-primitive@2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1) @@ -3653,6 +3787,32 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@radix-ui/react-primitive@2.1.3(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + + '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.12)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.12 + '@types/react-dom': 18.3.1 + '@radix-ui/react-slot@1.1.0(@types/react@18.3.12)(react@18.3.1)': dependencies: '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1) @@ -3660,12 +3820,25 @@ snapshots: optionalDependencies: '@types/react': 18.3.12 + '@radix-ui/react-slot@1.2.3(@types/react@18.3.12)(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.12)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.12 + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.12)(react@18.3.1)': dependencies: react: 18.3.1 optionalDependencies: '@types/react': 18.3.12 + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.3.12)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.12 + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.12)(react@18.3.1)': dependencies: '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1) @@ -3686,6 +3859,12 @@ snapshots: optionalDependencies: '@types/react': 18.3.12 + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.12)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.12 + '@rc-component/async-validator@5.0.4': dependencies: '@babel/runtime': 7.26.0 diff --git a/web/src/components/ui/scroll-area.tsx b/web/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000..b1e79c4 --- /dev/null +++ b/web/src/components/ui/scroll-area.tsx @@ -0,0 +1,53 @@ +import * as React from 'react'; +import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area'; +import clsx from 'clsx'; + +function ScrollArea({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + {children} + + + + + ); +} + +function ScrollBar({ + className, + orientation = 'vertical', + ...props +}: React.ComponentProps) { + return ( + + + + ); +} + +export { ScrollArea, ScrollBar }; diff --git a/web/src/pages/desktop/menu/fullscreen/index.tsx b/web/src/pages/desktop/menu/fullscreen/index.tsx index 7744240..5c33e25 100644 --- a/web/src/pages/desktop/menu/fullscreen/index.tsx +++ b/web/src/pages/desktop/menu/fullscreen/index.tsx @@ -8,9 +8,10 @@ export const Fullscreen = () => { const [isFullscreen, setIsFullscreen] = useState(false); useEffect(() => { - function onFullscreenChange() { + const onFullscreenChange = () => { setIsFullscreen(!!document.fullscreenElement); - } + }; + onFullscreenChange(); document.addEventListener('fullscreenchange', onFullscreenChange); @@ -24,8 +25,14 @@ export const Fullscreen = () => { if (!document.fullscreenElement) { const element = document.documentElement; element.requestFullscreen(); + + // @ts-expect-error - https://developer.mozilla.org/en-US/docs/Web/API/Keyboard/lock + navigator.keyboard?.lock(); } else { document.exitFullscreen(); + + // @ts-expect-error - https://developer.mozilla.org/en-US/docs/Web/API/Keyboard/unlock + navigator.keyboard?.unlock(); } } diff --git a/web/src/pages/desktop/menu/power/index.tsx b/web/src/pages/desktop/menu/power/index.tsx index bab5925..14b3f99 100644 --- a/web/src/pages/desktop/menu/power/index.tsx +++ b/web/src/pages/desktop/menu/power/index.tsx @@ -48,7 +48,7 @@ export const Power = () => { } const icon = ( -
+
{isLoading ? ( ) : ( diff --git a/web/src/pages/desktop/menu/screen/index.tsx b/web/src/pages/desktop/menu/screen/index.tsx index 203c7b6..f8b2fbb 100644 --- a/web/src/pages/desktop/menu/screen/index.tsx +++ b/web/src/pages/desktop/menu/screen/index.tsx @@ -71,10 +71,10 @@ export const Screen = () => { const content = (
- + {videoMode !== 'mjpeg' && } {videoMode === 'mjpeg' && } diff --git a/web/src/pages/desktop/menu/screen/scale.tsx b/web/src/pages/desktop/menu/screen/scale.tsx index c79731c..40af534 100644 --- a/web/src/pages/desktop/menu/screen/scale.tsx +++ b/web/src/pages/desktop/menu/screen/scale.tsx @@ -1,49 +1,56 @@ -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 { ReactElement, useEffect } from 'react'; +import { Popover } from 'antd'; +import { useAtom } from 'jotai'; +import { CheckIcon, PercentIcon, ScalingIcon } from 'lucide-react'; +import { useTranslation } from 'react-i18next'; -import { videoScaleAtom } from '@/jotai/screen.ts' -import * as storage from '@/lib/localstorage.ts' +import * as storage from '@/lib/localstorage.ts'; +import { videoScaleAtom } from '@/jotai/screen.ts'; + +const ScaleList = [ + { label: '200', value: 2 }, + { label: '150', value: 1.5 }, + { label: '100', value: 1 }, + { label: '75', value: 0.75 }, + { label: '50', value: 0.5 } +]; export const Scale = (): ReactElement => { - const { t } = useTranslation() + const { t } = useTranslation(); - const [videoScale, setVideoScale] = useAtom(videoScaleAtom) + const [videoScale, setVideoScale] = useAtom(videoScaleAtom); useEffect(() => { - const scale = storage.getVideoScale() + const scale = storage.getVideoScale(); if (scale) { - setVideoScale(scale) + setVideoScale(scale); } - }, [setVideoScale]) + }, [setVideoScale]); - async function updateScale(scale: number): Promise { - setVideoScale(scale) - storage.setVideoScale(scale) + async function update(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} - /> -
- ) + <> + {ScaleList.map((scale) => ( +
update(scale.value)} + > +
+ {scale.value === videoScale && } +
+
+ {scale.label} + +
+
+ ))} + + ); return ( @@ -54,5 +61,5 @@ export const Scale = (): ReactElement => { {t('screen.scale')}
- ) -} \ No newline at end of file + ); +}; diff --git a/web/src/pages/desktop/menu/screen/video-mode.tsx b/web/src/pages/desktop/menu/screen/video-mode.tsx index 9cafb24..a424153 100644 --- a/web/src/pages/desktop/menu/screen/video-mode.tsx +++ b/web/src/pages/desktop/menu/screen/video-mode.tsx @@ -41,9 +41,9 @@ export const VideoMode = () => { <> {!isDirectSupported && (
diff --git a/web/src/pages/desktop/menu/settings/about/community.tsx b/web/src/pages/desktop/menu/settings/about/community.tsx index 1c8754b..4a49235 100644 --- a/web/src/pages/desktop/menu/settings/about/community.tsx +++ b/web/src/pages/desktop/menu/settings/about/community.tsx @@ -31,9 +31,9 @@ export const Community = () => { return ( <> -
{t('settings.about.community')}
+
{t('settings.about.community')}
-
+
{communities.map((community) => ( { } return ( - <> -
+
+
{t('settings.about.hostname')} {editState === 'editing' ? ( @@ -94,10 +94,10 @@ export const Hostname = () => {
{editState === 'edited' && ( -
+
{t('settings.about.hostnameUpdated')}
)} - +
); }; diff --git a/web/src/pages/desktop/menu/settings/about/index.tsx b/web/src/pages/desktop/menu/settings/about/index.tsx index 1ef0970..17971a3 100644 --- a/web/src/pages/desktop/menu/settings/about/index.tsx +++ b/web/src/pages/desktop/menu/settings/about/index.tsx @@ -2,7 +2,6 @@ import { Divider } from 'antd'; import { useTranslation } from 'react-i18next'; import { Community } from './community.tsx'; -import { Hostname } from './hostname.tsx'; import { Information } from './information.tsx'; export const About = () => { @@ -10,12 +9,11 @@ export const About = () => { return ( <> -
{t('settings.about.title')}
- +
{t('settings.about.title')}
+ - - + diff --git a/web/src/pages/desktop/menu/settings/about/information.tsx b/web/src/pages/desktop/menu/settings/about/information.tsx index 9d9449d..442c75d 100644 --- a/web/src/pages/desktop/menu/settings/about/information.tsx +++ b/web/src/pages/desktop/menu/settings/about/information.tsx @@ -5,6 +5,8 @@ import { useTranslation } from 'react-i18next'; import * as api from '@/api/vm.ts'; +import { Hostname } from './hostname.tsx'; + type IP = { name: string; addr: string; @@ -38,9 +40,9 @@ export const Information = () => { return ( <> -
{t('settings.about.information')}
+
{t('settings.about.information')}
-
+
{/* IP list */}
{t('settings.about.ip')} @@ -103,6 +105,8 @@ export const Information = () => { {information ? information.application : '-'}
+ +
); diff --git a/web/src/pages/desktop/menu/settings/account/index.tsx b/web/src/pages/desktop/menu/settings/account/index.tsx index 7da1f45..fa250f8 100644 --- a/web/src/pages/desktop/menu/settings/account/index.tsx +++ b/web/src/pages/desktop/menu/settings/account/index.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { Divider } from 'antd'; +import { Button, Divider } from 'antd'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; @@ -27,10 +27,10 @@ export const Account = () => { return ( <> -
{t('settings.account.title')}
- +
{t('settings.account.title')}
+ -
+
{t('settings.account.webAccount')} {username ? username : '-'} @@ -38,15 +38,13 @@ export const Account = () => {
{t('settings.account.password')} - +
- + + diff --git a/web/src/pages/desktop/menu/settings/appearance/index.tsx b/web/src/pages/desktop/menu/settings/appearance/index.tsx index 1c24d20..e1c6c37 100644 --- a/web/src/pages/desktop/menu/settings/appearance/index.tsx +++ b/web/src/pages/desktop/menu/settings/appearance/index.tsx @@ -10,14 +10,14 @@ export const Appearance = () => { return ( <> -
{t('settings.appearance.title')}
- +
{t('settings.appearance.title')}
+ -
- - -
- +
{t('settings.appearance.display')}
+ + + + diff --git a/web/src/pages/desktop/menu/settings/appearance/language.tsx b/web/src/pages/desktop/menu/settings/appearance/language.tsx index fff2d81..b22f7bb 100644 --- a/web/src/pages/desktop/menu/settings/appearance/language.tsx +++ b/web/src/pages/desktop/menu/settings/appearance/language.tsx @@ -1,5 +1,4 @@ import { Select } from 'antd'; -import { LanguagesIcon } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import languages from '@/i18n/languages.ts'; @@ -21,18 +20,20 @@ export const Language = () => { } return ( -
-
- +
+
{t('settings.appearance.language')} + {t('settings.appearance.languageDesc')}
- +
); }; diff --git a/web/src/pages/desktop/menu/settings/appearance/menu-bar.tsx b/web/src/pages/desktop/menu/settings/appearance/menu-bar.tsx index eeb3a77..29abd1c 100644 --- a/web/src/pages/desktop/menu/settings/appearance/menu-bar.tsx +++ b/web/src/pages/desktop/menu/settings/appearance/menu-bar.tsx @@ -19,12 +19,12 @@ export const MenuBar = () => { const [menuDisabledItems, setMenuDisabledItems] = useAtom(menuDisabledItemsAtom); const items = [ - { key: 'image', icon: }, - { key: 'download', icon: }, - { key: 'script', icon: }, - { key: 'terminal', icon: }, - { key: 'wol', icon: }, - { key: 'power', icon: } + { key: 'image', icon: }, + { key: 'download', icon: }, + { key: 'script', icon: }, + { key: 'terminal', icon: }, + { key: 'wol', icon: }, + { key: 'power', icon: } ]; function updateItems(key: string) { @@ -45,10 +45,10 @@ export const MenuBar = () => { {t('settings.appearance.menuBarDesc')}
-
+
{items.map((item) => (
-
+
{item.icon} {t(`${item.key}.title`)}
diff --git a/web/src/pages/desktop/menu/settings/appearance/web-title.tsx b/web/src/pages/desktop/menu/settings/appearance/web-title.tsx index e3b1934..694d39e 100644 --- a/web/src/pages/desktop/menu/settings/appearance/web-title.tsx +++ b/web/src/pages/desktop/menu/settings/appearance/web-title.tsx @@ -1,7 +1,6 @@ import { useEffect, useState } from 'react'; import { Input } from 'antd'; import { useAtom } from 'jotai'; -import { GlobeIcon } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import * as api from '@/api/vm.ts'; @@ -46,26 +45,23 @@ export const WebTitle = () => { } return ( -
+
-
-
- -
- {t('settings.appearance.webTitle')} -
+ {t('settings.appearance.webTitle')} {t('settings.appearance.webTitleDesc')}
- setWebTitle(e.target.value)} - onPressEnter={submit} - onBlur={submit} - placeholder="NanoKVM" - /> +
+ setWebTitle(e.target.value)} + onPressEnter={submit} + onBlur={submit} + placeholder="NanoKVM" + /> +
); }; diff --git a/web/src/pages/desktop/menu/settings/device/advanced/index.tsx b/web/src/pages/desktop/menu/settings/device/advanced/index.tsx index 157dcf1..f256261 100644 --- a/web/src/pages/desktop/menu/settings/device/advanced/index.tsx +++ b/web/src/pages/desktop/menu/settings/device/advanced/index.tsx @@ -2,12 +2,11 @@ import { Collapse } from 'antd'; import { useTranslation } from 'react-i18next'; import { Swap } from './swap.tsx'; -import { Autostart } from './autostart.tsx'; const children = ( -
+
- + {/**/}
); diff --git a/web/src/pages/desktop/menu/settings/device/advanced/swap.tsx b/web/src/pages/desktop/menu/settings/device/advanced/swap.tsx index d60a4b2..0154a89 100644 --- a/web/src/pages/desktop/menu/settings/device/advanced/swap.tsx +++ b/web/src/pages/desktop/menu/settings/device/advanced/swap.tsx @@ -59,17 +59,17 @@ export const Swap = () => { return (
-
+
{t('settings.device.swap.title')} - +
{t('settings.device.swap.description')} diff --git a/web/src/pages/desktop/menu/settings/device/hdmi.tsx b/web/src/pages/desktop/menu/settings/device/hdmi.tsx index 4ab22ea..6bd7243 100644 --- a/web/src/pages/desktop/menu/settings/device/hdmi.tsx +++ b/web/src/pages/desktop/menu/settings/device/hdmi.tsx @@ -61,7 +61,7 @@ export const Hdmi = () => { <> {isPcie && (
-
+
HDMI diff --git a/web/src/pages/desktop/menu/settings/device/mdns.tsx b/web/src/pages/desktop/menu/settings/device/mdns.tsx index c97a7d2..17594e5 100644 --- a/web/src/pages/desktop/menu/settings/device/mdns.tsx +++ b/web/src/pages/desktop/menu/settings/device/mdns.tsx @@ -43,17 +43,17 @@ export const Mdns = () => { return (
-
+
mDNS - +
diff --git a/web/src/pages/desktop/menu/settings/device/mouse-jiggler.tsx b/web/src/pages/desktop/menu/settings/device/mouse-jiggler.tsx index f33dc02..3796349 100644 --- a/web/src/pages/desktop/menu/settings/device/mouse-jiggler.tsx +++ b/web/src/pages/desktop/menu/settings/device/mouse-jiggler.tsx @@ -84,7 +84,7 @@ export const MouseJiggler = () => { return (
-
+
{t('settings.device.mouseJiggler.title')} {t('settings.device.mouseJiggler.description')} diff --git a/web/src/pages/desktop/menu/settings/device/oled.tsx b/web/src/pages/desktop/menu/settings/device/oled.tsx index 6792cd8..fc013b1 100644 --- a/web/src/pages/desktop/menu/settings/device/oled.tsx +++ b/web/src/pages/desktop/menu/settings/device/oled.tsx @@ -54,7 +54,7 @@ export const Oled = () => { return (
-
+
{t('settings.device.oled.title')} {t('settings.device.oled.description')}
diff --git a/web/src/pages/desktop/menu/settings/device/ssh.tsx b/web/src/pages/desktop/menu/settings/device/ssh.tsx index ca4b73a..7128592 100644 --- a/web/src/pages/desktop/menu/settings/device/ssh.tsx +++ b/web/src/pages/desktop/menu/settings/device/ssh.tsx @@ -43,17 +43,17 @@ export const Ssh = () => { return (
-
+
SSH - +
{t('settings.device.ssh.description')} diff --git a/web/src/pages/desktop/menu/settings/device/tls.tsx b/web/src/pages/desktop/menu/settings/device/tls.tsx index 8fa477d..96f0ae8 100644 --- a/web/src/pages/desktop/menu/settings/device/tls.tsx +++ b/web/src/pages/desktop/menu/settings/device/tls.tsx @@ -47,17 +47,17 @@ export const Tls = () => { return (
-
+
HTTPS - +
{t('settings.device.tls.description')} diff --git a/web/src/pages/desktop/menu/settings/device/wifi.tsx b/web/src/pages/desktop/menu/settings/device/wifi.tsx index 876f0d9..a076463 100644 --- a/web/src/pages/desktop/menu/settings/device/wifi.tsx +++ b/web/src/pages/desktop/menu/settings/device/wifi.tsx @@ -126,7 +126,7 @@ export const Wifi = () => { return ( <>
-
+
{t('settings.device.wifi.title')} {t('settings.device.wifi.description')}
diff --git a/web/src/pages/desktop/menu/settings/index.tsx b/web/src/pages/desktop/menu/settings/index.tsx index b116ec7..2e1e0a9 100644 --- a/web/src/pages/desktop/menu/settings/index.tsx +++ b/web/src/pages/desktop/menu/settings/index.tsx @@ -17,6 +17,7 @@ import * as api from '@/api/application.ts'; import * as ls from '@/lib/localstorage.ts'; import { isKeyboardEnableAtom } from '@/jotai/keyboard.ts'; import { Tailscale as TailscaleIcon } from '@/components/icons/tailscale'; +import { ScrollArea } from '@/components/ui/scroll-area'; import { About } from './about'; import { Account } from './account'; @@ -119,23 +120,21 @@ export const Settings = () => { width={'80%'} centered={true} footer={null} - destroyOnClose={true} + destroyOnHidden={true} onCancel={closeModal} style={{ maxWidth: '1080px' }} styles={{ content: { padding: 0 } }} >
-
+
{t('settings.title')}
-
- {tabs.map((tab) => (
changeTab(tab.id)} > @@ -156,11 +155,13 @@ export const Settings = () => { ))}
-
-
- <>{tabs.find((tab) => tab.id === currentTab)?.component} + +
+
+ <>{tabs.find((tab) => tab.id === currentTab)?.component} +
-
+
diff --git a/web/src/pages/desktop/menu/settings/tailscale/header.tsx b/web/src/pages/desktop/menu/settings/tailscale/header.tsx index 412e169..fd34ba4 100644 --- a/web/src/pages/desktop/menu/settings/tailscale/header.tsx +++ b/web/src/pages/desktop/menu/settings/tailscale/header.tsx @@ -44,7 +44,7 @@ export const Header = ({ state, onSuccess }: HeaderProps) => { return (
- {t('settings.tailscale.title')} + {t('settings.tailscale.title')}
{state && ['notLogin', 'stopped', 'running'].includes(state) && ( @@ -101,7 +101,7 @@ export const Header = ({ state, onSuccess }: HeaderProps) => { placement="bottom" trigger="click" > -
+
diff --git a/web/src/pages/desktop/menu/settings/tailscale/index.tsx b/web/src/pages/desktop/menu/settings/tailscale/index.tsx index 26ce361..cb71a36 100644 --- a/web/src/pages/desktop/menu/settings/tailscale/index.tsx +++ b/web/src/pages/desktop/menu/settings/tailscale/index.tsx @@ -49,10 +49,10 @@ export const Tailscale = ({ setIsLocked }: TailscaleProps) => { return ( <>
- + {isLoading ? ( -
+
{t('settings.tailscale.loading')}
diff --git a/web/src/pages/desktop/menu/settings/tailscale/memory.tsx b/web/src/pages/desktop/menu/settings/tailscale/memory.tsx index b9fcfdb..c193d83 100644 --- a/web/src/pages/desktop/menu/settings/tailscale/memory.tsx +++ b/web/src/pages/desktop/menu/settings/tailscale/memory.tsx @@ -52,7 +52,7 @@ export const Memory = () => { title={t('settings.tailscale.memory.tip')} className="cursor-pointer text-neutral-500" placement="top" - overlayStyle={{ maxWidth: '400px' }} + styles={{ root: { maxWidth: '400px' } }} > diff --git a/web/src/pages/desktop/menu/settings/tailscale/swap.tsx b/web/src/pages/desktop/menu/settings/tailscale/swap.tsx index 8c24cf9..0777c5d 100644 --- a/web/src/pages/desktop/menu/settings/tailscale/swap.tsx +++ b/web/src/pages/desktop/menu/settings/tailscale/swap.tsx @@ -59,7 +59,7 @@ export const Swap = () => { title={t('settings.tailscale.swap.tip')} className="cursor-pointer text-neutral-500" placement="top" - overlayStyle={{ maxWidth: '400px' }} + styles={{ root: { maxWidth: '400px' } }} > diff --git a/web/src/pages/desktop/menu/settings/update/index.tsx b/web/src/pages/desktop/menu/settings/update/index.tsx index f949b8e..d5472cc 100644 --- a/web/src/pages/desktop/menu/settings/update/index.tsx +++ b/web/src/pages/desktop/menu/settings/update/index.tsx @@ -77,12 +77,12 @@ export const Update = ({ setIsLocked }: UpdateProps) => { return ( <> -
{t('settings.update.title')}
- +
{t('settings.update.title')}
+ -
+
{status === 'loading' && ( diff --git a/web/src/pages/desktop/menu/settings/update/preview.tsx b/web/src/pages/desktop/menu/settings/update/preview.tsx index 8fbfa7e..a472d70 100644 --- a/web/src/pages/desktop/menu/settings/update/preview.tsx +++ b/web/src/pages/desktop/menu/settings/update/preview.tsx @@ -56,17 +56,17 @@ export const Preview = () => { return (
-
+
{t('settings.update.preview')} - +