react-native-pdf417-scanner 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,16 +1,24 @@
1
1
  # React Native PDF417 Scanner SDK
2
2
 
3
- A comprehensive React Native SDK for live PDF417 barcode scanning using native Android implementation with ZXing library.
3
+ A comprehensive React Native SDK for live PDF417 barcode scanning with **native camera view** using Android implementation and ZXing library.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Live PDF417 Scanning**: Real-time barcode detection using device camera
8
- - **Native Performance**: Optimized native Android implementation with ZXing
9
- - **Camera Management**: Automatic camera permission handling and lifecycle management
10
- - **Advanced Controls**: Autofocus, torch/flashlight control, scan timeout
11
- - **Event-Driven API**: Clean React Native bridge with events and callbacks
12
- - **Error Handling**: Comprehensive error reporting and recovery
13
- - **TypeScript Support**: Full TypeScript definitions included
7
+ - **🎥 Live Camera View**: Real-time camera preview with native Android TextureView
8
+ - **📱 Live PDF417 Scanning**: Real-time barcode detection using device camera
9
+ - **⚡ Native Performance**: Optimized native Android implementation with ZXing
10
+ - **🎛️ Camera Management**: Automatic camera permission handling and lifecycle management
11
+ - **🔦 Advanced Controls**: Autofocus, torch/flashlight control, scan timeout
12
+ - **📡 Event-Driven API**: Clean React Native bridge with events and callbacks
13
+ - **🛡️ Error Handling**: Comprehensive error reporting and recovery
14
+ - **📝 TypeScript Support**: Full TypeScript definitions included
15
+
16
+ ## What's New in v1.2.0
17
+
18
+ - **Native Camera View Component**: Show live camera feed instead of black screen
19
+ - **Real-time Preview**: See exactly what the camera sees while scanning
20
+ - **Overlay Support**: Add custom UI overlays on top of camera view
21
+ - **Better UX**: Professional scanning experience with live preview
14
22
 
15
23
  ## Installation
16
24
 
@@ -65,14 +73,247 @@ add(PDF417ScannerPackage())
65
73
 
66
74
  ## Usage
67
75
 
68
- ### Basic Implementation
76
+ ### Method 1: With Native Camera View (Recommended)
77
+
78
+ ```typescript
79
+ import React, { useEffect, useState } from 'react';
80
+ import { View, Modal, TouchableOpacity, Text, StyleSheet } from 'react-native';
81
+ import PDF417Scanner, {
82
+ PDF417ScanResult,
83
+ PDF417ScanError,
84
+ PDF417CameraView
85
+ } from 'react-native-pdf417-scanner';
86
+
87
+ const ScannerWithCameraView = () => {
88
+ const [showScanner, setShowScanner] = useState(false);
89
+ const [torchEnabled, setTorchEnabled] = useState(false);
90
+ const [cameraReady, setCameraReady] = useState(false);
91
+
92
+ useEffect(() => {
93
+ const scanResultUnsubscribe = PDF417Scanner.onScanResult(handleScanResult);
94
+ const scanErrorUnsubscribe = PDF417Scanner.onScanError(handleScanError);
95
+
96
+ return () => {
97
+ scanResultUnsubscribe();
98
+ scanErrorUnsubscribe();
99
+ };
100
+ }, []);
101
+
102
+ const handleScanResult = (result: PDF417ScanResult) => {
103
+ console.log('Scanned:', result.data);
104
+ setShowScanner(false);
105
+ // Handle scan result
106
+ };
107
+
108
+ const handleScanError = (error: PDF417ScanError) => {
109
+ console.error('Scan error:', error);
110
+ };
111
+
112
+ const startScanning = async () => {
113
+ setShowScanner(true);
114
+ try {
115
+ await PDF417Scanner.startScanning({
116
+ enableAutoFocus: true,
117
+ enableTorch: torchEnabled,
118
+ scanTimeout: 30000,
119
+ enableBeep: true,
120
+ enableVibration: true,
121
+ });
122
+ } catch (error) {
123
+ console.error('Failed to start scanning:', error);
124
+ setShowScanner(false);
125
+ }
126
+ };
127
+
128
+ const stopScanning = async () => {
129
+ try {
130
+ await PDF417Scanner.stopScanning();
131
+ setShowScanner(false);
132
+ setCameraReady(false);
133
+ } catch (error) {
134
+ console.error('Failed to stop scanning:', error);
135
+ }
136
+ };
137
+
138
+ return (
139
+ <View style={styles.container}>
140
+ <TouchableOpacity style={styles.scanButton} onPress={startScanning}>
141
+ <Text style={styles.scanButtonText}>Start Scanning</Text>
142
+ </TouchableOpacity>
143
+
144
+ <Modal visible={showScanner} animationType="slide">
145
+ <View style={styles.scannerContainer}>
146
+ {/* Native Camera View */}
147
+ <PDF417CameraView
148
+ style={styles.cameraView}
149
+ isActive={showScanner}
150
+ torchEnabled={torchEnabled}
151
+ onCameraReady={() => setCameraReady(true)}
152
+ onCameraError={(event) => {
153
+ console.error('Camera error:', event.nativeEvent.error);
154
+ setShowScanner(false);
155
+ }}
156
+ />
157
+
158
+ {/* Overlay UI */}
159
+ <View style={styles.overlay}>
160
+ {/* Header */}
161
+ <View style={styles.header}>
162
+ <TouchableOpacity onPress={stopScanning}>
163
+ <Text style={styles.closeButton}>Close</Text>
164
+ </TouchableOpacity>
165
+ <Text style={styles.title}>Scan PDF417</Text>
166
+ <TouchableOpacity onPress={() => setTorchEnabled(!torchEnabled)}>
167
+ <Text style={styles.torchButton}>
168
+ {torchEnabled ? 'Flash Off' : 'Flash On'}
169
+ </Text>
170
+ </TouchableOpacity>
171
+ </View>
172
+
173
+ {/* Scan Frame */}
174
+ <View style={styles.scanFrame}>
175
+ <View style={styles.frameCorner} />
176
+ <View style={[styles.frameCorner, styles.topRight]} />
177
+ <View style={[styles.frameCorner, styles.bottomLeft]} />
178
+ <View style={[styles.frameCorner, styles.bottomRight]} />
179
+ </View>
180
+
181
+ {/* Instructions */}
182
+ <View style={styles.instructions}>
183
+ <Text style={styles.instructionText}>
184
+ {cameraReady
185
+ ? 'Point camera at PDF417 barcode'
186
+ : 'Starting camera...'}
187
+ </Text>
188
+ </View>
189
+ </View>
190
+ </View>
191
+ </Modal>
192
+ </View>
193
+ );
194
+ };
195
+
196
+ const styles = StyleSheet.create({
197
+ container: {
198
+ flex: 1,
199
+ justifyContent: 'center',
200
+ alignItems: 'center',
201
+ },
202
+ scanButton: {
203
+ backgroundColor: '#2196F3',
204
+ paddingHorizontal: 30,
205
+ paddingVertical: 15,
206
+ borderRadius: 8,
207
+ },
208
+ scanButtonText: {
209
+ color: '#fff',
210
+ fontSize: 16,
211
+ fontWeight: 'bold',
212
+ },
213
+ scannerContainer: {
214
+ flex: 1,
215
+ },
216
+ cameraView: {
217
+ flex: 1,
218
+ },
219
+ overlay: {
220
+ position: 'absolute',
221
+ top: 0,
222
+ left: 0,
223
+ right: 0,
224
+ bottom: 0,
225
+ },
226
+ header: {
227
+ flexDirection: 'row',
228
+ justifyContent: 'space-between',
229
+ alignItems: 'center',
230
+ paddingHorizontal: 20,
231
+ paddingTop: 50,
232
+ paddingBottom: 20,
233
+ backgroundColor: 'rgba(0,0,0,0.7)',
234
+ },
235
+ closeButton: {
236
+ color: '#fff',
237
+ fontSize: 16,
238
+ },
239
+ title: {
240
+ color: '#fff',
241
+ fontSize: 18,
242
+ fontWeight: 'bold',
243
+ },
244
+ torchButton: {
245
+ color: '#fff',
246
+ fontSize: 16,
247
+ },
248
+ scanFrame: {
249
+ position: 'absolute',
250
+ top: '50%',
251
+ left: '50%',
252
+ width: 250,
253
+ height: 150,
254
+ marginTop: -75,
255
+ marginLeft: -125,
256
+ },
257
+ frameCorner: {
258
+ position: 'absolute',
259
+ width: 20,
260
+ height: 20,
261
+ borderColor: '#2196F3',
262
+ borderWidth: 3,
263
+ borderRightColor: 'transparent',
264
+ borderBottomColor: 'transparent',
265
+ },
266
+ topRight: {
267
+ top: 0,
268
+ right: 0,
269
+ borderTopColor: '#2196F3',
270
+ borderRightColor: '#2196F3',
271
+ borderLeftColor: 'transparent',
272
+ borderBottomColor: 'transparent',
273
+ },
274
+ bottomLeft: {
275
+ bottom: 0,
276
+ left: 0,
277
+ borderBottomColor: '#2196F3',
278
+ borderLeftColor: '#2196F3',
279
+ borderTopColor: 'transparent',
280
+ borderRightColor: 'transparent',
281
+ },
282
+ bottomRight: {
283
+ bottom: 0,
284
+ right: 0,
285
+ borderBottomColor: '#2196F3',
286
+ borderRightColor: '#2196F3',
287
+ borderTopColor: 'transparent',
288
+ borderLeftColor: 'transparent',
289
+ },
290
+ instructions: {
291
+ position: 'absolute',
292
+ bottom: 100,
293
+ left: 0,
294
+ right: 0,
295
+ alignItems: 'center',
296
+ },
297
+ instructionText: {
298
+ color: '#fff',
299
+ fontSize: 16,
300
+ textAlign: 'center',
301
+ backgroundColor: 'rgba(0,0,0,0.7)',
302
+ paddingHorizontal: 20,
303
+ paddingVertical: 10,
304
+ borderRadius: 8,
305
+ },
306
+ });
307
+ ```
308
+
309
+ ### Method 2: Basic Implementation (Background Scanning)
69
310
 
70
311
  ```typescript
71
312
  import React, { useEffect, useState } from 'react';
72
313
  import { View, Button, Alert } from 'react-native';
73
314
  import PDF417Scanner, { PDF417ScanResult, PDF417ScanError } from 'react-native-pdf417-scanner';
74
315
 
75
- const ScannerComponent = () => {
316
+ const BasicScannerComponent = () => {
76
317
  const [isScanning, setIsScanning] = useState(false);
77
318
 
78
319
  useEffect(() => {
@@ -139,6 +380,35 @@ const ScannerComponent = () => {
139
380
 
140
381
  ## API Reference
141
382
 
383
+ ### Components
384
+
385
+ #### `PDF417CameraView`
386
+ Native camera view component that displays live camera feed.
387
+
388
+ **Props:**
389
+ ```typescript
390
+ interface PDF417CameraViewProps {
391
+ style?: ViewStyle; // View styling
392
+ isActive?: boolean; // Whether camera should be active
393
+ torchEnabled?: boolean; // Flash/torch state
394
+ onCameraReady?: () => void; // Called when camera is ready
395
+ onCameraError?: (event: { // Called on camera errors
396
+ nativeEvent: { error: string }
397
+ }) => void;
398
+ }
399
+ ```
400
+
401
+ **Example:**
402
+ ```typescript
403
+ <PDF417CameraView
404
+ style={{ flex: 1 }}
405
+ isActive={true}
406
+ torchEnabled={false}
407
+ onCameraReady={() => console.log('Camera ready')}
408
+ onCameraError={(e) => console.log('Error:', e.nativeEvent.error)}
409
+ />
410
+ ```
411
+
142
412
  ### Methods
143
413
 
144
414
  #### `startScanning(config?: PDF417ScannerConfig): Promise<void>`
@@ -0,0 +1,277 @@
1
+ package com.pdf417scanner;
2
+
3
+ import android.content.Context;
4
+ import android.graphics.SurfaceTexture;
5
+ import android.hardware.camera2.CameraAccessException;
6
+ import android.hardware.camera2.CameraCaptureSession;
7
+ import android.hardware.camera2.CameraCharacteristics;
8
+ import android.hardware.camera2.CameraDevice;
9
+ import android.hardware.camera2.CameraManager;
10
+ import android.hardware.camera2.CaptureRequest;
11
+ import android.hardware.camera2.params.StreamConfigurationMap;
12
+ import android.os.Handler;
13
+ import android.os.HandlerThread;
14
+ import android.util.AttributeSet;
15
+ import android.util.Log;
16
+ import android.util.Size;
17
+ import android.view.Surface;
18
+ import android.view.TextureView;
19
+
20
+ import androidx.annotation.NonNull;
21
+
22
+ import java.util.Arrays;
23
+ import java.util.concurrent.Semaphore;
24
+ import java.util.concurrent.TimeUnit;
25
+
26
+ public class PDF417CameraView extends TextureView implements TextureView.SurfaceTextureListener {
27
+ private static final String TAG = "PDF417CameraView";
28
+
29
+ private CameraManager cameraManager;
30
+ private CameraDevice cameraDevice;
31
+ private CameraCaptureSession captureSession;
32
+ private HandlerThread backgroundThread;
33
+ private Handler backgroundHandler;
34
+ private Semaphore cameraOpenCloseLock = new Semaphore(1);
35
+ private String cameraId;
36
+ private Size previewSize;
37
+ private boolean torchEnabled = false;
38
+ private CameraReadyListener cameraReadyListener;
39
+
40
+ public interface CameraReadyListener {
41
+ void onCameraReady();
42
+ void onCameraError(String error);
43
+ }
44
+
45
+ public PDF417CameraView(Context context) {
46
+ super(context);
47
+ init();
48
+ }
49
+
50
+ public PDF417CameraView(Context context, AttributeSet attrs) {
51
+ super(context, attrs);
52
+ init();
53
+ }
54
+
55
+ public PDF417CameraView(Context context, AttributeSet attrs, int defStyleAttr) {
56
+ super(context, attrs, defStyleAttr);
57
+ init();
58
+ }
59
+
60
+ private void init() {
61
+ cameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);
62
+ setSurfaceTextureListener(this);
63
+ }
64
+
65
+ public void setCameraReadyListener(CameraReadyListener listener) {
66
+ this.cameraReadyListener = listener;
67
+ }
68
+
69
+ public void startCamera() {
70
+ startBackgroundThread();
71
+ if (isAvailable()) {
72
+ openCamera(getWidth(), getHeight());
73
+ }
74
+ }
75
+
76
+ public void stopCamera() {
77
+ closeCamera();
78
+ stopBackgroundThread();
79
+ }
80
+
81
+ public void setTorchEnabled(boolean enabled) {
82
+ this.torchEnabled = enabled;
83
+ updateTorch();
84
+ }
85
+
86
+ private void updateTorch() {
87
+ if (captureSession != null && cameraDevice != null) {
88
+ try {
89
+ CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
90
+ builder.addTarget(new Surface(getSurfaceTexture()));
91
+ builder.set(CaptureRequest.FLASH_MODE, torchEnabled ?
92
+ CaptureRequest.FLASH_MODE_TORCH : CaptureRequest.FLASH_MODE_OFF);
93
+ captureSession.setRepeatingRequest(builder.build(), null, backgroundHandler);
94
+ } catch (CameraAccessException e) {
95
+ Log.e(TAG, "Error updating torch", e);
96
+ }
97
+ }
98
+ }
99
+
100
+ private void startBackgroundThread() {
101
+ backgroundThread = new HandlerThread("CameraBackground");
102
+ backgroundThread.start();
103
+ backgroundHandler = new Handler(backgroundThread.getLooper());
104
+ }
105
+
106
+ private void stopBackgroundThread() {
107
+ if (backgroundThread != null) {
108
+ backgroundThread.quitSafely();
109
+ try {
110
+ backgroundThread.join();
111
+ backgroundThread = null;
112
+ backgroundHandler = null;
113
+ } catch (InterruptedException e) {
114
+ Log.e(TAG, "Error stopping background thread", e);
115
+ }
116
+ }
117
+ }
118
+
119
+ private void openCamera(int width, int height) {
120
+ try {
121
+ if (!cameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
122
+ throw new RuntimeException("Time out waiting to lock camera opening.");
123
+ }
124
+
125
+ cameraId = selectCamera();
126
+ if (cameraId == null) {
127
+ if (cameraReadyListener != null) {
128
+ cameraReadyListener.onCameraError("No suitable camera found");
129
+ }
130
+ return;
131
+ }
132
+
133
+ cameraManager.openCamera(cameraId, stateCallback, backgroundHandler);
134
+ } catch (Exception e) {
135
+ Log.e(TAG, "Error opening camera", e);
136
+ if (cameraReadyListener != null) {
137
+ cameraReadyListener.onCameraError("Failed to open camera: " + e.getMessage());
138
+ }
139
+ }
140
+ }
141
+
142
+ private String selectCamera() throws CameraAccessException {
143
+ for (String cameraId : cameraManager.getCameraIdList()) {
144
+ CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
145
+ Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
146
+ if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) {
147
+ StreamConfigurationMap map = characteristics.get(
148
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
149
+ if (map != null) {
150
+ previewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class));
151
+ return cameraId;
152
+ }
153
+ }
154
+ }
155
+ return null;
156
+ }
157
+
158
+ private Size chooseOptimalSize(Size[] choices) {
159
+ for (Size size : choices) {
160
+ if (size.getWidth() <= 1920 && size.getHeight() <= 1080) {
161
+ return size;
162
+ }
163
+ }
164
+ return choices[0];
165
+ }
166
+
167
+ private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
168
+ @Override
169
+ public void onOpened(@NonNull CameraDevice camera) {
170
+ cameraOpenCloseLock.release();
171
+ cameraDevice = camera;
172
+ createCameraPreviewSession();
173
+ }
174
+
175
+ @Override
176
+ public void onDisconnected(@NonNull CameraDevice camera) {
177
+ cameraOpenCloseLock.release();
178
+ camera.close();
179
+ cameraDevice = null;
180
+ }
181
+
182
+ @Override
183
+ public void onError(@NonNull CameraDevice camera, int error) {
184
+ cameraOpenCloseLock.release();
185
+ camera.close();
186
+ cameraDevice = null;
187
+ if (cameraReadyListener != null) {
188
+ cameraReadyListener.onCameraError("Camera error: " + error);
189
+ }
190
+ }
191
+ };
192
+
193
+ private void createCameraPreviewSession() {
194
+ try {
195
+ SurfaceTexture texture = getSurfaceTexture();
196
+ texture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
197
+ Surface surface = new Surface(texture);
198
+
199
+ CaptureRequest.Builder builder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
200
+ builder.addTarget(surface);
201
+ builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
202
+
203
+ cameraDevice.createCaptureSession(Arrays.asList(surface),
204
+ new CameraCaptureSession.StateCallback() {
205
+ @Override
206
+ public void onConfigured(@NonNull CameraCaptureSession session) {
207
+ if (cameraDevice == null) return;
208
+
209
+ captureSession = session;
210
+ try {
211
+ session.setRepeatingRequest(builder.build(), null, backgroundHandler);
212
+ if (cameraReadyListener != null) {
213
+ cameraReadyListener.onCameraReady();
214
+ }
215
+ } catch (CameraAccessException e) {
216
+ Log.e(TAG, "Error starting camera preview", e);
217
+ if (cameraReadyListener != null) {
218
+ cameraReadyListener.onCameraError("Failed to start preview");
219
+ }
220
+ }
221
+ }
222
+
223
+ @Override
224
+ public void onConfigureFailed(@NonNull CameraCaptureSession session) {
225
+ if (cameraReadyListener != null) {
226
+ cameraReadyListener.onCameraError("Failed to configure camera");
227
+ }
228
+ }
229
+ }, null);
230
+ } catch (CameraAccessException e) {
231
+ Log.e(TAG, "Error creating camera preview session", e);
232
+ if (cameraReadyListener != null) {
233
+ cameraReadyListener.onCameraError("Failed to create preview session");
234
+ }
235
+ }
236
+ }
237
+
238
+ private void closeCamera() {
239
+ try {
240
+ cameraOpenCloseLock.acquire();
241
+ if (captureSession != null) {
242
+ captureSession.close();
243
+ captureSession = null;
244
+ }
245
+ if (cameraDevice != null) {
246
+ cameraDevice.close();
247
+ cameraDevice = null;
248
+ }
249
+ } catch (InterruptedException e) {
250
+ throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
251
+ } finally {
252
+ cameraOpenCloseLock.release();
253
+ }
254
+ }
255
+
256
+ // TextureView.SurfaceTextureListener methods
257
+ @Override
258
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
259
+ openCamera(width, height);
260
+ }
261
+
262
+ @Override
263
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
264
+ // Handle size changes if needed
265
+ }
266
+
267
+ @Override
268
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
269
+ closeCamera();
270
+ return true;
271
+ }
272
+
273
+ @Override
274
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
275
+ // Handle frame updates if needed
276
+ }
277
+ }
@@ -0,0 +1,95 @@
1
+ package com.pdf417scanner;
2
+
3
+ import android.view.View;
4
+
5
+ import androidx.annotation.NonNull;
6
+ import androidx.annotation.Nullable;
7
+
8
+ import com.facebook.react.bridge.Arguments;
9
+ import com.facebook.react.bridge.ReactContext;
10
+ import com.facebook.react.bridge.WritableMap;
11
+ import com.facebook.react.common.MapBuilder;
12
+ import com.facebook.react.uimanager.SimpleViewManager;
13
+ import com.facebook.react.uimanager.ThemedReactContext;
14
+ import com.facebook.react.uimanager.annotations.ReactProp;
15
+ import com.facebook.react.uimanager.events.RCTEventEmitter;
16
+
17
+ import java.util.Map;
18
+
19
+ public class PDF417CameraViewManager extends SimpleViewManager<PDF417CameraView>
20
+ implements PDF417CameraView.CameraReadyListener {
21
+
22
+ public static final String REACT_CLASS = "PDF417CameraView";
23
+
24
+ private PDF417CameraView currentCameraView;
25
+
26
+ @NonNull
27
+ @Override
28
+ public String getName() {
29
+ return REACT_CLASS;
30
+ }
31
+
32
+ @NonNull
33
+ @Override
34
+ protected PDF417CameraView createViewInstance(@NonNull ThemedReactContext reactContext) {
35
+ PDF417CameraView cameraView = new PDF417CameraView(reactContext);
36
+ cameraView.setCameraReadyListener(this);
37
+ currentCameraView = cameraView;
38
+ return cameraView;
39
+ }
40
+
41
+ @ReactProp(name = "isActive")
42
+ public void setIsActive(PDF417CameraView view, boolean isActive) {
43
+ if (isActive) {
44
+ view.startCamera();
45
+ } else {
46
+ view.stopCamera();
47
+ }
48
+ }
49
+
50
+ @ReactProp(name = "torchEnabled")
51
+ public void setTorchEnabled(PDF417CameraView view, boolean torchEnabled) {
52
+ view.setTorchEnabled(torchEnabled);
53
+ }
54
+
55
+ @Override
56
+ public void onDropViewInstance(@NonNull PDF417CameraView view) {
57
+ view.stopCamera();
58
+ super.onDropViewInstance(view);
59
+ }
60
+
61
+ @Nullable
62
+ @Override
63
+ public Map<String, Object> getExportedCustomDirectEventTypeConstants() {
64
+ return MapBuilder.<String, Object>builder()
65
+ .put("onCameraReady", MapBuilder.of("registrationName", "onCameraReady"))
66
+ .put("onCameraError", MapBuilder.of("registrationName", "onCameraError"))
67
+ .build();
68
+ }
69
+
70
+ // CameraReadyListener implementation
71
+ @Override
72
+ public void onCameraReady() {
73
+ if (currentCameraView != null) {
74
+ WritableMap event = Arguments.createMap();
75
+ ReactContext reactContext = (ReactContext) currentCameraView.getContext();
76
+ reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
77
+ currentCameraView.getId(),
78
+ "onCameraReady",
79
+ event);
80
+ }
81
+ }
82
+
83
+ @Override
84
+ public void onCameraError(String error) {
85
+ if (currentCameraView != null) {
86
+ WritableMap event = Arguments.createMap();
87
+ event.putString("error", error);
88
+ ReactContext reactContext = (ReactContext) currentCameraView.getContext();
89
+ reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
90
+ currentCameraView.getId(),
91
+ "onCameraError",
92
+ event);
93
+ }
94
+ }
95
+ }
@@ -23,6 +23,8 @@ public class PDF417ScannerPackage implements ReactPackage {
23
23
  @NonNull
24
24
  @Override
25
25
  public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
26
- return Collections.emptyList();
26
+ List<ViewManager> viewManagers = new ArrayList<>();
27
+ viewManagers.add(new PDF417CameraViewManager());
28
+ return viewManagers;
27
29
  }
28
30
  }
package/lib/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ViewStyle } from 'react-native';
1
2
  export interface PDF417ScanResult {
2
3
  data: string;
3
4
  format: string;
@@ -14,6 +15,18 @@ export interface PDF417ScannerConfig {
14
15
  enableBeep?: boolean;
15
16
  enableVibration?: boolean;
16
17
  }
18
+ export interface PDF417CameraViewProps {
19
+ style?: ViewStyle;
20
+ isActive?: boolean;
21
+ torchEnabled?: boolean;
22
+ onCameraReady?: () => void;
23
+ onCameraError?: (event: {
24
+ nativeEvent: {
25
+ error: string;
26
+ };
27
+ }) => void;
28
+ }
29
+ export declare const PDF417CameraView: import("react-native").HostComponent<PDF417CameraViewProps>;
17
30
  declare class PDF417ScannerModule {
18
31
  private eventEmitter;
19
32
  private isScanning;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,cAAM,mBAAmB;IACvB,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,UAAU,CAAkB;;IAMpC;;OAEG;IACG,uBAAuB,IAAI,OAAO,CAAC,OAAO,CAAC;IAuBjD;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC;IAgB7C;;OAEG;IACG,aAAa,CAAC,MAAM,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBpE;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC;;OAEG;IACH,mBAAmB,IAAI,OAAO;IAI9B;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtD;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI;IAKtE;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;IAKnE;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;CAIhD;;AAED,wBAAyC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2F,SAAS,EAAE,MAAM,cAAc,CAAC;AAIlI,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,KAAK,IAAI,CAAC;CACrE;AAGD,eAAO,MAAM,gBAAgB,6DAAoE,CAAC;AAElG,cAAM,mBAAmB;IACvB,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,UAAU,CAAkB;;IAMpC;;OAEG;IACG,uBAAuB,IAAI,OAAO,CAAC,OAAO,CAAC;IAuBjD;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC;IAgB7C;;OAEG;IACG,aAAa,CAAC,MAAM,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBpE;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC;;OAEG;IACH,mBAAmB,IAAI,OAAO;IAI9B;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAQtD;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI;IAKtE;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,GAAG,MAAM,IAAI;IAKnE;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;CAIhD;;AAED,wBAAyC"}
package/lib/index.js CHANGED
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PDF417CameraView = void 0;
3
4
  const react_native_1 = require("react-native");
4
5
  const { PDF417Scanner } = react_native_1.NativeModules;
6
+ // Native Camera View Component
7
+ exports.PDF417CameraView = (0, react_native_1.requireNativeComponent)('PDF417CameraView');
5
8
  class PDF417ScannerModule {
6
9
  constructor() {
7
10
  this.isScanning = false;
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,34 +1,38 @@
1
1
  {
2
2
  "name": "react-native-pdf417-scanner",
3
- "version": "1.0.0",
4
- "description": "React Native SDK for PDF417 barcode scanning",
3
+ "version": "1.2.0",
4
+ "description": "React Native SDK for PDF417 barcode scanning with native camera view",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "tsc",
9
- "prepare": "npm run build"
9
+ "prepare": "npm run build",
10
+ "clean": "rm -rf lib"
10
11
  },
11
12
  "keywords": [
12
13
  "react-native",
13
14
  "pdf417",
14
15
  "barcode",
15
16
  "scanner",
16
- "camera"
17
+ "camera",
18
+ "native-camera",
19
+ "android"
17
20
  ],
18
21
  "author": "Your Name",
19
22
  "license": "MIT",
20
23
  "peerDependencies": {
21
- "react": "*",
22
- "react-native": "*"
24
+ "react": ">=16.8.0",
25
+ "react-native": ">=0.60.0"
23
26
  },
24
27
  "devDependencies": {
25
- "@types/react": "^18.0.0",
28
+ "@types/react": "^18.3.0",
26
29
  "@types/react-native": "^0.72.0",
27
30
  "typescript": "^5.0.0"
28
31
  },
29
32
  "files": [
30
33
  "lib/",
31
34
  "android/",
32
- "react-native-pdf417-scanner.podspec"
35
+ "react-native-pdf417-scanner.podspec",
36
+ "README.md"
33
37
  ]
34
- }
38
+ }