diff --git a/.changeset/chilled-dodos-dream.md b/.changeset/chilled-dodos-dream.md new file mode 100644 index 0000000..201736f --- /dev/null +++ b/.changeset/chilled-dodos-dream.md @@ -0,0 +1,5 @@ +--- +'@capacitor-mlkit/barcode-scanning': minor +--- + +feat: add `barcodesScanned` listener diff --git a/packages/barcode-scanning/README.md b/packages/barcode-scanning/README.md index fd94220..c9080cd 100644 --- a/packages/barcode-scanning/README.md +++ b/packages/barcode-scanning/README.md @@ -297,6 +297,7 @@ If you can't see the camera view, make sure all elements in the DOM are not visi * [`checkPermissions()`](#checkpermissions) * [`requestPermissions()`](#requestpermissions) * [`addListener('barcodeScanned', ...)`](#addlistenerbarcodescanned) +* [`addListener('barcodesScanned', ...)`](#addlistenerbarcodesscanned) * [`addListener('scanError', ...)`](#addlistenerscanerror) * [`addListener('googleBarcodeScannerModuleInstallProgress', ...)`](#addlistenergooglebarcodescannermoduleinstallprogress) * [`removeAllListeners()`](#removealllisteners) @@ -666,6 +667,28 @@ Available on Android and iOS. -------------------- +### addListener('barcodesScanned', ...) + +```typescript +addListener(eventName: 'barcodesScanned', listenerFunc: (event: BarcodesScannedEvent) => void) => Promise +``` + +Called when barcodes are scanned. + +Available on Android and iOS. + +| Param | Type | +| ------------------ | ----------------------------------------------------------------------------------------- | +| **`eventName`** | 'barcodesScanned' | +| **`listenerFunc`** | (event: BarcodesScannedEvent) => void | + +**Returns:** Promise<PluginListenerHandle> + +**Since:** 6.2.0 + +-------------------- + + ### addListener('scanError', ...) ```typescript @@ -852,6 +875,13 @@ Remove all listeners for this plugin. | **`barcode`** | Barcode | A detected barcode. | 0.0.1 | +#### BarcodesScannedEvent + +| Prop | Type | Description | Since | +| -------------- | ---------------------- | ---------------------- | ----- | +| **`barcodes`** | Barcode[] | The detected barcodes. | 6.2.0 | + + #### ScanErrorEvent | Prop | Type | Description | Since | diff --git a/packages/barcode-scanning/android/src/main/java/io/capawesome/capacitorjs/plugins/mlkit/barcodescanning/BarcodeScanner.java b/packages/barcode-scanning/android/src/main/java/io/capawesome/capacitorjs/plugins/mlkit/barcodescanning/BarcodeScanner.java index 709c42f..d4d4d1d 100644 --- a/packages/barcode-scanning/android/src/main/java/io/capawesome/capacitorjs/plugins/mlkit/barcodescanning/BarcodeScanner.java +++ b/packages/barcode-scanning/android/src/main/java/io/capawesome/capacitorjs/plugins/mlkit/barcodescanning/BarcodeScanner.java @@ -44,7 +44,9 @@ import io.capawesome.capacitorjs.plugins.mlkit.barcodescanning.classes.results.GetMaxZoomRatioResult; import io.capawesome.capacitorjs.plugins.mlkit.barcodescanning.classes.results.GetMinZoomRatioResult; import io.capawesome.capacitorjs.plugins.mlkit.barcodescanning.classes.results.GetZoomRatioResult; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; public class BarcodeScanner implements ImageAnalysis.Analyzer { @@ -350,11 +352,12 @@ public void analyze(@NonNull ImageProxy imageProxy) { // Scanning stopped while processing the image return; } - for (Barcode barcode : barcodes) { - Integer votes = voteForBarcode(barcode); - if (votes >= 10) { - handleScannedBarcode(barcode, imageSize); - } + List barcodesWithEnoughVotes = voteForBarcodes(barcodes); + for (Barcode barcode : barcodesWithEnoughVotes) { + handleScannedBarcode(barcode, imageSize); + } + if (barcodesWithEnoughVotes.size() > 0) { + handleScannedBarcodes(barcodesWithEnoughVotes.toArray(new Barcode[0]), imageSize); } } ) @@ -410,6 +413,10 @@ private void handleScannedBarcode(Barcode barcode, Point imageSize) { plugin.notifyBarcodeScannedListener(barcode, imageSize); } + private void handleScannedBarcodes(Barcode[] barcodes, Point imageSize) { + plugin.notifyBarcodesScannedListener(barcodes, imageSize); + } + private void handleScanError(Exception exception) { plugin.notifyScanErrorListener(exception.getMessage()); } @@ -439,4 +446,15 @@ private Integer voteForBarcode(Barcode barcode) { return barcodeRawValueVotes.get(rawValue); } } + + private List voteForBarcodes(List barcodes) { + List barcodesWithEnoughVotes = new ArrayList<>(); + for (Barcode barcode : barcodes) { + Integer votes = voteForBarcode(barcode); + if (votes >= 10) { + barcodesWithEnoughVotes.add(barcode); + } + } + return barcodesWithEnoughVotes; + } } diff --git a/packages/barcode-scanning/android/src/main/java/io/capawesome/capacitorjs/plugins/mlkit/barcodescanning/BarcodeScannerPlugin.java b/packages/barcode-scanning/android/src/main/java/io/capawesome/capacitorjs/plugins/mlkit/barcodescanning/BarcodeScannerPlugin.java index 0c8163e..fd41894 100644 --- a/packages/barcode-scanning/android/src/main/java/io/capawesome/capacitorjs/plugins/mlkit/barcodescanning/BarcodeScannerPlugin.java +++ b/packages/barcode-scanning/android/src/main/java/io/capawesome/capacitorjs/plugins/mlkit/barcodescanning/BarcodeScannerPlugin.java @@ -39,6 +39,7 @@ public class BarcodeScannerPlugin extends Plugin { public static final String CAMERA = "camera"; public static final String BARCODE_SCANNED_EVENT = "barcodeScanned"; + public static final String BARCODES_SCANNED_EVENT = "barcodesScanned"; public static final String SCAN_ERROR_EVENT = "scanError"; public static final String GOOGLE_BARCODE_SCANNER_MODULE_INSTALL_PROGRESS_EVENT = "googleBarcodeScannerModuleInstallProgress"; public static final String ERROR_SCAN_CANCELED = "scan canceled."; @@ -477,6 +478,23 @@ public void notifyBarcodeScannedListener(Barcode barcode, Point imageSize) { } } + public void notifyBarcodesScannedListener(Barcode[] barcodes, Point imageSize) { + try { + Point screenSize = this.getScreenSize(); + JSArray barcodesResult = new JSArray(); + for (Barcode barcode : barcodes) { + JSObject barcodeResult = BarcodeScannerHelper.createBarcodeResultForBarcode(barcode, imageSize, screenSize); + barcodesResult.put(barcodeResult); + } + + JSObject result = new JSObject(); + result.put("barcodes", barcodesResult); + notifyListeners(BARCODES_SCANNED_EVENT, result); + } catch (Exception exception) { + Logger.error(TAG, exception.getMessage(), exception); + } + } + public void notifyScanErrorListener(String message) { try { JSObject result = new JSObject(); diff --git a/packages/barcode-scanning/ios/Plugin/BarcodeScanner.swift b/packages/barcode-scanning/ios/Plugin/BarcodeScanner.swift index 605f8d6..b0fd413 100644 --- a/packages/barcode-scanning/ios/Plugin/BarcodeScanner.swift +++ b/packages/barcode-scanning/ios/Plugin/BarcodeScanner.swift @@ -260,6 +260,10 @@ typealias MLKitBarcodeScanner = MLKitBarcodeScanning.BarcodeScanner plugin.notifyBarcodeScannedListener(barcode: barcode, imageSize: imageSize, videoOrientation: videoOrientation) } + private func handleScannedBarcodes(barcodes: [Barcode], imageSize: CGSize, videoOrientation: AVCaptureVideoOrientation?) { + plugin.notifyBarcodesScannedListener(barcodes: barcodes, imageSize: imageSize, videoOrientation: videoOrientation) + } + private func voteForBarcode(barcode: Barcode) -> Int { guard let rawValue = barcode.rawValue else { return 1 @@ -271,6 +275,12 @@ typealias MLKitBarcodeScanner = MLKitBarcodeScanning.BarcodeScanner } return self.barcodeRawValueVotes[rawValue] ?? 1 } + + private func voteForBarcodes(barcodes: [Barcode]) -> [Barcode] { + return barcodes.filter { barcode in + return self.voteForBarcode(barcode: barcode) >= 10 + } + } } extension BarcodeScanner: BarcodeScannerViewDelegate { @@ -279,11 +289,12 @@ extension BarcodeScanner: BarcodeScannerViewDelegate { scanCompletionHandler(barcodes, videoOrientation, nil) self.stopScan() } else { - for barcode in barcodes { - let votes = self.voteForBarcode(barcode: barcode) - if votes >= 10 { - self.handleScannedBarcode(barcode: barcode, imageSize: imageSize, videoOrientation: videoOrientation) - } + let barcodesWithEnoughVotes = self.voteForBarcodes(barcodes: barcodes) + for barcode in barcodesWithEnoughVotes { + self.handleScannedBarcode(barcode: barcode, imageSize: imageSize, videoOrientation: videoOrientation) + } + if barcodesWithEnoughVotes.count > 0 { + self.handleScannedBarcodes(barcodes: barcodesWithEnoughVotes, imageSize: imageSize, videoOrientation: videoOrientation) } } } diff --git a/packages/barcode-scanning/ios/Plugin/BarcodeScannerHelper.swift b/packages/barcode-scanning/ios/Plugin/BarcodeScannerHelper.swift index 77ac9fe..a995a3e 100644 --- a/packages/barcode-scanning/ios/Plugin/BarcodeScannerHelper.swift +++ b/packages/barcode-scanning/ios/Plugin/BarcodeScannerHelper.swift @@ -34,15 +34,12 @@ public class BarcodeScannerHelper { case .portrait, .portraitUpsideDown: x = ((imageHeight - cornerPoint.cgPointValue.y) * scale) - (invisibleWidth / 2) y = (cornerPoint.cgPointValue.x * scale) - (invisibleHeight / 2) - break - case .landscapeLeft: + case .landscapeLeft: x = ((imageHeight - cornerPoint.cgPointValue.x) * scale) - (invisibleWidth / 2) y = ((imageWidth - cornerPoint.cgPointValue.y) * scale) - (invisibleHeight / 2) - break - default: + default: x = (cornerPoint.cgPointValue.x * scale) - (invisibleWidth / 2) y = (cornerPoint.cgPointValue.y * scale) - (invisibleHeight / 2) - break } let point = CGPoint(x: Int(x), y: Int(y)) let value = NSValue(cgPoint: point) diff --git a/packages/barcode-scanning/ios/Plugin/BarcodeScannerPlugin.swift b/packages/barcode-scanning/ios/Plugin/BarcodeScannerPlugin.swift index 526034d..c72a778 100644 --- a/packages/barcode-scanning/ios/Plugin/BarcodeScannerPlugin.swift +++ b/packages/barcode-scanning/ios/Plugin/BarcodeScannerPlugin.swift @@ -24,6 +24,7 @@ public class BarcodeScannerPlugin: CAPPlugin { public let errorPermissionDenied = "User denied access to camera." public let errorOpenSettingsFailed = "Cannot open settings." public let barcodeScannedEvent = "barcodeScanned" + public let barcodesScannedEvent = "barcodesScanned" private var implementation: BarcodeScanner? @@ -239,6 +240,16 @@ public class BarcodeScannerPlugin: CAPPlugin { result["barcode"] = BarcodeScannerHelper.createBarcodeResultForBarcode(barcode, imageSize: imageSize, videoOrientation: videoOrientation) notifyListeners(barcodeScannedEvent, data: result) } + + func notifyBarcodesScannedListener(barcodes: [Barcode], imageSize: CGSize, videoOrientation: AVCaptureVideoOrientation?) { + var barcodesResult = JSArray() + for barcode in barcodes { + barcodesResult.append(BarcodeScannerHelper.createBarcodeResultForBarcode(barcode, imageSize: imageSize, videoOrientation: videoOrientation)) + } + var result = JSObject() + result["barcodes"] = barcodesResult + notifyListeners(barcodesScannedEvent, data: result) + } } extension AVAuthorizationStatus { diff --git a/packages/barcode-scanning/src/definitions.ts b/packages/barcode-scanning/src/definitions.ts index d29c2dd..b9dabdb 100644 --- a/packages/barcode-scanning/src/definitions.ts +++ b/packages/barcode-scanning/src/definitions.ts @@ -179,11 +179,23 @@ export interface BarcodeScannerPlugin { * Available on Android and iOS. * * @since 0.0.1 + * @deprecated Use the `barcodesScanned` event listener instead. */ addListener( eventName: 'barcodeScanned', listenerFunc: (event: BarcodeScannedEvent) => void, ): Promise; + /** + * Called when barcodes are scanned. + * + * Available on Android and iOS. + * + * @since 6.2.0 + */ + addListener( + eventName: 'barcodesScanned', + listenerFunc: (event: BarcodesScannedEvent) => void, + ): Promise; /** * Called when an error occurs during the scan. * @@ -417,6 +429,18 @@ export interface BarcodeScannedEvent { barcode: Barcode; } +/** + * @since 6.2.0 + */ +export interface BarcodesScannedEvent { + /** + * The detected barcodes. + * + * @since 6.2.0 + */ + barcodes: Barcode[]; +} + /** * @since 0.0.1 */