UNPKG

4.23 kBTypeScriptView Raw
1import { UnavailabilityError } from '@unimodules/core';
2import mapValues from 'lodash/mapValues';
3import * as React from 'react';
4import { Platform, ViewProps } from 'react-native';
5import { PermissionResponse, PermissionStatus } from 'unimodules-permissions-interface';
6
7import ExpoBarCodeScannerModule from './ExpoBarCodeScannerModule';
8import ExpoBarCodeScannerView from './ExpoBarCodeScannerView';
9
10const { BarCodeType, Type } = ExpoBarCodeScannerModule;
11
12const EVENT_THROTTLE_MS = 500;
13
14export type BarCodePoint = {
15 x: number;
16 y: number;
17};
18
19export type BarCodeSize = {
20 height: number;
21 width: number;
22};
23
24export type BarCodeBounds = {
25 origin: BarCodePoint;
26 size: BarCodeSize;
27};
28
29export type BarCodeScannerResult = {
30 type: string;
31 data: string;
32 bounds?: BarCodeBounds;
33 cornerPoints?: BarCodePoint[];
34};
35
36export type BarCodeEvent = BarCodeScannerResult & {
37 target?: number;
38};
39
40export type BarCodeEventCallbackArguments = {
41 nativeEvent: BarCodeEvent;
42};
43
44export type BarCodeScannedCallback = (params: BarCodeEvent) => void;
45
46export { PermissionResponse, PermissionStatus };
47
48export interface BarCodeScannerProps extends ViewProps {
49 type?: 'front' | 'back' | number;
50 barCodeTypes?: string[];
51 onBarCodeScanned?: BarCodeScannedCallback;
52}
53
54export class BarCodeScanner extends React.Component<BarCodeScannerProps> {
55 lastEvents: { [key: string]: any } = {};
56 lastEventsTimes: { [key: string]: any } = {};
57
58 static Constants = {
59 BarCodeType,
60 Type,
61 };
62
63 static ConversionTables = {
64 type: Type,
65 };
66
67 static defaultProps = {
68 type: Type.back,
69 barCodeTypes: Object.values(BarCodeType),
70 };
71
72 static async getPermissionsAsync(): Promise<PermissionResponse> {
73 return ExpoBarCodeScannerModule.getPermissionsAsync();
74 }
75
76 static async requestPermissionsAsync(): Promise<PermissionResponse> {
77 return ExpoBarCodeScannerModule.requestPermissionsAsync();
78 }
79
80 static async scanFromURLAsync(
81 url: string,
82 barCodeTypes: string[] = Object.values(BarCodeType)
83 ): Promise<BarCodeScannerResult[]> {
84 if (!ExpoBarCodeScannerModule.scanFromURLAsync) {
85 throw new UnavailabilityError('expo-barcode-scanner', 'scanFromURLAsync');
86 }
87 if (Array.isArray(barCodeTypes) && !barCodeTypes.length) {
88 throw new Error('No barCodeTypes specified; provide at least one barCodeType for scanner');
89 }
90
91 if (Platform.OS === 'ios') {
92 if (Array.isArray(barCodeTypes) && !barCodeTypes.includes(BarCodeType.qr)) {
93 // Only QR type is supported on iOS, fail if one tries to use other types
94 throw new Error('Only QR type is supported by scanFromURLAsync() on iOS');
95 }
96 // on iOS use only supported QR type
97 return await ExpoBarCodeScannerModule.scanFromURLAsync(url, [BarCodeType.qr]);
98 }
99
100 // On other platforms, if barCodeTypes is not provided, use all available types
101 return await ExpoBarCodeScannerModule.scanFromURLAsync(url, barCodeTypes);
102 }
103
104 render() {
105 const nativeProps = this.convertNativeProps(this.props);
106 const { onBarCodeScanned } = this.props;
107 return (
108 <ExpoBarCodeScannerView
109 {...nativeProps}
110 onBarCodeScanned={this.onObjectDetected(onBarCodeScanned)}
111 />
112 );
113 }
114
115 onObjectDetected = (callback?: BarCodeScannedCallback) => ({
116 nativeEvent,
117 }: BarCodeEventCallbackArguments) => {
118 const { type } = nativeEvent;
119 if (
120 this.lastEvents[type] &&
121 this.lastEventsTimes[type] &&
122 JSON.stringify(nativeEvent) === this.lastEvents[type] &&
123 Date.now() - this.lastEventsTimes[type] < EVENT_THROTTLE_MS
124 ) {
125 return;
126 }
127
128 if (callback) {
129 callback(nativeEvent);
130 this.lastEventsTimes[type] = new Date();
131 this.lastEvents[type] = JSON.stringify(nativeEvent);
132 }
133 };
134
135 convertNativeProps(props: BarCodeScannerProps) {
136 const newProps = mapValues(props, this.convertProp);
137 return newProps;
138 }
139
140 convertProp(value: any, key: string): any {
141 if (typeof value === 'string' && BarCodeScanner.ConversionTables[key]) {
142 return BarCodeScanner.ConversionTables[key][value];
143 }
144 return value;
145 }
146}
147
148export const { Constants, getPermissionsAsync, requestPermissionsAsync } = BarCodeScanner;