import { usePtzCommand } from "@/api/ws"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; import useKeyboardListener from "@/hooks/use-keyboard-listener"; import { CameraPtzInfo } from "@/types/ptz"; import React, { useCallback } from "react"; import { isDesktop, isMobile } from "react-device-detect"; import { BsThreeDotsVertical } from "react-icons/bs"; import { FaAngleDown, FaAngleLeft, FaAngleRight, FaAngleUp, } from "react-icons/fa"; import { TbViewfinder } from "react-icons/tb"; import { MdCenterFocusStrong, MdCenterFocusWeak, MdZoomIn, MdZoomOut, } from "react-icons/md"; import useSWR from "swr"; import { cn } from "@/lib/utils"; import { useTranslation } from "react-i18next"; import TooltipButton from "@/views/button/TooltipButton"; export default function PtzControlPanel({ className, camera, enabled, clickOverlay, setClickOverlay, }: { className?: string; camera: string; enabled: boolean; clickOverlay: boolean; setClickOverlay: React.Dispatch>; }) { const { t } = useTranslation(["views/live"]); const { data: ptz } = useSWR( enabled ? `${camera}/ptz/info` : null, ); const { send: sendPtz } = usePtzCommand(camera); const onStop = useCallback( (e: React.SyntheticEvent) => { e.preventDefault(); sendPtz("STOP"); }, [sendPtz], ); useKeyboardListener( [ "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "+", "-", "1", "2", "3", "4", "5", "6", "7", "8", "9", ], (key, modifiers) => { if (modifiers.repeat || !key) { return; } if (["1", "2", "3", "4", "5", "6", "7", "8", "9"].includes(key)) { const presetNumber = parseInt(key); if ( ptz && (ptz.presets?.length ?? 0) > 0 && presetNumber <= ptz.presets.length ) { sendPtz(`preset_${ptz.presets[presetNumber - 1]}`); } return; } if (!modifiers.down) { sendPtz("STOP"); return; } switch (key) { case "ArrowLeft": sendPtz("MOVE_LEFT"); break; case "ArrowRight": sendPtz("MOVE_RIGHT"); break; case "ArrowUp": sendPtz("MOVE_UP"); break; case "ArrowDown": sendPtz("MOVE_DOWN"); break; case "+": sendPtz(modifiers.shift ? "FOCUS_IN" : "ZOOM_IN"); break; case "-": sendPtz(modifiers.shift ? "FOCUS_OUT" : "ZOOM_OUT"); break; } }, ); return (
{ptz?.features?.includes("pt") && ( <> { e.preventDefault(); sendPtz("MOVE_LEFT"); }} onTouchStart={(e) => { e.preventDefault(); sendPtz("MOVE_LEFT"); }} onMouseUp={onStop} onTouchEnd={onStop} > { e.preventDefault(); sendPtz("MOVE_UP"); }} onTouchStart={(e) => { e.preventDefault(); sendPtz("MOVE_UP"); }} onMouseUp={onStop} onTouchEnd={onStop} > { e.preventDefault(); sendPtz("MOVE_DOWN"); }} onTouchStart={(e) => { e.preventDefault(); sendPtz("MOVE_DOWN"); }} onMouseUp={onStop} onTouchEnd={onStop} > { e.preventDefault(); sendPtz("MOVE_RIGHT"); }} onTouchStart={(e) => { e.preventDefault(); sendPtz("MOVE_RIGHT"); }} onMouseUp={onStop} onTouchEnd={onStop} > )} {ptz?.features?.includes("zoom") && ( <> { e.preventDefault(); sendPtz("ZOOM_IN"); }} onTouchStart={(e) => { e.preventDefault(); sendPtz("ZOOM_IN"); }} onMouseUp={onStop} onTouchEnd={onStop} > { e.preventDefault(); sendPtz("ZOOM_OUT"); }} onTouchStart={(e) => { e.preventDefault(); sendPtz("ZOOM_OUT"); }} onMouseUp={onStop} onTouchEnd={onStop} > )} {ptz?.features?.includes("focus") && ( <> { e.preventDefault(); sendPtz("FOCUS_IN"); }} onTouchStart={(e) => { e.preventDefault(); sendPtz("FOCUS_IN"); }} onMouseUp={onStop} onTouchEnd={onStop} > { e.preventDefault(); sendPtz("FOCUS_OUT"); }} onTouchStart={(e) => { e.preventDefault(); sendPtz("FOCUS_OUT"); }} onMouseUp={onStop} onTouchEnd={onStop} > )} {ptz?.features?.includes("pt-r-fov") && (

{clickOverlay ? t("ptz.move.clickMove.disable") : t("ptz.move.clickMove.enable")}

)} {(ptz?.presets?.length ?? 0) > 0 && (

{t("ptz.presets")}

e.preventDefault()} > {ptz?.presets.map((preset) => ( sendPtz(`preset_${preset}`)} > {preset} ))}
)}
); }