update virtual keyboard

This commit is contained in:
wj-xiao
2024-08-30 15:16:43 +08:00
parent 618498f7b0
commit 462b3427f5
3 changed files with 48 additions and 40 deletions

View File

@@ -79,7 +79,7 @@
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
}
.hg-layout-default .hg-button.hg-functionBtn.hg-button-space {
.hg-button.hg-functionBtn.hg-button-space {
width: 250px;
}
@@ -87,14 +87,14 @@
width: 350px;
}
.simple-keyboard.hg-layout-default .simple-keyboard.hg-layout-mac .hg-button.hg-highlight {
.simple-keyboard .hg-highlight {
background: rgb(37 99 235);
border-bottom: 1px solid #2563eb;
box-shadow: 0 1px 3px 0 rgb(37 99 235 / 0.1), 0 1px 2px -1px rgb(37 99 235 / 0.1);
color: white;
}
.simple-keyboard.hg-layout-default .simple-keyboard.hg-layout-mac .hg-button.hg-double{
.simple-keyboard .hg-button.hg-double{
text-align: center;
font-size: 14px;
line-height: 16px;

View File

@@ -7,6 +7,7 @@ const QUALITY_KEY = 'nano-kvm-quality';
const MOUSE_STYLE_KEY = 'nano-kvm-mouse-style';
const MOUSE_MODE_KEY = 'nano-kvm-mouse-mode';
const SKIP_UPDATE_KEY = 'nano-kvm-check-update';
const KEYBOARD_LAYOUT_KEY = 'nano-kvm-keyboard-layout';
type ItemWithExpiry = {
value: string;
@@ -108,3 +109,11 @@ export function setSkipUpdate(skip: boolean) {
const expiry = 3 * 24 * 60 * 60 * 1000; // 3天
setWithExpiry(SKIP_UPDATE_KEY, String(skip), expiry);
}
export function setKeyboardLayout(layout: string) {
localStorage.setItem(KEYBOARD_LAYOUT_KEY, layout);
}
export function getKeyboardLayout() {
return localStorage.getItem(KEYBOARD_LAYOUT_KEY);
}

View File

@@ -1,16 +1,16 @@
import { useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { AppleOutlined, WindowsOutlined } from '@ant-design/icons';
import { ConfigProvider, Segmented, theme } from 'antd';
import clsx from 'clsx';
import { useAtom } from 'jotai';
import { XIcon } from 'lucide-react';
import Keyboard, { KeyboardButtonTheme } from 'react-simple-keyboard';
import { Drawer } from 'vaul';
import { Radio } from 'antd';
import type { RadioChangeEvent } from 'antd';
import { useTranslation } from 'react-i18next';
import 'react-simple-keyboard/build/css/index.css';
import '@/assets/styles/keyboard.css';
import { getKeyboardLayout, setKeyboardLayout } from '@/lib/localstorage.ts';
import { client } from '@/lib/websocket.ts';
import { isKeyboardOpenAtom } from '@/jotai/keyboard.ts';
@@ -28,22 +28,21 @@ type KeyboardProps = {
isBigScreen: boolean;
};
const keyboardLayoutOptions = [
{ label: 'Win', value: 'default' },
{ label: 'Mac', value: 'mac' }
];
export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => {
const { t } = useTranslation();
const [isKeyboardOpen, setIsKeyboardOpen] = useAtom(isKeyboardOpenAtom);
const [isCapsLock, setIsCapsLock] = useState(false);
const [activeModifierKeys, setActiveModifierKeys] = useState<string[]>([]);
const [layout, setLayout] = useState('default');
const [activeModifierKeys, setActiveModifierKeys] = useState<string[]>([]);
const keyboardRef = useRef<any>(null);
useEffect(() => {
const keyboardLayout = getKeyboardLayout();
if (keyboardLayout && ['default', 'mac'].includes(keyboardLayout)) {
setLayout(keyboardLayout);
}
}, []);
function onKeyPress(key: string) {
if (modifierKeys.includes(key)) {
if (activeModifierKeys.includes(key)) {
@@ -52,13 +51,10 @@ export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => {
} else {
setActiveModifierKeys([...activeModifierKeys, key]);
}
} else {
if (key === '{capslock}') {
setIsCapsLock(!isCapsLock);
}
sendKeydown(key);
return;
}
sendKeydown(key);
}
function onKeyReleased(key: string) {
@@ -126,18 +122,16 @@ export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => {
function getButtonTheme(): KeyboardButtonTheme[] {
const theme = [{ class: 'hg-double', buttons: doubleKeys.join(' ') }];
const activeKeys = [...activeModifierKeys];
if (isCapsLock) {
activeKeys.push('{capslock}');
}
if (activeKeys.length > 0) {
theme.push({ class: 'hg-highlight', buttons: activeKeys.join(' ') });
if (activeModifierKeys.length > 0) {
const buttons = activeModifierKeys.join(' ');
theme.push({ class: 'hg-highlight', buttons });
}
return theme;
}
function selectLayout({ target: { value } }: RadioChangeEvent) {
function selectLayout(value: string) {
setKeyboardLayout(value);
setLayout(value);
}
@@ -153,18 +147,22 @@ export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => {
{/* header */}
<div className="flex items-center justify-between px-3 py-1">
<div className="flex flex-row">
<div className="keyboard-header w-fit my-auto mr-2 text-sm font-bold text-neutral-500">
{t('keyboard')}
</div>
<Radio.Group
options={keyboardLayoutOptions}
onChange={selectLayout}
value={layout}
optionType='button'
buttonStyle='solid'
/>
<ConfigProvider
theme={{
algorithm: theme.defaultAlgorithm
}}
>
<Segmented
options={[
{ label: 'Win', value: 'default', icon: <WindowsOutlined /> },
{ label: 'Mac', value: 'mac', icon: <AppleOutlined /> }
]}
value={layout}
onChange={selectLayout}
/>
</ConfigProvider>
</div>
<div className="h-1.5 w-12 flex-shrink-0 rounded-full bg-zinc-300" />
<div className="flex w-[100px] items-center justify-end">
<div
className="flex h-[20px] w-[20px] cursor-pointer items-center justify-center rounded text-neutral-600 hover:bg-neutral-300 hover:text-white"
@@ -174,6 +172,7 @@ export const VirtualKeyboard = ({ isBigScreen }: KeyboardProps) => {
</div>
</div>
</div>
<div className="h-px flex-shrink-0 border-b bg-neutral-300" />
<div data-vaul-no-drag className="keyboardContainer w-full">