diff --git a/src/hooks/constant.ts b/src/hooks/constant.ts index 3a106eec..44299bb2 100644 --- a/src/hooks/constant.ts +++ b/src/hooks/constant.ts @@ -64,3 +64,21 @@ export const PROFILE_CONFIG2 = { } } }; + +// Keystroke output is a profile-wide DataWedge setting, so it cannot be scoped to +// a single field. It is toggled at runtime: disabled while a barcode input owns +// the scanner (so a scan arrives only via the intent broadcast and is not also +// typed into the focused field as keystrokes), and re-enabled otherwise so plain +// inputs elsewhere can still be populated by scanning. +export const getKeystrokeOutputConfig = (enabled: boolean) => ({ + PROFILE_NAME: 'OPENBOXES', + PROFILE_ENABLED: 'true', + CONFIG_MODE: 'UPDATE', + PLUGIN_CONFIG: { + PLUGIN_NAME: 'KEYSTROKE', + RESET_CONFIG: 'true', + PARAM_LIST: { + keystroke_output_enabled: enabled ? 'true' : 'false' + } + } +}); diff --git a/src/hooks/useScanListener.ts b/src/hooks/useScanListener.ts index 8068365d..669c5235 100644 --- a/src/hooks/useScanListener.ts +++ b/src/hooks/useScanListener.ts @@ -6,6 +6,7 @@ import { ACTION, FILTER_ACTIONS, FILTER_CATEGORY, + getKeystrokeOutputConfig, LISTENER, PROFILE, PROFILE_CONFIG, @@ -19,6 +20,10 @@ export type ScanResult = { let profileConfigured = false; +// Number of barcode inputs currently listening for scans. Keystroke output is +// muted while this is > 0 (see below). +let activeConsumerCount = 0; + function sendDataWedgeCommand(extraName: string, extraValue: unknown): void { DataWedgeIntents.sendBroadcastWithExtras({ action: ACTION.API_ACTION, @@ -36,6 +41,10 @@ function configureProfileOnce(): void { sendDataWedgeCommand(PROFILE.SET_CONFIG_PROFILE, PROFILE_CONFIG2); } +function setKeystrokeOutput(enabled: boolean): void { + sendDataWedgeCommand(PROFILE.SET_CONFIG_PROFILE, getKeystrokeOutputConfig(enabled)); +} + function extractScan(intent: Record): ScanResult | null { const data = intent?.[ACTION.DATA_STRING] ?? intent?.data; if (!data) { @@ -60,6 +69,16 @@ export function useScanListener(onScan: (result: ScanResult) => void, enabled = filterCategories: FILTER_CATEGORY }); + // A barcode input is now listening via the intent broadcast. While any is + // active, mute DataWedge keystroke output so the scan is not also typed into + // the focused field (which would duplicate/append the value). Reference + // counted so overlapping inputs (e.g. a screen input and a modal input) keep + // it muted until the last one goes away, then restore it for plain inputs. + activeConsumerCount += 1; + if (activeConsumerCount === 1) { + setKeystrokeOutput(false); + } + const handleIntent = (intent: Record) => { const result = extractScan(intent); if (result) { @@ -68,6 +87,12 @@ export function useScanListener(onScan: (result: ScanResult) => void, enabled = }; const subscription = DeviceEventEmitter.addListener(LISTENER.BROADCAST_INTENT, handleIntent); - return () => subscription.remove(); + return () => { + subscription.remove(); + activeConsumerCount -= 1; + if (activeConsumerCount === 0) { + setKeystrokeOutput(true); + } + }; }, [enabled]); }