mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 17:40:46 -04:00
stateful night vision rework
This commit is contained in:
@@ -312,10 +312,23 @@ export function ControlSystemProvider({ children }) {
|
||||
[pipeline],
|
||||
);
|
||||
|
||||
const setNightVision = useCallback(
|
||||
(nightVisionOn) => {
|
||||
if (!pipeline.nightVision) return;
|
||||
if (typeof nightVisionOn === 'boolean') {
|
||||
const action = nightVisionOn ? 'off' : 'on';
|
||||
pipeline.sendNightVision(action);
|
||||
} else {
|
||||
pipeline.sendNightVision('toggle');
|
||||
}
|
||||
recordControlIntent();
|
||||
},
|
||||
[pipeline, recordControlIntent],
|
||||
);
|
||||
|
||||
const toggleNightVision = useCallback(() => {
|
||||
pipeline.sendNightVision('toggle');
|
||||
recordControlIntent();
|
||||
}, [pipeline, recordControlIntent]);
|
||||
setNightVision();
|
||||
}, [setNightVision]);
|
||||
|
||||
const setSongNote = useCallback(
|
||||
(note) => {
|
||||
@@ -354,6 +367,7 @@ export function ControlSystemProvider({ children }) {
|
||||
stopAllMotion,
|
||||
sendOiCommand,
|
||||
setSensorStream,
|
||||
setNightVision,
|
||||
toggleNightVision,
|
||||
updateKeyBinding,
|
||||
resetKeyBindings,
|
||||
@@ -376,6 +390,7 @@ export function ControlSystemProvider({ children }) {
|
||||
stopAllMotion,
|
||||
sendOiCommand,
|
||||
setSensorStream,
|
||||
setNightVision,
|
||||
toggleNightVision,
|
||||
updateKeyBinding,
|
||||
resetKeyBindings,
|
||||
|
||||
@@ -32,6 +32,8 @@ export function useCommandPipeline(options = {}) {
|
||||
return rosterEntry.nightVision;
|
||||
}, [rosterEntry]);
|
||||
|
||||
const nightVisionState = useMemo(() => rosterEntry?.nightVision?.state ?? null, [rosterEntry]);
|
||||
|
||||
const emitCommand = useCallback(
|
||||
(payload, cb) => {
|
||||
if (!roverId) return;
|
||||
@@ -202,6 +204,7 @@ export function useCommandPipeline(options = {}) {
|
||||
rosterEntry,
|
||||
servoConfig,
|
||||
nightVision,
|
||||
nightVisionState,
|
||||
emitCommand,
|
||||
enableSensorStream,
|
||||
sendDriveDirect,
|
||||
@@ -217,6 +220,7 @@ export function useCommandPipeline(options = {}) {
|
||||
rosterEntry,
|
||||
servoConfig,
|
||||
nightVision,
|
||||
nightVisionState,
|
||||
emitCommand,
|
||||
enableSensorStream,
|
||||
sendDriveDirect,
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
getPadSignature,
|
||||
} from './gamepadBindings.js';
|
||||
import { subscribeGamepadHub } from './gamepadHub.js';
|
||||
import { isTextEntryActive } from './inputFocusUtils.js';
|
||||
|
||||
const SOURCE = 'gamepad';
|
||||
const ZERO_VECTOR = { x: 0, y: 0, boost: false };
|
||||
@@ -154,6 +155,21 @@ export default function GamepadInputManager() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTextEntryActive()) {
|
||||
if (!areVectorsEqual(lastVectorRef.current, ZERO_VECTOR)) {
|
||||
lastVectorRef.current = ZERO_VECTOR;
|
||||
setDriveVector(ZERO_VECTOR, { source: SOURCE });
|
||||
}
|
||||
if (!areAuxEqual(lastAuxRef.current, ZERO_AUX)) {
|
||||
lastAuxRef.current = ZERO_AUX;
|
||||
setAuxMotors(ZERO_AUX);
|
||||
}
|
||||
buttonStateRef.current = new Map();
|
||||
reverseStateRef.current = { main: false, side: false };
|
||||
registerInputState(SOURCE, { connected: true, blocked: true });
|
||||
return;
|
||||
}
|
||||
|
||||
ensureProfile(activePad);
|
||||
const signature = activePad.signature;
|
||||
const profile =
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useControlSystem } from '../ControlContext.jsx';
|
||||
import { useChat } from '../../context/ChatContext.jsx';
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import { normalizeKeymapEntries, tokensForEvent } from '../keymapUtils.js';
|
||||
import { isTextInputElement } from './inputFocusUtils.js';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
import { INPUT_SETTINGS_DEFAULTS } from '../../settings/namespaces.js';
|
||||
import {
|
||||
@@ -55,15 +56,7 @@ function mapTiltIntervalToSpeed(interval) {
|
||||
}
|
||||
|
||||
function shouldIgnoreEvent(event) {
|
||||
const target = event.target;
|
||||
if (!target) return false;
|
||||
const tag = target.tagName;
|
||||
return (
|
||||
tag === 'INPUT' ||
|
||||
tag === 'TEXTAREA' ||
|
||||
target.isContentEditable ||
|
||||
tag === 'SELECT'
|
||||
);
|
||||
return isTextInputElement(event?.target);
|
||||
}
|
||||
|
||||
function bindingActive(bindingSet, keys) {
|
||||
@@ -395,12 +388,12 @@ export default function KeyboardInputManager() {
|
||||
resetAll();
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
window.addEventListener('keyup', handleKeyUp);
|
||||
window.addEventListener('keydown', handleKeyDown, { capture: true });
|
||||
window.addEventListener('keyup', handleKeyUp, { capture: true });
|
||||
window.addEventListener('blur', handleBlur);
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
window.removeEventListener('keyup', handleKeyUp);
|
||||
window.removeEventListener('keydown', handleKeyDown, { capture: true });
|
||||
window.removeEventListener('keyup', handleKeyUp, { capture: true });
|
||||
window.removeEventListener('blur', handleBlur);
|
||||
};
|
||||
}, [
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
const TEXT_INPUT_TYPES = new Set([
|
||||
'',
|
||||
'text',
|
||||
'search',
|
||||
'email',
|
||||
'password',
|
||||
'url',
|
||||
'tel',
|
||||
'number',
|
||||
'date',
|
||||
'datetime-local',
|
||||
'month',
|
||||
'time',
|
||||
'week',
|
||||
]);
|
||||
|
||||
export function isTextInputElement(target) {
|
||||
if (!target || target.nodeType !== 1) return false;
|
||||
const tag = target.tagName;
|
||||
if (tag === 'TEXTAREA') return true;
|
||||
if (target.isContentEditable) return true;
|
||||
if (tag !== 'INPUT') return false;
|
||||
const type = target.type ? target.type.toLowerCase() : '';
|
||||
return TEXT_INPUT_TYPES.has(type);
|
||||
}
|
||||
|
||||
export function isTextEntryActive() {
|
||||
if (typeof document === 'undefined') return false;
|
||||
return isTextInputElement(document.activeElement);
|
||||
}
|
||||
Reference in New Issue
Block a user