mirror of
https://github.com/luckfox-eng29/kvm.git
synced 2026-05-26 08:05:08 +02:00
feat(usb): add UsbStatusPanel component and integrate it into BottomBarPC and MobileDesktop
Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import React, { useCallback } from "react";
|
||||
import { useReactAt } from "i18n-auto-extractor/react";
|
||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||
import notifications from "@/notifications";
|
||||
import { dark_bg2_style, dark_bd_style, dark_line_style, dark_bg_style_fun } from "@/layout/theme_color";
|
||||
import { useThemeSettings } from "@routes/login_page/useLocalAuth";
|
||||
import { isMobile } from "react-device-detect";
|
||||
|
||||
const UsbStatusPanel: React.FC = () => {
|
||||
const { $at } = useReactAt();
|
||||
const { isDark } = useThemeSettings();
|
||||
const [send] = useJsonRpc();
|
||||
|
||||
const handleReinitializeUsbGadget = useCallback(() => {
|
||||
send("reinitializeUsbGadget", {}, resp => {
|
||||
if ("error" in resp) {
|
||||
notifications.error(
|
||||
`Failed to reinitialize USB gadget: ${resp.error.data || "Unknown error"}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
notifications.success("USB Gadget reinitialized successfully");
|
||||
});
|
||||
}, [send]);
|
||||
|
||||
if (isMobile) {
|
||||
return (
|
||||
<div className={`w-full h-full flex flex-col ${dark_bg_style_fun(isDark)} p-4`}>
|
||||
<div className={`flex flex-col w-full mx-auto ${isDark ? 'text-white' : 'text-black'}`}>
|
||||
<div
|
||||
className={`
|
||||
flex items-center justify-between py-4 w-full
|
||||
cursor-pointer transition-all duration-200 ease-in-out
|
||||
${isDark ? 'text-white' : 'text-black'}
|
||||
`}
|
||||
onClick={handleReinitializeUsbGadget}
|
||||
>
|
||||
<span className="font-normal tracking-[0.5px]">
|
||||
{$at("Reinitialize USB Gadget")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)' }}
|
||||
className={`p-1.5 w-[200px] rounded font-sans ${dark_bg2_style} border ${dark_bd_style}`}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<div
|
||||
style={{
|
||||
padding: '8px 12px',
|
||||
cursor: 'pointer',
|
||||
backgroundColor: 'transparent',
|
||||
color: isDark ? 'rgba(255, 255, 255, 0.85)' : 'rgba(0, 0, 0, 0.85)',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
borderRadius: '4px',
|
||||
}}
|
||||
onClick={handleReinitializeUsbGadget}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.backgroundColor = isDark ? 'rgba(255, 255, 255, 0.08)' : 'rgba(0, 0, 0, 0.04)';
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.backgroundColor = 'transparent';
|
||||
}}
|
||||
>
|
||||
<span style={{ fontSize: "12px" }}>{$at("Reinitialize USB Gadget")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UsbStatusPanel;
|
||||
@@ -176,11 +176,13 @@ export default function BottomBarMobile() {
|
||||
text={$at("HDMI")}
|
||||
isActive={!!peerConnectionState}
|
||||
/>
|
||||
<ConnectionStatusButton
|
||||
icon={usbState === "configured" ? <Usb2SVG /> : <UsbSVG />}
|
||||
text={$at("USB")}
|
||||
isActive={usbState === "configured"}
|
||||
/>
|
||||
<div onClick={() => toggleSidebarView("UsbStatusPanel")}>
|
||||
<ConnectionStatusButton
|
||||
icon={usbState === "configured" ? <Usb2SVG /> : <UsbSVG />}
|
||||
text={$at("USB")}
|
||||
isActive={usbState === "configured"}
|
||||
/>
|
||||
</div>
|
||||
<VpnStatusButton
|
||||
text={$at("TailScale")}
|
||||
peerState={peerConnectionState}
|
||||
|
||||
@@ -32,6 +32,7 @@ import BottomPopoverButton from "@components/PopoverButton";
|
||||
import MousePanel from "@components/MousePanel";
|
||||
import KeyboardPanel from "@/layout/components_bottom/keyboard/KeyboardPanel";
|
||||
import UsbEpModeSelect from "@/layout/components_bottom/usbepmode/UsbEpModeSelect";
|
||||
import UsbStatusPanel from "@/layout/components_bottom/usb_status/UsbStatusPanel";
|
||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||
import { dark_bg2_style, selected_bt_bg } from "@/layout/theme_color";
|
||||
import { useThemeSettings } from "@routes/login_page/useLocalAuth";
|
||||
@@ -115,10 +116,12 @@ export default function BottomBarPC() {
|
||||
isActive={hdmiState === "ready"}
|
||||
/>
|
||||
|
||||
<ConnectionStatusButton
|
||||
icon={usbState === "configured" ? <Usb2SVG fontSize={16} /> : <UsbSVG fontSize={16} />}
|
||||
text={$at("USB")}
|
||||
isActive={usbState === "configured"}
|
||||
<BottomPopoverButton
|
||||
buttonIconNode={usbState === "configured" ? <Usb2SVG fontSize={16} /> : <UsbSVG fontSize={16} />}
|
||||
buttonText={$at("USB")}
|
||||
style={{ color: usbState === "configured" ? "rgba(0, 205, 27, 1)" : "inherit" }}
|
||||
panelContent={<UsbStatusPanel />}
|
||||
align="left"
|
||||
/>
|
||||
|
||||
<VpnStatusButton
|
||||
|
||||
@@ -37,6 +37,7 @@ import SettingsMacros from "@/layout/components_side/Macros";
|
||||
import { useTouchZoom } from "@/layout/core/desktop/hooks/useTouchZoom";
|
||||
import { usePasteHandler } from "@/layout/core/desktop/hooks/usePasteHandler";
|
||||
import UsbEpModeSelect from "@/layout/components_bottom/usbepmode/UsbEpModeSelect";
|
||||
import UsbStatusPanel from "@/layout/components_bottom/usb_status/UsbStatusPanel";
|
||||
import VirtualMediaSource from "@/layout/components_side/VirtualMediaSource";
|
||||
import { useJsonRpc } from "@/hooks/useJsonRpc";
|
||||
import OcrOverlay from "@components/OcrOverlay";
|
||||
@@ -423,6 +424,11 @@ export default function MobileDesktop({ isFullscreen }: { isFullscreen?: number
|
||||
drawerRender={() => (<UsbEpModeSelect/>)}
|
||||
className={"px-[20px]"}
|
||||
/>
|
||||
<EnhancedDrawer
|
||||
targetView={"UsbStatusPanel"}
|
||||
placement={"bottom"}
|
||||
drawerRender={() => (<UsbStatusPanel/>)}
|
||||
/>
|
||||
|
||||
<EnhancedDrawer
|
||||
title={$at("Virtual Media Source")}
|
||||
@@ -686,7 +692,7 @@ export default function MobileDesktop({ isFullscreen }: { isFullscreen?: number
|
||||
"flex h-8 w-8 items-center justify-center rounded-full text-white text-xs active:scale-90 transition-transform duration-100",
|
||||
isDark ? "bg-gray-500/70" : "bg-black/30",
|
||||
)}
|
||||
onClick={() => send("wheelReport", { wheelY: 1 })}
|
||||
onClick={() => { send("wheelReport", { wheelY: 1 }); }}
|
||||
>
|
||||
▲
|
||||
</div>
|
||||
@@ -712,7 +718,7 @@ export default function MobileDesktop({ isFullscreen }: { isFullscreen?: number
|
||||
"mt-1 flex h-8 w-8 items-center justify-center rounded-full text-white text-xs active:scale-90 transition-transform duration-100",
|
||||
isDark ? "bg-gray-500/70" : "bg-black/30",
|
||||
)}
|
||||
onClick={() => send("wheelReport", { wheelY: -1 })}
|
||||
onClick={() => { send("wheelReport", { wheelY: -1 }); }}
|
||||
>
|
||||
▼
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user