Skip to content

Fix duplicate scans from concurrent scan listeners - #436

Closed
jmiranda wants to merge 1 commit into
developfrom
claude/fix-duplicate-scan-listener
Closed

Fix duplicate scans from concurrent scan listeners#436
jmiranda wants to merge 1 commit into
developfrom
claude/fix-duplicate-scan-listener

Conversation

@jmiranda

@jmiranda jmiranda commented Aug 5, 2026

Copy link
Copy Markdown
Member

Follow-up to #423 (OBLS-822).

Problem

A single hardware scan produces exactly one DataWedge intent broadcast, which DeviceEventEmitter dispatches to every registered listener. useScanListener adds one listener per enabled consumer, so whenever two ScannerInputs are mounted at the same time the same scan is handled twice and the value is applied twice.

This happens on screens that pair a screen-level ScannerInput with a modal dialog that contains its own ScannerInput (e.g. SortationContainerScreen + ContainerMismatchDialog, PutawayLocationScanScreen, PutawayQuantityScreen). Each screen disables one input while the other is active (isEnabled={!isDialogVisible ...}), but during the dialog open/close transition both inputs can be subscribed for a moment, and a scan in that window is delivered to both listeners.

This is not native-receiver stacking: react-native-datawedge-intents reuses a single genericReceiver and unregisters it before re-registering, so there is only ever one native receiver and one emit per scan. The duplication is purely on the JS listener side.

Change

  • Route all scans through a single shared DeviceEventEmitter subscription.
  • Track enabled consumers as a stack and deliver each scan only to the most recently enabled one — the scanner is owned by one listener at a time. This is robust to two ScannerInputs being briefly subscribed together: only the active (top-of-stack) one handles the scan.

This preserves the existing enabled gating on useScanListener (ScannerInput still passes shouldBeFocused) and matches the codebase invariant of one scanner input per screen; useBarcodeScanned is unchanged.

How to test (no Zebra required)

Open the inbound sortation flow (Sortation → scan product → container screen), then from a connected device/emulator:

adb shell am broadcast -a com.openboxes.android.ACTION --es com.symbol.datawedge.data_string "0123456789" --es com.symbol.datawedge.label_type "LABEL-TYPE-CODE128"

The value should be applied once. Also exercise the container-mismatch dialog (scan a wrong container to open it, then scan again inside the dialog) and confirm no double entry/submit across the dialog transition.

Not covered here

DataWedge Keystroke output is still enabled alongside Intent output, so a scan is also typed into the focused field. That's a separate potential duplicate source (would show as doubled/appended text or a double submit, including on single-input screens with no dialog). Left out of this PR; can be addressed separately if it turns out to be a real symptom in practice.

🤖 Generated with Claude Code

useScanListener added a DeviceEventEmitter listener per enabled consumer.
A single hardware scan produces one intent broadcast, which the emitter
dispatches to every registered listener, so when two ScannerInputs are
mounted together — e.g. a screen input and a modal dialog input during a
dialog open/close transition — both handled the same scan and the value
was applied twice.

Route scans through a single shared subscription and deliver each scan to
only the most recently enabled consumer (top of a listener stack), so the
scanner is owned by one listener at a time.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018esj4qV5h4teD7M6WfHahM
@jmiranda
jmiranda force-pushed the claude/fix-duplicate-scan-listener branch from ae36d0f to 2acd681 Compare August 5, 2026 18:19
@jmiranda jmiranda changed the title Fix duplicate DataWedge scans from concurrent scan listeners Fix duplicate scans from concurrent scan listeners Aug 5, 2026
@jmiranda
jmiranda force-pushed the claude/fix-duplicate-scan-listener branch from 79608c8 to 2acd681 Compare August 5, 2026 18:37
@jmiranda

jmiranda commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

Closing to temporarily halt the bitrise builds that are being triggered.

cc @awalkowiak

@jmiranda jmiranda closed this Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant