react-native-camera / react-native-camera-v4

Camera support for React Native
37 stars 2 forks source link

barCodeTypes not working on iOs #8

Open artola opened 3 years ago

artola commented 3 years ago

In v3 the barCodeTypes are not correctly typed, it is not supporting the detected types on iOs.

For example, if I would like to restrict the valid codes to only QR, the TS typings say to pass:

barCodeTypes: ['qr']

but it does not work on iOs, I need to pass:

barCodeTypes: ['org.iso.QRCode']

I do not know if makes sense to fix this on v3 or just see this looking forward.

Docs: https://developer.apple.com/documentation/avfoundation/avmetadatamachinereadablecodeobject/machine-readable_object_types

MarcoScabbiolo commented 3 years ago

I agree, and this goes for every option, not only barCodeTypes:

Features/options supported by both iOS and Android will have the same values. To read QR codes setting qr will work for both iOS and Android, and the type of the possible values for the barCodeTypes prop will include all those types of bar codes available in both iOS and Android.

For those features/options supported by only one OS, there will be an extension of the base prop value type for that OS that extends with the OS-specific features/options. For example:

type BarCodeTypes = 'qr' | 'barcodeformatfoo'
type IOSBarCodeTypes = BarCodeTypes | 'appleQR'
type AndroidBarCodeTypes = BarCodeTypes

interface BarcodeOptions {
  barcodeTypes: (BarCodeType | IOSBarCodeTypes | AndroidBarCodeTypes)[]
}

Invalid options should be rejected by an OS, but the JS side should filter sending valid options for one OS when the runtime is of another OS. That means:

// This doesn't fail on either Android or iOS
<BarcodePlugin barcodeTypes={['qr', 'appleQR']} />

// This fails on both Android and iOS
<BarcodePlugin barcodeTypes={['invalid']} />

This means v4 will have a lot of breaking changes in props and options to make the API as clean and platform-agnostic as possible. Typescript types and good documentation is the way to get it right.

Native options should not be hidden by the JS side just as an attempt to provide a uniform API across both OS. Take the quality option of record as an example: Current possible values are '2160p' | ... | '288p', '4:3' but iOS doesn't actually have a 4:3 value, it does have 640x480 option which provides a 4:3 ratio but is the same as setting it to 480p. On top of that, many of the supported iOS are not being exposed in the API, so the right way to document this is to say the quality option supports 2160p ... 288p on both Android and iOS, and additionally any valid iOS AVCaptureSession.Preset value is a valid option. This does mean we have to add every possible option for each OS into the OS specific types and update them as they are added, but I think it is worth it to expose the full potential of the native side.

type RecordQuality = '2160p' | '1080p' | '720p' | '480p' | '288p'
type IOSRecordQuality = RecordQuality | 'qvga320x240' | 'low' | 'medium' | 'high' | ...

Please note that these are all example values and don't reflect the final API.