Shopify / shopify-app-bridge

https://shopify.dev/docs/api/app-bridge
85 stars 9 forks source link

Scanner.Action.CAPTURE not firing? #172

Closed dgtlmonk closed 1 year ago

dgtlmonk commented 1 year ago

Describe the bug

Subscription to Scanner.Action.CAPTURE is not firing, while other Actions subscription like Cart.Action.UPDATE is working as expected.

To Reproduce

Steps to reproduce the behaviour:

  const app = useAppBridge();
  const scanner = Scanner.create(app);

  // THIS IS NOT FIRING :-/
  scanner.subscribe(Scanner.Action.CAPTURE, payload => {
    window.alert('scanner captured ', payload.scanData)  
  });

  scanner.dispatch(Scanner.Action.OPEN_CAMERA)

Expected behaviour

subscription to Scanner.Action.CAPTURE event should trigger

Contextual information

I have a simple POS extension app that utilizes Scanner Action to read barcode. The camera is opening fine and I can see the captured barcode value from the built-in Shopify Scanner functionality, but the "capturing" event subscription in my code is not being called. I tried other Actions like Cart.Action.UPDATE and I was able to receive the subscription event.

Packages and versions

Platform

Additional context

The app is purely created with shopify-cli no modifications (NodeJS/React)

pramodparanthaman commented 1 year ago

This has been broken for a while and has been brought up before. https://github.com/Shopify/shopify-app-bridge/issues/97#issuecomment-1058811578

I've been using app.subscribe() instead of scanner.subscribe() as a work-around.

import { Features, Group, Scanner } from "@shopify/app-bridge/actions";

let subscribed = false;
let available = false;

export const scanBarcode = (app, barcodeCallback) => {
  try {
    let scanner = Scanner.create(app);
    let features = Features.create(app);

    // Open camera
    scanner.dispatch(Scanner.Action.OPEN_CAMERA);

    // Dispatch an action to request access to Camera Scanner
    features.subscribe(Features.Action.REQUEST_UPDATE, function (payload) {
      if (payload.feature[Scanner.Action.OPEN_CAMERA]) {
        available = payload.feature[Scanner.Action.OPEN_CAMERA].Dispatch;
        if (available) {
          scanner.dispatch(Scanner.Action.OPEN_CAMERA);
        }
      }
    });    

    // Does nothing on Shopify POS on Android and iOS
    // Works fine on Shopify Mobile
    features.dispatch(Features.Action.REQUEST, {
      feature: Group.Scanner,
      action: Scanner.Action.OPEN_CAMERA,
    });
    if (!subscribed) {
      subscribed = true;
      app.subscribe(Scanner.Action.CAPTURE, (payload) => {
        let barcode = payload.data.data
          ? payload.data.data
          : payload.data.scanData;
        alert("Barcode" + barcode);
        barcodeCallback(barcode); // Process barcode
      });
    }
  } catch (err) {
    console.log("Camera scanner not available.", err);
    alert("Camera scanner not available. " + JSON.stringify(err?.message));
  }
};
dgtlmonk commented 1 year ago

Thank you @pramodparanthaman. This is a confirmed workaround

charles-tyler commented 1 year ago

@pramodparanthaman and @dgtlmonk

This workaround doesn't seem to work with "Optimize loading on mobile". It seems to cause the feature to fire multiple times.

It also seems that the scanner is crashing the Shopify Mobile app when opened unless using "Optimize loading on mobile".

henrytao-me commented 1 year ago

@charles-tyler May I know what Shopify Mobile version and OS that you are using? 🙇

charles-tyler commented 1 year ago

@henrytao-me iOS - 16.2 Shopify Mobile - 9.97.0 Shopify POS (where the issue is) - 8.2.0

The workaround app.subscribe was working for both Shopify Mobile and Shopify POS. This then got reported as not working well by our users when we upgraded to "Optimize loading on mobile" -> The scanner returned the payload multiple times.

We tried to turn off "Optimize loading on mobile" but this caused the Shopify Mobile app to crash when the scanner was opened on the most recent version of the Shopify Mobile app.

We then turned "Optimize loading on mobile" back on, and went back to scanner.subscribe which is working again as desired in Shopify Mobile. However on Shopify POS the payload is not returned as expected. A toast appears with the result instead of being usable.

Happy to supply further info or hop on a call if useful.

henrytao-me commented 1 year ago

Thanks @charles-tyler for more info.

The workaround app.subscribe was working for both Shopify Mobile and Shopify POS. This then got reported as not working well by our users when we upgraded to "Optimize loading on mobile" -> The scanner returned the payload multiple times.

👀 Let me investigate this

We tried to turn off "Optimize loading on mobile" but this caused the Shopify Mobile app to crash when the scanner was opened on the most recent version of the Shopify Mobile app.

✅ We identified a bug with latest release of Shopify Mobile iOS when mobile optimize feature is OFF. The fix has been merged and should be available publicly in the next release.

We then turned "Optimize loading on mobile" back on, and went back to scanner.subscribe which is working again as desired in Shopify Mobile. However on Shopify POS the payload is not returned as expected. A toast appears with the result instead of being usable.

👀 I will also investigate this scanner.subscribe should work UNLESS you dispatch and subscribe with different scanner object. There is an internal id for each app-bridge action. For example, below code won't work:


// This code won't work
var scanner = AppBridgeScanner.create(...);
scanner.subscribe(...)
scanner = AppBridgeScanner.create(...);
scanner.dispatch(...)

// This code will have race condition because you dispatch before subscribing
var scanner = AppBridgeScanner.create(...);
scanner.dispatch(...)
scanner.subscribe(...)

// This code should work (unless there is a bug on our side 🤞 => will look into it)
var scanner = AppBridgeScanner.create(...);
scanner.subscribe(...)
scanner.dispatch(...)
henrytao-me commented 1 year ago

FYI, we found the root cause for the scanner.subscribe. We will post here when the issue is resolved 🙇

pramodparanthaman commented 1 year ago

Adding a 500ms delay between calls to the app-bridge scanner fixed this on iOS Shopify POS in my app. https://apps.shopify.com/picklist