react-native-rectangle-doc-scanner 3.65.0 → 3.67.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.
@@ -88,6 +88,18 @@ exports.DocScanner = (0, react_1.forwardRef)(({ onCapture, overlayColor = DEFAUL
88
88
  return Math.min(100, Math.max(0, quality));
89
89
  }, [quality]);
90
90
  const handlePictureTaken = (0, react_1.useCallback)((event) => {
91
+ const captureError = event?.error;
92
+ if (captureError) {
93
+ console.error('[DocScanner] Native capture error received:', captureError);
94
+ captureOriginRef.current = 'auto';
95
+ setIsAutoCapturing(false);
96
+ setDetectedRectangle(null);
97
+ if (captureResolvers.current) {
98
+ captureResolvers.current.reject(new Error(String(captureError)));
99
+ captureResolvers.current = null;
100
+ }
101
+ return;
102
+ }
91
103
  console.log('[DocScanner] handlePictureTaken called with event:', {
92
104
  hasInitialImage: !!event.initialImage,
93
105
  hasCroppedImage: !!event.croppedImage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "3.65.0",
3
+ "version": "3.67.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -150,6 +150,21 @@ export const DocScanner = forwardRef<DocScannerHandle, Props>(
150
150
 
151
151
  const handlePictureTaken = useCallback(
152
152
  (event: PictureEvent) => {
153
+ const captureError = (event as any)?.error;
154
+ if (captureError) {
155
+ console.error('[DocScanner] Native capture error received:', captureError);
156
+ captureOriginRef.current = 'auto';
157
+ setIsAutoCapturing(false);
158
+ setDetectedRectangle(null);
159
+
160
+ if (captureResolvers.current) {
161
+ captureResolvers.current.reject(new Error(String(captureError)));
162
+ captureResolvers.current = null;
163
+ }
164
+
165
+ return;
166
+ }
167
+
153
168
  console.log('[DocScanner] handlePictureTaken called with event:', {
154
169
  hasInitialImage: !!event.initialImage,
155
170
  hasCroppedImage: !!event.croppedImage,
@@ -127,7 +127,28 @@
127
127
  - (void) capture {
128
128
  NSLog(@"[DocumentScanner] capture called");
129
129
  [self captureImageWithCompletionHander:^(UIImage *croppedImage, UIImage *initialImage, CIRectangleFeature *rectangleFeature) {
130
- NSLog(@"[DocumentScanner] captureImageWithCompletionHander callback - croppedImage: %@, initialImage: %@", croppedImage ? @"YES" : @"NO", initialImage ? @"YES" : @"NO");
130
+ NSLog(@"[DocumentScanner] captureImageWithCompletionHander callback - croppedImage: %@, initialImage: %@", croppedImage ? @"YES" : @"NO", initialImage ? @"YES" : @"NO");
131
+
132
+ if (!croppedImage && initialImage) {
133
+ // Use initial image when cropping is not available
134
+ croppedImage = initialImage;
135
+ } else if (!initialImage && croppedImage) {
136
+ // Mirror cropped image so downstream logic continues to work
137
+ initialImage = croppedImage;
138
+ }
139
+
140
+ if (!croppedImage || !initialImage) {
141
+ NSLog(@"[DocumentScanner] capture failed - missing image data");
142
+ if (self.onPictureTaken) {
143
+ self.onPictureTaken(@{ @"error": @"capture_failed" });
144
+ }
145
+
146
+ if (!self.captureMultiple) {
147
+ [self stop];
148
+ }
149
+ return;
150
+ }
151
+
131
152
  if (self.onPictureTaken) {
132
153
  NSLog(@"[DocumentScanner] Calling onPictureTaken");
133
154
  // Use maximum JPEG quality (1.0) or user's quality setting, whichever is higher
@@ -15,6 +15,19 @@
15
15
  #import <ImageIO/ImageIO.h>
16
16
  #import <GLKit/GLKit.h>
17
17
 
18
+ static inline void dispatch_async_main_queue(dispatch_block_t block)
19
+ {
20
+ if (!block) {
21
+ return;
22
+ }
23
+
24
+ if ([NSThread isMainThread]) {
25
+ block();
26
+ } else {
27
+ dispatch_async(dispatch_get_main_queue(), block);
28
+ }
29
+ }
30
+
18
31
  @interface IPDFCameraViewController () <AVCaptureVideoDataOutputSampleBufferDelegate, AVCapturePhotoCaptureDelegate>
19
32
 
20
33
  @property (nonatomic,strong) AVCaptureSession *captureSession;
@@ -47,6 +60,39 @@
47
60
  BOOL _isCapturing;
48
61
  }
49
62
 
63
+ - (void)completeCaptureWithCroppedImage:(UIImage *)croppedImage
64
+ initialImage:(UIImage *)initialImage
65
+ rectangle:(CIRectangleFeature *)rectangleFeature
66
+ error:(NSError *)error
67
+ {
68
+ void (^completionHandler)(UIImage *, UIImage *, CIRectangleFeature *) = self.captureCompletionHandler;
69
+
70
+ dispatch_async_main_queue(^{
71
+ if (error) {
72
+ NSLog(@"[IPDFCameraViewController] Completing capture with error: %@", error.localizedDescription);
73
+ if (completionHandler) {
74
+ completionHandler(nil, nil, nil);
75
+ }
76
+ } else {
77
+ UIImage *resolvedInitial = initialImage ?: croppedImage;
78
+ UIImage *resolvedCropped = croppedImage ?: resolvedInitial;
79
+
80
+ if (!resolvedInitial || !resolvedCropped) {
81
+ NSLog(@"[IPDFCameraViewController] Missing images during completion, sending failure to JS");
82
+ if (completionHandler) {
83
+ completionHandler(nil, nil, nil);
84
+ }
85
+ } else if (completionHandler) {
86
+ completionHandler(resolvedCropped, resolvedInitial, rectangleFeature);
87
+ }
88
+ }
89
+
90
+ self.captureCompletionHandler = nil;
91
+ self->_isCapturing = NO;
92
+ [self hideGLKView:NO completion:nil];
93
+ });
94
+ }
95
+
50
96
  - (void)awakeFromNib
51
97
  {
52
98
  [super awakeFromNib];
@@ -153,7 +199,16 @@
153
199
  [session addOutput:self.photoOutput];
154
200
  NSLog(@"[IPDFCamera] Using AVCapturePhotoOutput (modern API)");
155
201
  } else {
156
- NSLog(@"[IPDFCamera] ERROR: Cannot add AVCapturePhotoOutput");
202
+ NSLog(@"[IPDFCamera] WARNING: Cannot add AVCapturePhotoOutput, falling back to AVCaptureStillImageOutput");
203
+ self.photoOutput = nil;
204
+ // Fallback to legacy API
205
+ self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
206
+ if ([session canAddOutput:self.stillImageOutput]) {
207
+ [session addOutput:self.stillImageOutput];
208
+ NSLog(@"[IPDFCamera] Fallback successful: Using AVCaptureStillImageOutput");
209
+ } else {
210
+ NSLog(@"[IPDFCamera] CRITICAL ERROR: Cannot add any capture output!");
211
+ }
157
212
  }
158
213
  } else {
159
214
  // Fallback for older iOS versions (< iOS 10)
@@ -443,7 +498,10 @@
443
498
 
444
499
  if (!self.captureSession || !self.captureSession.isRunning) {
445
500
  NSLog(@"[IPDFCameraViewController] ERROR: captureSession is not running");
446
- _isCapturing = NO;
501
+ NSError *error = [NSError errorWithDomain:@"IPDFCameraViewController"
502
+ code:-200
503
+ userInfo:@{ NSLocalizedDescriptionKey: @"capture_session_not_running" }];
504
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:error];
447
505
  return;
448
506
  }
449
507
 
@@ -464,24 +522,25 @@
464
522
 
465
523
  // Use modern AVCapturePhotoOutput API (iOS 10+)
466
524
  if (@available(iOS 10.0, *)) {
467
- if (!self.photoOutput) {
468
- NSLog(@"[IPDFCameraViewController] ERROR: photoOutput is nil");
469
- _isCapturing = NO;
470
- self.captureCompletionHandler = nil;
471
- [weakSelf hideGLKView:NO completion:nil];
525
+ if (self.photoOutput) {
526
+ NSLog(@"[IPDFCameraViewController] Using AVCapturePhotoOutput to capture");
527
+ AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings];
528
+ [self.photoOutput capturePhotoWithSettings:settings delegate:self];
472
529
  return;
473
530
  }
474
531
 
475
- NSLog(@"[IPDFCameraViewController] Using AVCapturePhotoOutput to capture");
476
- AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings];
477
- [self.photoOutput capturePhotoWithSettings:settings delegate:self];
478
- } else {
479
- // Fallback to deprecated API for iOS < 10
532
+ NSLog(@"[IPDFCameraViewController] photoOutput is nil, trying fallback to stillImageOutput");
533
+ // Fallback to legacy API if photoOutput is not available
534
+ }
535
+
536
+ // Fallback: Use legacy AVCaptureStillImageOutput (iOS < 10 or when photoOutput failed)
537
+ {
480
538
  if (!self.stillImageOutput) {
481
539
  NSLog(@"[IPDFCameraViewController] ERROR: stillImageOutput is nil");
482
- _isCapturing = NO;
483
- self.captureCompletionHandler = nil;
484
- [weakSelf hideGLKView:NO completion:nil];
540
+ NSError *error = [NSError errorWithDomain:@"IPDFCameraViewController"
541
+ code:-201
542
+ userInfo:@{ NSLocalizedDescriptionKey: @"missing_still_image_output" }];
543
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:error];
485
544
  return;
486
545
  }
487
546
 
@@ -501,9 +560,10 @@
501
560
 
502
561
  if (!videoConnection) {
503
562
  NSLog(@"[IPDFCameraViewController] ERROR: No video connection found");
504
- _isCapturing = NO;
505
- self.captureCompletionHandler = nil;
506
- [weakSelf hideGLKView:NO completion:nil];
563
+ NSError *error = [NSError errorWithDomain:@"IPDFCameraViewController"
564
+ code:-202
565
+ userInfo:@{ NSLocalizedDescriptionKey: @"no_video_connection" }];
566
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:error];
507
567
  return;
508
568
  }
509
569
 
@@ -521,126 +581,155 @@
521
581
 
522
582
  if (error) {
523
583
  NSLog(@"[IPDFCameraViewController] ERROR in didFinishProcessingPhoto: %@", error);
524
- _isCapturing = NO;
525
- self.captureCompletionHandler = nil;
526
- [self hideGLKView:NO completion:nil];
584
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:error];
527
585
  return;
528
586
  }
529
587
 
588
+ // iOS 11+ uses fileDataRepresentation
530
589
  NSData *imageData = [photo fileDataRepresentation];
531
590
  if (!imageData) {
532
591
  NSLog(@"[IPDFCameraViewController] ERROR: Failed to get image data from photo");
533
- _isCapturing = NO;
534
- self.captureCompletionHandler = nil;
535
- [self hideGLKView:NO completion:nil];
592
+ NSError *dataError = [NSError errorWithDomain:@"IPDFCameraViewController"
593
+ code:-203
594
+ userInfo:@{ NSLocalizedDescriptionKey: @"no_image_data_from_photo" }];
595
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:dataError];
536
596
  return;
537
597
  }
538
598
 
599
+ NSLog(@"[IPDFCameraViewController] Got image data from AVCapturePhoto, size: %lu bytes", (unsigned long)imageData.length);
539
600
  [self processImageData:imageData];
540
601
  }
541
602
 
542
603
  // AVCapturePhotoCaptureDelegate method for iOS 10
543
604
  - (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhotoSampleBuffer:(CMSampleBufferRef)photoSampleBuffer previewPhotoSampleBuffer:(CMSampleBufferRef)previewPhotoSampleBuffer resolvedSettings:(AVCaptureResolvedPhotoSettings *)resolvedSettings bracketSettings:(AVCaptureBracketedStillImageSettings *)bracketSettings error:(NSError *)error API_DEPRECATED("Use -captureOutput:didFinishProcessingPhoto:error: instead.", ios(10.0, 11.0)) {
544
605
  NSLog(@"[IPDFCameraViewController] didFinishProcessingPhotoSampleBuffer called (iOS 10)");
545
- [self handleCapturedImageData:photoSampleBuffer error:error];
606
+
607
+ if (error) {
608
+ NSLog(@"[IPDFCameraViewController] ERROR in didFinishProcessingPhotoSampleBuffer: %@", error);
609
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:error];
610
+ return;
611
+ }
612
+
613
+ if (!photoSampleBuffer) {
614
+ NSLog(@"[IPDFCameraViewController] ERROR: photoSampleBuffer is nil");
615
+ NSError *bufferError = [NSError errorWithDomain:@"IPDFCameraViewController"
616
+ code:-204
617
+ userInfo:@{ NSLocalizedDescriptionKey: @"photo_sample_buffer_nil" }];
618
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:bufferError];
619
+ return;
620
+ }
621
+
622
+ // iOS 10: Use AVCapturePhotoOutput's method for converting sample buffer
623
+ NSData *imageData = [AVCapturePhotoOutput JPEGPhotoDataRepresentationForJPEGSampleBuffer:photoSampleBuffer previewPhotoSampleBuffer:previewPhotoSampleBuffer];
624
+
625
+ if (!imageData) {
626
+ NSLog(@"[IPDFCameraViewController] ERROR: Failed to create JPEG data from photo sample buffer");
627
+ NSError *dataError = [NSError errorWithDomain:@"IPDFCameraViewController"
628
+ code:-205
629
+ userInfo:@{ NSLocalizedDescriptionKey: @"jpeg_conversion_failed" }];
630
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:dataError];
631
+ return;
632
+ }
633
+
634
+ NSLog(@"[IPDFCameraViewController] Got image data from photo sample buffer (iOS 10), size: %lu bytes", (unsigned long)imageData.length);
635
+ [self processImageData:imageData];
546
636
  }
547
637
 
638
+ // Helper method for legacy AVCaptureStillImageOutput (iOS < 10)
548
639
  - (void)handleCapturedImageData:(CMSampleBufferRef)sampleBuffer error:(NSError *)error {
549
- NSLog(@"[IPDFCameraViewController] handleCapturedImageData called, error=%@, buffer=%@", error, sampleBuffer ? @"YES" : @"NO");
640
+ NSLog(@"[IPDFCameraViewController] handleCapturedImageData called (legacy), error=%@, buffer=%@", error, sampleBuffer ? @"YES" : @"NO");
550
641
 
551
642
  if (error) {
552
643
  NSLog(@"[IPDFCameraViewController] ERROR capturing image: %@", error);
553
- _isCapturing = NO;
554
- self.captureCompletionHandler = nil;
555
- [self hideGLKView:NO completion:nil];
644
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:error];
556
645
  return;
557
646
  }
558
647
 
559
648
  if (!sampleBuffer) {
560
649
  NSLog(@"[IPDFCameraViewController] ERROR: sampleBuffer is nil");
561
- _isCapturing = NO;
562
- self.captureCompletionHandler = nil;
563
- [self hideGLKView:NO completion:nil];
650
+ NSError *bufferError = [NSError errorWithDomain:@"IPDFCameraViewController"
651
+ code:-206
652
+ userInfo:@{ NSLocalizedDescriptionKey: @"sample_buffer_nil" }];
653
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:bufferError];
564
654
  return;
565
655
  }
566
656
 
657
+ // iOS < 10: Use AVCaptureStillImageOutput's method
567
658
  NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:sampleBuffer];
568
659
 
569
660
  if (!imageData) {
570
- NSLog(@"[IPDFCameraViewController] ERROR: Failed to create image data from sample buffer");
571
- _isCapturing = NO;
572
- self.captureCompletionHandler = nil;
573
- [self hideGLKView:NO completion:nil];
661
+ NSLog(@"[IPDFCameraViewController] ERROR: Failed to create image data from sample buffer (legacy)");
662
+ NSError *dataError = [NSError errorWithDomain:@"IPDFCameraViewController"
663
+ code:-207
664
+ userInfo:@{ NSLocalizedDescriptionKey: @"legacy_sample_conversion_failed" }];
665
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:dataError];
574
666
  return;
575
667
  }
576
668
 
669
+ NSLog(@"[IPDFCameraViewController] Got image data from still image output (legacy), size: %lu bytes", (unsigned long)imageData.length);
577
670
  [self processImageData:imageData];
578
671
  }
579
672
 
580
673
  - (void)processImageData:(NSData *)imageData {
581
674
  NSLog(@"[IPDFCameraViewController] processImageData called, imageData size: %lu bytes", (unsigned long)imageData.length);
582
675
 
583
- __weak typeof(self) weakSelf = self;
584
- void (^completionHandler)(UIImage *, UIImage *, CIRectangleFeature *) = self.captureCompletionHandler;
585
-
586
- if (!completionHandler) {
587
- NSLog(@"[IPDFCameraViewController] ERROR: completionHandler is nil");
588
- _isCapturing = NO;
589
- [self hideGLKView:NO completion:nil];
676
+ if (!imageData || imageData.length == 0) {
677
+ NSError *dataError = [NSError errorWithDomain:@"IPDFCameraViewController"
678
+ code:-208
679
+ userInfo:@{ NSLocalizedDescriptionKey: @"empty_image_data" }];
680
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:dataError];
590
681
  return;
591
682
  }
592
683
 
593
- if (self.cameraViewType == IPDFCameraViewTypeBlackAndWhite || self.isBorderDetectionEnabled)
594
- {
595
- CIImage *enhancedImage = [CIImage imageWithData:imageData];
596
-
597
- if (self.cameraViewType == IPDFCameraViewTypeBlackAndWhite)
598
- {
599
- enhancedImage = [self filteredImageUsingEnhanceFilterOnImage:enhancedImage];
600
- }
601
- else
602
- {
603
- enhancedImage = [self filteredImageUsingContrastFilterOnImage:enhancedImage];
604
- }
605
-
606
- if (self.isBorderDetectionEnabled && rectangleDetectionConfidenceHighEnough(_imageDedectionConfidence))
607
- {
608
- CIRectangleFeature *rectangleFeature = [self biggestRectangleInRectangles:[[self highAccuracyRectangleDetector] featuresInImage:enhancedImage]];
609
-
610
- if (rectangleFeature)
611
- {
612
- enhancedImage = [self correctPerspectiveForImage:enhancedImage withFeatures:rectangleFeature];
684
+ UIImage *initialImage = [UIImage imageWithData:imageData];
685
+ if (!initialImage) {
686
+ NSError *conversionError = [NSError errorWithDomain:@"IPDFCameraViewController"
687
+ code:-209
688
+ userInfo:@{ NSLocalizedDescriptionKey: @"initial_image_conversion_failed" }];
689
+ [self completeCaptureWithCroppedImage:nil initialImage:nil rectangle:nil error:conversionError];
690
+ return;
691
+ }
613
692
 
614
- UIGraphicsBeginImageContext(CGSizeMake(enhancedImage.extent.size.height, enhancedImage.extent.size.width));
615
- [[UIImage imageWithCIImage:enhancedImage scale:1.0 orientation:UIImageOrientationRight] drawInRect:CGRectMake(0,0, enhancedImage.extent.size.height, enhancedImage.extent.size.width)];
616
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
617
- UIImage *initialImage = [UIImage imageWithData:imageData];
618
- UIGraphicsEndImageContext();
693
+ UIImage *croppedImage = initialImage;
694
+ CIRectangleFeature *rectangleFeature = nil;
619
695
 
620
- [weakSelf hideGLKView:NO completion:nil];
621
- completionHandler(image, initialImage, rectangleFeature);
696
+ BOOL shouldEnhance = (self.cameraViewType == IPDFCameraViewTypeBlackAndWhite) || self.isBorderDetectionEnabled;
697
+ if (shouldEnhance) {
698
+ CIImage *processedImage = [CIImage imageWithData:imageData];
699
+ if (!processedImage) {
700
+ NSLog(@"[IPDFCameraViewController] Unable to create CIImage from data, returning original image");
701
+ } else {
702
+ if (self.cameraViewType == IPDFCameraViewTypeBlackAndWhite) {
703
+ processedImage = [self filteredImageUsingEnhanceFilterOnImage:processedImage];
622
704
  } else {
623
- // No rectangle detected, return original image
624
- NSLog(@"[IPDFCameraViewController] No rectangle detected during manual capture, returning original image");
625
- [weakSelf hideGLKView:NO completion:nil];
626
- UIImage *initialImage = [UIImage imageWithData:imageData];
627
- completionHandler(initialImage, initialImage, nil);
705
+ processedImage = [self filteredImageUsingContrastFilterOnImage:processedImage];
706
+ }
707
+
708
+ if (self.isBorderDetectionEnabled && rectangleDetectionConfidenceHighEnough(_imageDedectionConfidence)) {
709
+ CIRectangleFeature *detectedRectangle = [self biggestRectangleInRectangles:[[self highAccuracyRectangleDetector] featuresInImage:processedImage]];
710
+
711
+ if (detectedRectangle) {
712
+ rectangleFeature = detectedRectangle;
713
+ CIImage *correctedImage = [self correctPerspectiveForImage:processedImage withFeatures:detectedRectangle];
714
+
715
+ UIGraphicsBeginImageContext(CGSizeMake(correctedImage.extent.size.height, correctedImage.extent.size.width));
716
+ [[UIImage imageWithCIImage:correctedImage scale:1.0 orientation:UIImageOrientationRight] drawInRect:CGRectMake(0, 0, correctedImage.extent.size.height, correctedImage.extent.size.width)];
717
+ UIImage *perspectiveCorrectedImage = UIGraphicsGetImageFromCurrentImageContext();
718
+ UIGraphicsEndImageContext();
719
+
720
+ if (perspectiveCorrectedImage) {
721
+ croppedImage = perspectiveCorrectedImage;
722
+ } else {
723
+ NSLog(@"[IPDFCameraViewController] Failed to create perspective corrected image, using original");
724
+ }
725
+ } else {
726
+ NSLog(@"[IPDFCameraViewController] No rectangle detected during manual capture, returning original image");
727
+ }
628
728
  }
629
- } else {
630
- [weakSelf hideGLKView:NO completion:nil];
631
- UIImage *initialImage = [UIImage imageWithData:imageData];
632
- completionHandler(initialImage, initialImage, nil);
633
729
  }
634
730
  }
635
- else
636
- {
637
- [weakSelf hideGLKView:NO completion:nil];
638
- UIImage *initialImage = [UIImage imageWithData:imageData];
639
- completionHandler(initialImage, initialImage, nil);
640
- }
641
731
 
642
- _isCapturing = NO;
643
- self.captureCompletionHandler = nil;
732
+ [self completeCaptureWithCroppedImage:croppedImage initialImage:initialImage rectangle:rectangleFeature error:nil];
644
733
  }
645
734
 
646
735
  - (void)hideGLKView:(BOOL)hidden completion:(void(^)())completion
@@ -34,24 +34,37 @@ RCT_EXPORT_VIEW_PROPERTY(quality, float)
34
34
  RCT_EXPORT_VIEW_PROPERTY(brightness, float)
35
35
  RCT_EXPORT_VIEW_PROPERTY(contrast, float)
36
36
 
37
- RCT_EXPORT_METHOD(capture:(nonnull NSNumber *)reactTag) {
37
+ // Main capture method - uses the last created scanner view
38
+ RCT_EXPORT_METHOD(capture:(nullable NSNumber *)reactTag) {
38
39
  NSLog(@"[RNPdfScannerManager] capture called with reactTag: %@", reactTag);
39
40
  dispatch_async(dispatch_get_main_queue(), ^{
40
- UIView *view = [self.bridge.uiManager viewForReactTag:reactTag];
41
- if (!view || ![view isKindOfClass:[DocumentScannerView class]]) {
42
- NSLog(@"[RNPdfScannerManager] Cannot find DocumentScannerView with tag #%@", reactTag);
41
+ DocumentScannerView *targetView = nil;
42
+
43
+ if (reactTag) {
44
+ UIView *view = [self.bridge.uiManager viewForReactTag:reactTag];
45
+ if ([view isKindOfClass:[DocumentScannerView class]]) {
46
+ targetView = (DocumentScannerView *)view;
47
+ self->_scannerView = targetView;
48
+ } else if (view) {
49
+ NSLog(@"[RNPdfScannerManager] View for tag %@ is not DocumentScannerView: %@", reactTag, NSStringFromClass(view.class));
50
+ } else {
51
+ NSLog(@"[RNPdfScannerManager] No view found for tag %@", reactTag);
52
+ }
53
+ }
54
+
55
+ if (!targetView && self->_scannerView) {
56
+ NSLog(@"[RNPdfScannerManager] Falling back to last known scanner view");
57
+ targetView = self->_scannerView;
58
+ }
59
+
60
+ if (!targetView) {
61
+ NSLog(@"[RNPdfScannerManager] ERROR: No scanner view available for capture");
43
62
  return;
44
63
  }
45
- DocumentScannerView *scannerView = (DocumentScannerView *)view;
46
- NSLog(@"[RNPdfScannerManager] Calling capture on view: %@", scannerView);
47
- [scannerView capture];
48
- });
49
- }
50
64
 
51
- // Deprecated - kept for backward compatibility
52
- RCT_EXPORT_METHOD(captureGlobal) {
53
- NSLog(@"[RNPdfScannerManager] captureGlobal called (deprecated), scannerView: %@", _scannerView ? @"YES" : @"NO");
54
- [_scannerView capture];
65
+ NSLog(@"[RNPdfScannerManager] Calling capture on view: %@", targetView);
66
+ [targetView capture];
67
+ });
55
68
  }
56
69
 
57
70
  - (UIView*) view {