Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Barcode Detector does'nt work in some devices #138

Open
AlirezaDevv opened this issue Dec 18, 2024 · 1 comment
Open

Barcode Detector does'nt work in some devices #138

AlirezaDevv opened this issue Dec 18, 2024 · 1 comment

Comments

@AlirezaDevv
Copy link

AlirezaDevv commented Dec 18, 2024

Hi , Im using this package in react , barcode reader work perfectly in some phones and does'nt work in others

this is my code on a useBarcode hook :

import { useEffect, useState } from 'react';
import { BarcodeReader } from './barcodeClass';
import type Webcam from 'react-webcam';

interface useBarcodeData {
  webcamRef: React.RefObject<Webcam>;
  scannerOpen: boolean;
}

export const useBarcode = (props: useBarcodeData) => {
  const [barcodeReader, setBarcodeReader] = useState<BarcodeReader | null>(null);
  const [barcodeData, setBarcodeData] = useState('Not Found');

  // Initialize BarcodeReader on component mount
  useEffect(() => {
    const setupBarcodeReader = async () => {
      const result = await BarcodeReader.setup();
      if (result.barcodeReaderError) {
        console.error(result.barcodeReaderError);
      } else {
        const reader = await BarcodeReader.create(['qr_code', 'ean_13', 'code_128']);
        setBarcodeReader(reader);
      }
    };

    void setupBarcodeReader();
  }, []);

  const handleScanBarcode = async () => {
    if (props.webcamRef.current && barcodeReader) {
      const imageSrc = props.webcamRef.current.getScreenshot();
      if (imageSrc) {
        try {
          const image = new Image();
          image.src = imageSrc;
          image.onload = async () => {
            try {
              const barcode = await barcodeReader.detect(image);
              setBarcodeData(barcode.rawValue);
            } catch (error) {
              console.error('Error detecting barcode:', error);
            }
          };
        } catch (error) {
          console.error('Error processing image for barcode detection:', error);
        }
      }
    }
  };

  let interval: NodeJS.Timeout | null = null;
  if (props.scannerOpen) {
    interval = setInterval(async () => {
      await handleScanBarcode();
    }, 500);
  } else if (interval && !props.scannerOpen) {
    {
      clearInterval(interval);
    }
  }

  return { barcodeData };
};

And this is BarcodeReader class :

/* eslint-disable @typescript-eslint/member-ordering */
// utils/barcodeReader.ts

interface BarcodeDetection {
  rawValue: string;
  format: string;
  boundingBox: DOMRect;
  cornerPoints: Array<{ x: number; y: number }>;
}

const WHITELISTED_FORMATS = [
  'aztec',
  'code_128',
  'code_39',
  'code_93',
  'codabar',
  'data_matrix',
  'ean_13',
  'ean_8',
  'itf',
  'pdf417',
  'qr_code',
  'upc_a',
  'upc_e',
];

class BarcodeReader {
  // eslint-disable-next-line @typescript-eslint/class-literal-property-style
  private readonly barcodeReader: BarcodeDetector | null = null;

  static async polyfill() {
    if (!('BarcodeDetector' in window)) {
      try {
        await import('barcode-detector');
        console.log('Using BarcodeDetector polyfill.');
      } catch (error) {
        throw new Error('BarcodeDetector API is not supported by your browser.', { cause: error });
      }
    } else {
      console.log('Using the native BarcodeDetector API.');
    }
  }

  static async getSupportedFormats() {
    const nativeSupportedFormats = (await window.BarcodeDetector.getSupportedFormats()) || [];
    // @ts-expect-error - TS doesn't know about the WHITELISTED_FORMATS constant
    return WHITELISTED_FORMATS.filter((format) => nativeSupportedFormats.includes(format));
  }

  static async create(supportedFormats: string[]): Promise<BarcodeReader> {
    const isValidFormats = Array.isArray(supportedFormats) && supportedFormats.length > 0;
    const formats = isValidFormats ? supportedFormats : await BarcodeReader.getSupportedFormats();
    // @ts-expect-error - TS doesn't know about the WHITELISTED_FORMATS constant
    return new BarcodeReader(formats);
  }

  static async setup() {
    try {
      await BarcodeReader.polyfill();
      return { barcodeReaderError: null };
    } catch (error) {
      return { barcodeReaderError: error };
    }
  }

  constructor(formats: BarcodeDetectorOptions['formats']) {
    this.barcodeReader = new window.BarcodeDetector({ formats });
  }

  async detect(source: HTMLImageElement | HTMLVideoElement | ImageBitmap): Promise<BarcodeDetection> {
    if (!this.barcodeReader) {
      throw new Error('BarcodeReader is not initialized.');
    }

    const results = await this.barcodeReader.detect(source);
    if (Array.isArray(results) && results.length > 0) {
      const firstResult = results[0];
      console.log({ rawValue: firstResult.rawValue, format: firstResult.format });
      return firstResult;
    } else {
      throw new Error('Could not detect barcode from provided source.');
    }
  }
}

export { BarcodeReader };
@Sec-ant
Copy link
Owner

Sec-ant commented Dec 18, 2024

does'nt work in others

So what's exactly the problem? What's the error message?

I appreciate it if you can simplify your code a bit further. Is there any issue if you just call the detect function from this library?

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

No branches or pull requests

2 participants