Skip to content

Commit 99f3fb6

Browse files
committed
Cleanup GameController barcode parser implementation
1 parent fa0d62b commit 99f3fb6

File tree

7 files changed

+30
-732
lines changed

7 files changed

+30
-732
lines changed

Modules/Sources/Experiments/DefaultFeatureFlagService.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,6 @@ public struct DefaultFeatureFlagService: FeatureFlagService {
9090
return true
9191
case .pointOfSaleBarcodeScanningi1:
9292
return true
93-
case .pointOfSaleBarcodeScanningi2:
94-
return buildConfig == .localDeveloper || buildConfig == .alpha
9593
case .showPointOfSaleBarcodeSimulator:
9694
// Enables a simulated barcode scanner in dev builds for testing. Do not ship this one!
9795
return false

Modules/Sources/Experiments/FeatureFlag.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,6 @@ public enum FeatureFlag: Int {
188188
///
189189
case pointOfSaleBarcodeScanningi1
190190

191-
/// Enables further improvements to barcode scanning with an external scanner in POS
192-
///
193-
case pointOfSaleBarcodeScanningi2
194-
195191
/// Enables a simulated barcode scanner for testing in POS. Do not ship this one!
196192
///
197193
case showPointOfSaleBarcodeSimulator

WooCommerce/Classes/POS/Presentation/Barcode Scanning/BarcodeScannerContainer.swift

Lines changed: 4 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -40,90 +40,15 @@ struct BarcodeScannerContainerRepresentable: UIViewControllerRepresentable {
4040
let onScan: (Result<String, Error>) -> Void
4141

4242
func makeUIViewController(context: Context) -> UIViewController {
43-
let featureFlagService = ServiceLocator.featureFlagService
44-
45-
if featureFlagService.isFeatureFlagEnabled(.pointOfSaleBarcodeScanningi2) {
46-
return GameControllerBarcodeScannerHostingController(
47-
configuration: configuration,
48-
onScan: onScan
49-
)
50-
} else {
51-
return BarcodeScannerHostingController(
52-
configuration: configuration,
53-
onScan: onScan
54-
)
55-
}
43+
return GameControllerBarcodeScannerHostingController(
44+
configuration: configuration,
45+
onScan: onScan
46+
)
5647
}
5748

5849
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
5950
}
6051

61-
/// A UIHostingController that handles keyboard input events for barcode scanning.
62-
/// This controller captures keyboard input and interprets it as barcode data when a terminating
63-
/// character is detected.
64-
class BarcodeScannerHostingController: UIHostingController<EmptyView> {
65-
private let configuration: HIDBarcodeParserConfiguration
66-
private let scanner: HIDBarcodeParser
67-
68-
init(
69-
configuration: HIDBarcodeParserConfiguration,
70-
onScan: @escaping (Result<String, Error>) -> Void
71-
) {
72-
self.configuration = configuration
73-
self.scanner = HIDBarcodeParser(configuration: configuration,
74-
onScan: onScan)
75-
super.init(rootView: EmptyView())
76-
}
77-
78-
@MainActor required dynamic init?(coder aDecoder: NSCoder) {
79-
fatalError("init(coder:) has not been implemented")
80-
}
81-
82-
override var canBecomeFirstResponder: Bool { true }
83-
84-
override func viewDidAppear(_ animated: Bool) {
85-
super.viewDidAppear(animated)
86-
becomeFirstResponder()
87-
}
88-
89-
override func viewDidDisappear(_ animated: Bool) {
90-
super.viewDidDisappear(animated)
91-
resignFirstResponder()
92-
}
93-
94-
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
95-
/// We don't call super here because it helps prevent the system from hiding the software keyboard when
96-
/// a textfield is next used.
97-
}
98-
99-
/// Handles the end of keyboard press events, interpreting them as barcode input.
100-
/// When a terminating character is detected, the accumulated buffer is treated as a complete
101-
/// barcode and passed to the onScan callback.
102-
/// We don't call `super` here because we don't other responder chain items to handle our barcode as well,
103-
/// as this could cause unexpected behavior.
104-
override func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
105-
/// While a scanner should just "press" each key once, in theory it's possible for presses to be cancelled
106-
/// or change between the `began` call and the `ended` call.
107-
/// It's better practice for barcode scanning to only consider the presses when they end.
108-
for press in presses {
109-
guard let key = press.key else { continue }
110-
scanner.processKeyPress(key)
111-
}
112-
}
113-
114-
override func pressesChanged(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
115-
super.pressesChanged(presses, with: event)
116-
}
117-
118-
/// `pressesCancelled` is rarely called, but Apple's documentation suggests it's possible and that crashes may occur if it's not handled.
119-
/// It makes sense to clear the buffer when this happens.
120-
/// We call super in case other presses are handled elsewhere in the responder chain.
121-
override func pressesCancelled(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
122-
scanner.cancel()
123-
super.pressesCancelled(presses, with: event)
124-
}
125-
}
126-
12752
/// A UIHostingController that handles GameController keyboard input events for barcode scanning.
12853
/// This controller uses GameController framework exclusively for language-independent barcode scanning.
12954
final class GameControllerBarcodeScannerHostingController: UIHostingController<EmptyView> {

WooCommerce/Classes/POS/Presentation/Barcode Scanning/GameControllerBarcodeParser.swift

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,7 @@ final class GameControllerBarcodeParser {
4646
}
4747

4848
private func shouldRecogniseAsScanKeystroke(_ keyCode: GCKeyCode, isShiftPressed: Bool) -> Bool {
49-
guard let character = characterForKeyCode(keyCode, isShiftPressed: isShiftPressed) else {
50-
// This prevents a double-trigger-pull on a Star scanner from adding an error row –
51-
// Star use this as a shortcut to switch to the software keyboard. They send keycode 174 0xAE, which is
52-
// undefined and reserved in UIKeyboardHIDUsage. The scanner doesn't send a character with the code.
53-
// There seems to be no reason to handle empty input when considering scans.
54-
return false
55-
}
56-
57-
guard character.isNotEmpty else {
49+
guard let character = characterForKeyCode(keyCode, isShiftPressed: isShiftPressed), character.isNotEmpty else {
5850
// This prevents a double-trigger-pull on a Star scanner from adding an error row –
5951
// Star use this as a shortcut to switch to the software keyboard. They send keycode 174 0xAE, which is
6052
// undefined and reserved in UIKeyboardHIDUsage. The scanner doesn't send a character with the code.
@@ -195,3 +187,28 @@ final class GameControllerBarcodeParser {
195187
resetScan()
196188
}
197189
}
190+
191+
/// Configuration options for the HID barcode parser
192+
struct HIDBarcodeParserConfiguration {
193+
/// Strings that indicate the end of a barcode scan
194+
let terminatingStrings: Set<String>
195+
196+
/// Minimum length to consider scanned input complete
197+
let minimumBarcodeLength: Int
198+
199+
/// Maximum time between scanned keystrokes
200+
/// After this time elapses, any further keystrokes result in the scan being rejected
201+
let maximumInterCharacterTime: TimeInterval
202+
203+
/// Default configuration suitable for most barcode scanners
204+
static let `default` = HIDBarcodeParserConfiguration(
205+
terminatingStrings: ["\r", "\n"],
206+
minimumBarcodeLength: 6,
207+
maximumInterCharacterTime: 0.2
208+
)
209+
}
210+
211+
enum HIDBarcodeParserError: Error {
212+
case scanTooShort(barcode: String)
213+
case timedOut(barcode: String)
214+
}

WooCommerce/Classes/POS/Presentation/Barcode Scanning/HIDBarcodeParser.swift

Lines changed: 0 additions & 199 deletions
This file was deleted.

0 commit comments

Comments
 (0)