mirror of
https://github.com/sipeed/NanoKVM.git
synced 2026-09-12 01:50:20 -05:00
update virtual keyboard
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user