import { useCallback, useEffect } from 'react';
import { useControlActions, useControlSelector } from '../../controls/index.js';
import { triggerTouchHaptic } from '../../lib/touchHaptics.js';
import CardFrame from '../../components/CardFrame/index.jsx';
import ControlPadPanel from '../../components/MobileControls/ControlPadPanel.jsx';
import GPIOToggleControl from '../../components/GPIOToggleControl/index.jsx';
import KeyPill from '../../components/vip/VipAudioUploadCard/KeyPill.jsx';
import ControlHint from '../../components/ControlHint/index.jsx';
function PtzLightingControls({ disabled = false }) {
const { setHeadlight, setLaser } = useControlActions();
const { spotlightOn, irMode, pending } = useControlSelector((control) => control.ptzControls.lighting);
const canControl = useControlSelector((control) => control.ptzControls.isActive);
const blocked = disabled || !canControl;
const cycleIr = () => {
triggerTouchHaptic('button');
setLaser();
};
return (
);
}
function PtzMobileZoomButtons({ disabled = false }) {
const { setCameraAxisIntent } = useControlActions();
const stopZoom = useCallback(() => {
/*
Zero only releases the zoom axis. The PTZ adapter combines it with any
pan/tilt direction still held on the movement pad, so lifting one finger
cannot erase the other finger's intent.
*/
setCameraAxisIntent(0);
}, [setCameraAxisIntent]);
const startZoom = useCallback(
(direction) => (event) => {
/*
Publish held state once. The adapter owns the single motion heartbeat,
so this button no longer creates a second interval whose queued callback
could run after pointerup and restart zoom.
*/
event.preventDefault();
if (disabled) return;
triggerTouchHaptic('button');
event.currentTarget.setPointerCapture?.(event.pointerId);
setCameraAxisIntent(direction);
},
[disabled, setCameraAxisIntent],
);
const stopFromPointer = useCallback(
(event) => {
event?.preventDefault?.();
if (disabled) return;
stopZoom();
},
[disabled, stopZoom],
);
useEffect(
() => () => {
/*
A touch surface can unmount during orientation changes or fullscreen
close while a pointer is still down. Explicitly clear zoom here because
an unmounted DOM node cannot deliver its pointerup/pointercancel event.
*/
setCameraAxisIntent(0);
},
[setCameraAxisIntent],
);
return (
{/*
Reuse the rover control pad so touch intent still enters the normal
control system. The PTZ adapter translates that same drive vector into
pan/tilt commands only while this user is the PTZ operator.
*/}