mirror of
https://github.com/sipeed/NanoKVM.git
synced 2026-09-11 00:22:56 -05:00
@@ -47,6 +47,7 @@ const en = {
|
||||
finishBtn: 'Finished'
|
||||
},
|
||||
screen: {
|
||||
title: 'Screen',
|
||||
video: 'Video Mode',
|
||||
resolution: 'Resolution',
|
||||
auto: 'Automatic',
|
||||
@@ -65,6 +66,7 @@ const en = {
|
||||
resetHdmi: 'Reset HDMI'
|
||||
},
|
||||
keyboard: {
|
||||
title: 'Keyboard',
|
||||
paste: 'Paste',
|
||||
tips: 'Only standard keyboard letters and symbols are supported',
|
||||
placeholder: 'Please input',
|
||||
@@ -73,6 +75,7 @@ const en = {
|
||||
ctrlaltdel: 'Ctrl+Alt+Del'
|
||||
},
|
||||
mouse: {
|
||||
title: 'Mouse',
|
||||
default: 'Default cursor',
|
||||
pointer: 'Pointer cursor',
|
||||
cell: 'Cell cursor',
|
||||
@@ -86,7 +89,7 @@ const en = {
|
||||
resetHid: 'Reset HID'
|
||||
},
|
||||
image: {
|
||||
title: 'Image',
|
||||
title: 'Images',
|
||||
loading: 'Loading...',
|
||||
empty: 'Nothing Found',
|
||||
cdrom: 'Mount the image in CD-ROM mode',
|
||||
@@ -110,7 +113,7 @@ const en = {
|
||||
}
|
||||
},
|
||||
script: {
|
||||
title: 'Script',
|
||||
title: 'Scripts',
|
||||
upload: 'Upload',
|
||||
run: 'Run',
|
||||
runBackground: 'Run Background',
|
||||
@@ -139,7 +142,7 @@ const en = {
|
||||
ok: 'Ok'
|
||||
},
|
||||
download: {
|
||||
title: 'Download Image',
|
||||
title: 'Image Downloader',
|
||||
input: 'Please enter a remote image URL',
|
||||
ok: 'Ok',
|
||||
disabled: '/data partition is RO, so we cannot download the image'
|
||||
@@ -257,8 +260,15 @@ const en = {
|
||||
}
|
||||
},
|
||||
error: {
|
||||
title: "We've ran into an issue",
|
||||
refresh: 'Refresh'
|
||||
title: 'We\'ve ran into an issue',
|
||||
refresh: 'Refresh',
|
||||
},
|
||||
fullscreen: {
|
||||
toggle: 'Toggle Fullscreen',
|
||||
},
|
||||
menu: {
|
||||
collapse: 'Collapse Menu',
|
||||
expand: 'Expand Menu',
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ChangeEvent, useEffect, useRef, useState } from 'react';
|
||||
import { Button, Divider, Input, Popover } from 'antd';
|
||||
import { Button, Divider, Input, Popover, Tooltip } from 'antd';
|
||||
import type { InputRef } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import { useSetAtom } from 'jotai';
|
||||
@@ -21,6 +21,9 @@ export const DownloadImage = () => {
|
||||
const [diskEnabled, setDiskEnabled] = useState(false);
|
||||
const [popoverKey, setPopoverKey] = useState(0);
|
||||
|
||||
const tooltip = t('download.title');
|
||||
const [tooltipValue, setTooltipValue] = useState(tooltip);
|
||||
|
||||
const inputRef = useRef<InputRef>(null);
|
||||
|
||||
const intervalId = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||
@@ -165,11 +168,16 @@ export const DownloadImage = () => {
|
||||
trigger="click"
|
||||
arrow={false}
|
||||
open={isPopoverOpen}
|
||||
onOpenChange={handleOpenChange}
|
||||
onOpenChange={(visible) => {
|
||||
handleOpenChange(visible);
|
||||
setTooltipValue(visible ? '' : tooltip);
|
||||
}}
|
||||
>
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<DownloadIcon size={18} />
|
||||
</div>
|
||||
<Tooltip title={tooltipValue} placement="bottom">
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<DownloadIcon size={18} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { MaximizeIcon, MinimizeIcon } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Tooltip } from 'antd';
|
||||
|
||||
export const Fullscreen = () => {
|
||||
const { t } = useTranslation();
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
const [tooltipValue, setTooltipValue] = useState(t('fullscreen.toggle'));
|
||||
|
||||
useEffect(() => {
|
||||
function onFullscreenChange() {
|
||||
@@ -27,11 +31,13 @@ export const Fullscreen = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="hidden h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white sm:flex"
|
||||
onClick={handleFullscreen}
|
||||
>
|
||||
{isFullscreen ? <MinimizeIcon size={18} /> : <MaximizeIcon size={18} />}
|
||||
</div>
|
||||
<Tooltip title={tooltipValue} placement="bottom">
|
||||
<div
|
||||
className="hidden h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white sm:flex"
|
||||
onClick={handleFullscreen}
|
||||
>
|
||||
{isFullscreen ? <MinimizeIcon size={18} /> : <MaximizeIcon size={18} />}
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -18,6 +18,9 @@ export const Image = () => {
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
const [cdrom, setCdrom] = useState(false);
|
||||
|
||||
const tooltip = t('image.title');
|
||||
const [tooltipValue, setTooltipValue] = useState(tooltip);
|
||||
|
||||
useEffect(() => {
|
||||
getMountedImage().then((rsp) => {
|
||||
if (rsp.code !== 0) return;
|
||||
@@ -60,16 +63,21 @@ export const Image = () => {
|
||||
trigger="click"
|
||||
arrow={false}
|
||||
open={isPopoverOpen}
|
||||
onOpenChange={setIsPopoverOpen}
|
||||
onOpenChange={(visible) => {
|
||||
setIsPopoverOpen(visible);
|
||||
setTooltipValue(visible ? '' : tooltip);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
'flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded hover:bg-neutral-700',
|
||||
isMounted ? 'text-blue-500' : 'text-neutral-300 hover:text-white'
|
||||
)}
|
||||
>
|
||||
<DiscIcon size={18} />
|
||||
</div>
|
||||
<Tooltip title={tooltipValue} placement="bottom">
|
||||
<div
|
||||
className={clsx(
|
||||
'flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded hover:bg-neutral-700',
|
||||
isMounted ? 'text-blue-500' : 'text-neutral-300 hover:text-white'
|
||||
)}
|
||||
>
|
||||
<DiscIcon size={18} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Divider } from 'antd';
|
||||
import { Divider, Tooltip } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import { useAtom } from 'jotai';
|
||||
import { MenuIcon, XIcon } from 'lucide-react';
|
||||
@@ -18,6 +18,7 @@ import { Script } from './script';
|
||||
import { Settings } from './settings';
|
||||
import { Terminal } from './terminal';
|
||||
import { Wol } from './wol';
|
||||
import { t } from 'i18next';
|
||||
|
||||
export const Menu = () => {
|
||||
const [menuDisabledItems, setMenuDisabledItems] = useAtom(menuDisabledItemsAtom);
|
||||
@@ -67,21 +68,25 @@ export const Menu = () => {
|
||||
<Settings />
|
||||
<Fullscreen />
|
||||
|
||||
<div
|
||||
className="mr-1 flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white"
|
||||
onClick={() => setIsMenuOpen((o) => !o)}
|
||||
>
|
||||
<XIcon size={20} />
|
||||
</div>
|
||||
<Tooltip title={t('menu.collapse')} placement="bottom">
|
||||
<div
|
||||
className="mr-1 flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white"
|
||||
onClick={() => setIsMenuOpen((o) => !o)}
|
||||
>
|
||||
<XIcon size={20} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{!isMenuOpen && (
|
||||
<div
|
||||
className="flex h-[30px] w-[50px] items-center justify-center rounded bg-neutral-800/50 text-white/50 hover:bg-neutral-800 hover:text-white"
|
||||
onClick={() => setIsMenuOpen((o) => !o)}
|
||||
>
|
||||
<MenuIcon />
|
||||
</div>
|
||||
<Tooltip title={t('menu.expand')} placement="bottom">
|
||||
<div
|
||||
className="flex h-[30px] w-[50px] items-center justify-center rounded bg-neutral-800/50 text-white/50 hover:bg-neutral-800 hover:text-white"
|
||||
onClick={() => setIsMenuOpen((o) => !o)}
|
||||
>
|
||||
<MenuIcon />
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
import { useState } from 'react';
|
||||
import { Popover } from 'antd';
|
||||
import { Popover, Tooltip } from 'antd';
|
||||
import { KeyboardIcon } from 'lucide-react';
|
||||
import { t } from 'i18next';
|
||||
|
||||
import { Paste } from './paste.tsx';
|
||||
import { VirtualKeyboard } from './virtual-keyboard.tsx';
|
||||
import { CtrlAltDel } from './ctrl-alt-del.tsx';
|
||||
|
||||
|
||||
export const Keyboard = () => {
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||
|
||||
const tooltip = t('keyboard.title')
|
||||
const [tooltipValue, setTooltipValue] = useState(tooltip);
|
||||
|
||||
const content = (
|
||||
<>
|
||||
<Paste setIsPopoverOpen={setIsPopoverOpen} />
|
||||
@@ -24,11 +29,16 @@ export const Keyboard = () => {
|
||||
trigger="click"
|
||||
arrow={false}
|
||||
open={isPopoverOpen}
|
||||
onOpenChange={setIsPopoverOpen}
|
||||
onOpenChange={(visible) => {
|
||||
setIsPopoverOpen(visible);
|
||||
setTooltipValue(visible ? "" : tooltip);
|
||||
}}
|
||||
>
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<KeyboardIcon size={18} />
|
||||
</div>
|
||||
<Tooltip title={tooltipValue} placement="bottom">
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<KeyboardIcon size={18} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Divider, Popover } from 'antd';
|
||||
import { Divider, Popover, Tooltip } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import { useAtom } from 'jotai';
|
||||
import {
|
||||
@@ -27,6 +27,9 @@ export const Mouse = () => {
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||
const [isResetting, setIsResetting] = useState(false);
|
||||
|
||||
const tooltip = t('mouse.title');
|
||||
const [tooltipValue, setTooltipValue] = useState(tooltip);
|
||||
|
||||
const mouseStyles = [
|
||||
{ name: t('mouse.default'), icon: <MousePointerIcon size={14} />, value: 'cursor-default' },
|
||||
{ name: t('mouse.grab'), icon: <HandIcon size={14} />, value: 'cursor-grab' },
|
||||
@@ -154,11 +157,16 @@ export const Mouse = () => {
|
||||
trigger="click"
|
||||
arrow={false}
|
||||
open={isPopoverOpen}
|
||||
onOpenChange={setIsPopoverOpen}
|
||||
onOpenChange={(visible) => {
|
||||
setIsPopoverOpen(visible);
|
||||
setTooltipValue(visible ? "" : tooltip);
|
||||
}}
|
||||
>
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<MouseIcon size={18} />
|
||||
</div>
|
||||
<Tooltip title={tooltipValue}>
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<MouseIcon size={18} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Popover, Slider } from 'antd';
|
||||
import { Popover, Slider, Tooltip } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import { CirclePowerIcon, LoaderCircleIcon, PowerIcon, RotateCcwIcon } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -13,6 +13,9 @@ export const Power = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [powerDuration, setPowerDuration] = useState(8);
|
||||
|
||||
const tooltip = t('power.title');
|
||||
const [tooltipValue, setTooltipValue] = useState(tooltip);
|
||||
|
||||
useEffect(() => {
|
||||
getLed();
|
||||
const interval = setInterval(getLed, 5000);
|
||||
@@ -95,19 +98,24 @@ export const Power = () => {
|
||||
trigger="click"
|
||||
arrow={false}
|
||||
open={isPopoverOpen}
|
||||
onOpenChange={setIsPopoverOpen}
|
||||
onOpenChange={(visible) => {
|
||||
setIsPopoverOpen(visible);
|
||||
setTooltipValue(visible ? '' : tooltip);
|
||||
}}
|
||||
>
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded hover:bg-neutral-700 hover:text-white">
|
||||
<div
|
||||
className={clsx('h-[18px] w-[18px]', isPowerOn ? 'text-green-600' : 'text-neutral-500')}
|
||||
>
|
||||
{isLoading ? (
|
||||
<LoaderCircleIcon className="animate-spin" size={18} />
|
||||
) : (
|
||||
<PowerIcon size={18} />
|
||||
)}
|
||||
<Tooltip title={tooltipValue} placement="bottom">
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded hover:bg-neutral-700 hover:text-white">
|
||||
<div
|
||||
className={clsx('h-[18px] w-[18px]', isPowerOn ? 'text-green-600' : 'text-neutral-500')}
|
||||
>
|
||||
{isLoading ? (
|
||||
<LoaderCircleIcon className="animate-spin" size={18} />
|
||||
) : (
|
||||
<PowerIcon size={18} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Popover } from 'antd';
|
||||
import { Popover, Tooltip } from 'antd';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { MonitorIcon } from 'lucide-react';
|
||||
|
||||
@@ -14,6 +14,7 @@ import { Quality } from './quality';
|
||||
import { Reset } from './reset.tsx';
|
||||
import { Resolution } from './resolution';
|
||||
import { VideoMode } from './video-mode.tsx';
|
||||
import { t } from 'i18next';
|
||||
|
||||
export const Screen = () => {
|
||||
const videoMode = useAtomValue(videoModeAtom);
|
||||
@@ -21,10 +22,12 @@ export const Screen = () => {
|
||||
const [fps, setFps] = useState(30);
|
||||
const [quality, setQuality] = useState(2);
|
||||
|
||||
const tooltip = t('screen.title');
|
||||
const [tooltipValue, setTooltipValue] = useState(tooltip);
|
||||
|
||||
useEffect(() => {
|
||||
updateScreen('type', videoMode === 'mjpeg' ? 0 : 1);
|
||||
updateScreen('resolution', resolution!.height);
|
||||
|
||||
updateQuality();
|
||||
updateFps();
|
||||
}, []);
|
||||
@@ -69,10 +72,13 @@ export const Screen = () => {
|
||||
placement="bottomLeft"
|
||||
trigger="click"
|
||||
arrow={false}
|
||||
onOpenChange={(visible) => setTooltipValue(visible ? '' : tooltip)}
|
||||
>
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<MonitorIcon size={18} />
|
||||
</div>
|
||||
<Tooltip title={tooltipValue}>
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<MonitorIcon size={18} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ChangeEvent, useRef, useState } from 'react';
|
||||
import { UploadOutlined } from '@ant-design/icons';
|
||||
import { Button, Divider, Popconfirm, Popover } from 'antd';
|
||||
import { Button, Divider, Popconfirm, Popover, Tooltip } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import { ChevronRightIcon, FileJsonIcon } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -22,6 +22,9 @@ export const Script = () => {
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const inputRef = useRef<any>(null);
|
||||
|
||||
const tooltip = t('script.title');
|
||||
const [tooltipValue, setTooltipValue] = useState(tooltip);
|
||||
|
||||
function handleOpenChange(open: boolean) {
|
||||
if (open) {
|
||||
getScripts();
|
||||
@@ -194,11 +197,16 @@ export const Script = () => {
|
||||
trigger="click"
|
||||
arrow={false}
|
||||
open={isPopoverOpen}
|
||||
onOpenChange={handleOpenChange}
|
||||
onOpenChange={(visible) => {
|
||||
handleOpenChange(visible);
|
||||
setTooltipValue(visible ? '' : tooltip);
|
||||
}}
|
||||
>
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<FileJsonIcon size={18} />
|
||||
</div>
|
||||
<Tooltip title={tooltipValue} placement="bottom">
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<FileJsonIcon size={18} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
|
||||
{isRunning && <Run script={currentScript} setIsRunning={setIsRunning} />}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Badge, Modal } from 'antd';
|
||||
import { Badge, Modal, Tooltip } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import {
|
||||
BadgeInfoIcon,
|
||||
@@ -32,6 +32,9 @@ export const Settings = () => {
|
||||
|
||||
const [isUpdateAvailable, setIsUpdateAvailable] = useState(false);
|
||||
|
||||
const tooltip = t('settings.title');
|
||||
const [tooltipValue, setTooltipValue] = useState(tooltip);
|
||||
|
||||
const tabs = [
|
||||
{ id: 'about', icon: <BadgeInfoIcon size={16} />, component: <About /> },
|
||||
{ id: 'appearance', icon: <PaletteIcon size={16} />, component: <Appearance /> },
|
||||
@@ -92,16 +95,18 @@ export const Settings = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-white hover:bg-neutral-700"
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
>
|
||||
<Badge dot={isUpdateAvailable} color="blue" offset={[0, 2]}>
|
||||
<div className="pt-[3px]">
|
||||
<SettingsIcon size={18} />
|
||||
</div>
|
||||
</Badge>
|
||||
</div>
|
||||
<Tooltip title={tooltipValue} placement="bottom">
|
||||
<div
|
||||
className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-white hover:bg-neutral-700"
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
>
|
||||
<Badge dot={isUpdateAvailable} color="blue" offset={[0, 2]}>
|
||||
<div className="pt-[3px]">
|
||||
<SettingsIcon size={18} />
|
||||
</div>
|
||||
</Badge>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
<Modal
|
||||
open={isModalOpen}
|
||||
@@ -110,6 +115,7 @@ export const Settings = () => {
|
||||
destroyOnClose={true}
|
||||
styles={{ content: { padding: 0 } }}
|
||||
onCancel={closeModal}
|
||||
afterOpenChange={(visible) => setTooltipValue(visible ? '' : tooltip)}
|
||||
>
|
||||
<div className="flex min-h-[500px] rounded-lg outline outline-1 outline-neutral-700">
|
||||
<div className="flex flex-col space-y-0.5 rounded-l-lg bg-neutral-800 py-5 sm:w-1/5 sm:px-2">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Divider, Popover } from 'antd';
|
||||
import { Divider, Popover, Tooltip } from 'antd';
|
||||
import { SquareTerminalIcon } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -10,6 +10,9 @@ export const Terminal = () => {
|
||||
const { t } = useTranslation();
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||
|
||||
const tooltip = t('terminal.title');
|
||||
const [tooltipValue, setTooltipValue] = useState(tooltip);
|
||||
|
||||
const content = (
|
||||
<div className="min-w-[200px]">
|
||||
<div className="flex items-center justify-between px-1">
|
||||
@@ -30,11 +33,16 @@ export const Terminal = () => {
|
||||
trigger="click"
|
||||
arrow={false}
|
||||
open={isPopoverOpen}
|
||||
onOpenChange={setIsPopoverOpen}
|
||||
onOpenChange={(visible) => {
|
||||
setIsPopoverOpen(visible);
|
||||
setTooltipValue(visible ? '' : tooltip);
|
||||
}}
|
||||
>
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<SquareTerminalIcon size={18} />
|
||||
</div>
|
||||
<Tooltip title={tooltipValue} placement="bottom">
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<SquareTerminalIcon size={18} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ChangeEvent, useRef, useState } from 'react';
|
||||
import { Button, Divider, Input, List, Popover } from 'antd';
|
||||
import { Button, Divider, Input, List, Popover, Tooltip } from 'antd';
|
||||
import type { InputRef } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import { useSetAtom } from 'jotai';
|
||||
@@ -22,6 +22,9 @@ export const Wol = () => {
|
||||
const [status, setStatus] = useState('');
|
||||
const [log, setLog] = useState('');
|
||||
|
||||
const tooltip = t('wol.title');
|
||||
const [tooltipValue, setTooltipValue] = useState(tooltip);
|
||||
|
||||
const [macList, setMacList] = useState<string[]>([]);
|
||||
|
||||
const inputRef = useRef<InputRef>(null);
|
||||
@@ -153,11 +156,16 @@ export const Wol = () => {
|
||||
trigger="click"
|
||||
arrow={false}
|
||||
open={isPopoverOpen}
|
||||
onOpenChange={handleOpenChange}
|
||||
onOpenChange={(visible) => {
|
||||
handleOpenChange(visible);
|
||||
setTooltipValue(visible ? '' : tooltip);
|
||||
}}
|
||||
>
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<NetworkIcon size={16} />
|
||||
</div>
|
||||
<Tooltip title={tooltipValue} placement="bottom">
|
||||
<div className="flex h-[30px] w-[30px] cursor-pointer items-center justify-center rounded text-neutral-300 hover:bg-neutral-700 hover:text-white">
|
||||
<NetworkIcon size={16} />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user