Skip to content

Commit

Permalink
feat(barcode-scanning): add barcodesScanned listener (#195)
Browse files Browse the repository at this point in the history
* feat(barcode-scanning): add a `barcodesScanned` listener

* fixes

* style: format
  • Loading branch information
robingenz authored Oct 9, 2024
1 parent c3672b4 commit fa76d3c
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilled-dodos-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@capacitor-mlkit/barcode-scanning': minor
---

feat: add `barcodesScanned` listener
30 changes: 30 additions & 0 deletions packages/barcode-scanning/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -666,6 +667,28 @@ Available on Android and iOS.
--------------------


### addListener('barcodesScanned', ...)

```typescript
addListener(eventName: 'barcodesScanned', listenerFunc: (event: BarcodesScannedEvent) => void) => Promise<PluginListenerHandle>
```

Called when barcodes are scanned.

Available on Android and iOS.

| Param | Type |
| ------------------ | ----------------------------------------------------------------------------------------- |
| **`eventName`** | <code>'barcodesScanned'</code> |
| **`listenerFunc`** | <code>(event: <a href="#barcodesscannedevent">BarcodesScannedEvent</a>) =&gt; void</code> |

**Returns:** <code>Promise&lt;<a href="#pluginlistenerhandle">PluginListenerHandle</a>&gt;</code>

**Since:** 6.2.0

--------------------


### addListener('scanError', ...)

```typescript
Expand Down Expand Up @@ -852,6 +875,13 @@ Remove all listeners for this plugin.
| **`barcode`** | <code><a href="#barcode">Barcode</a></code> | A detected barcode. | 0.0.1 |


#### BarcodesScannedEvent

| Prop | Type | Description | Since |
| -------------- | ---------------------- | ---------------------- | ----- |
| **`barcodes`** | <code>Barcode[]</code> | The detected barcodes. | 6.2.0 |


#### ScanErrorEvent

| Prop | Type | Description | Since |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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<Barcode> barcodesWithEnoughVotes = voteForBarcodes(barcodes);
for (Barcode barcode : barcodesWithEnoughVotes) {
handleScannedBarcode(barcode, imageSize);
}
if (barcodesWithEnoughVotes.size() > 0) {
handleScannedBarcodes(barcodesWithEnoughVotes.toArray(new Barcode[0]), imageSize);
}
}
)
Expand Down Expand Up @@ -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());
}
Expand Down Expand Up @@ -439,4 +446,15 @@ private Integer voteForBarcode(Barcode barcode) {
return barcodeRawValueVotes.get(rawValue);
}
}

private List<Barcode> voteForBarcodes(List<Barcode> barcodes) {
List<Barcode> barcodesWithEnoughVotes = new ArrayList<>();
for (Barcode barcode : barcodes) {
Integer votes = voteForBarcode(barcode);
if (votes >= 10) {
barcodesWithEnoughVotes.add(barcode);
}
}
return barcodesWithEnoughVotes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.";
Expand Down Expand Up @@ -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();
Expand Down
21 changes: 16 additions & 5 deletions packages/barcode-scanning/ios/Plugin/BarcodeScanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions packages/barcode-scanning/ios/Plugin/BarcodeScannerPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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?

Expand Down Expand Up @@ -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 {
Expand Down
24 changes: 24 additions & 0 deletions packages/barcode-scanning/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<PluginListenerHandle>;
/**
* Called when barcodes are scanned.
*
* Available on Android and iOS.
*
* @since 6.2.0
*/
addListener(
eventName: 'barcodesScanned',
listenerFunc: (event: BarcodesScannedEvent) => void,
): Promise<PluginListenerHandle>;
/**
* Called when an error occurs during the scan.
*
Expand Down Expand Up @@ -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
*/
Expand Down

0 comments on commit fa76d3c

Please sign in to comment.