import { MdOutlineContentPasteGo, MdVolumeOff, MdVolumeUp, MdGraphicEq } from "react-icons/md"; import { LuCable, LuHardDrive, LuMaximize, LuSettings, LuSignal } from "react-icons/lu"; import { FaKeyboard } from "react-icons/fa6"; import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react"; import { Fragment, useCallback, useEffect, useRef, useState } from "react"; import { CommandLineIcon } from "@heroicons/react/20/solid"; import { Button } from "@components/Button"; import { useHidStore, useMountMediaStore, useSettingsStore, useUiStore, } from "@/hooks/stores"; import Container from "@components/Container"; import { cx } from "@/cva.config"; import PasteModal from "@/components/popovers/PasteModal"; import WakeOnLanModal from "@/components/popovers/WakeOnLan/Index"; import MountPopopover from "@/components/popovers/MountPopover"; import ExtensionPopover from "@/components/popovers/ExtensionPopover"; import AudioControlPopover from "@/components/popovers/AudioControlPopover"; import { useDeviceUiNavigation } from "@/hooks/useAppNavigation"; import api from "@/api"; export default function Actionbar({ requestFullscreen, }: { requestFullscreen: () => Promise; }) { const { navigateTo } = useDeviceUiNavigation(); const virtualKeyboard = useHidStore(state => state.isVirtualKeyboardEnabled); const setVirtualKeyboard = useHidStore(state => state.setVirtualKeyboardEnabled); const toggleSidebarView = useUiStore(state => state.toggleSidebarView); const setDisableFocusTrap = useUiStore(state => state.setDisableVideoFocusTrap); const terminalType = useUiStore(state => state.terminalType); const setTerminalType = useUiStore(state => state.setTerminalType); const remoteVirtualMediaState = useMountMediaStore( state => state.remoteVirtualMediaState, ); const developerMode = useSettingsStore(state => state.developerMode); // This is the only way to get a reliable state change for the popover // at time of writing this there is no mount, or unmount event for the popover const isOpen = useRef(false); const checkIfStateChanged = useCallback( (open: boolean) => { if (open !== isOpen.current) { isOpen.current = open; if (!open) { setTimeout(() => { setDisableFocusTrap(false); console.log("Popover is closing. Returning focus trap to video"); }, 0); } } }, [setDisableFocusTrap], ); // Mute/unmute state for button display const [isMuted, setIsMuted] = useState(false); useEffect(() => { api.GET("/audio/mute").then(async resp => { if (resp.ok) { const data = await resp.json(); setIsMuted(!!data.muted); } }); // Refresh mute state periodically for button display const interval = setInterval(async () => { const resp = await api.GET("/audio/mute"); if (resp.ok) { const data = await resp.json(); setIsMuted(!!data.muted); } }, 1000); return () => clearInterval(interval); }, []); return (
e.stopPropagation()} onKeyDown={e => e.stopPropagation()} className="flex flex-wrap items-center justify-between gap-x-4 gap-y-2 py-1.5" >
{developerMode && (
); }