react-native-rectangle-doc-scanner 3.88.0 → 3.89.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.
@@ -308,7 +308,8 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
308
308
  }
309
309
  const imageUri = result.assets[0].uri;
310
310
  console.log('[FullDocScanner] Gallery image selected:', imageUri);
311
- await openCropper(imageUri);
311
+ // Skip waitForModalDismissal for gallery - go directly to cropper
312
+ await openCropper(imageUri, { waitForPickerDismissal: false });
312
313
  }
313
314
  catch (error) {
314
315
  console.error('[FullDocScanner] Gallery pick error:', error);
@@ -423,18 +424,24 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
423
424
  react_1.default.createElement(react_native_1.Text, { style: styles.confirmButtonText }, mergedStrings.confirm))))) : (react_1.default.createElement(react_native_1.View, { style: styles.flex },
424
425
  react_1.default.createElement(DocScanner_1.DocScanner, { ref: docScannerRef, autoCapture: false, overlayColor: overlayColor, showGrid: showGrid, gridColor: resolvedGridColor, gridLineWidth: gridLineWidth, minStableFrames: minStableFrames ?? 6, detectionConfig: detectionConfig, onCapture: handleCapture, onRectangleDetect: handleRectangleDetect, showManualCaptureButton: false, enableTorch: flashEnabled },
425
426
  react_1.default.createElement(react_native_1.View, { style: styles.overlayTop, pointerEvents: "box-none" },
426
- react_1.default.createElement(react_native_1.TouchableOpacity, { style: styles.closeButton, onPress: handleClose, accessibilityLabel: mergedStrings.cancel, accessibilityRole: "button" },
427
- react_1.default.createElement(react_native_1.Text, { style: styles.closeButtonLabel }, "\u00D7"))),
427
+ react_1.default.createElement(react_native_1.TouchableOpacity, { style: [
428
+ styles.iconButton,
429
+ processing && styles.buttonDisabled,
430
+ flashEnabled && styles.flashButtonActive
431
+ ], onPress: handleFlashToggle, disabled: processing, accessibilityLabel: "Toggle flash", accessibilityRole: "button" },
432
+ react_1.default.createElement(react_native_1.View, { style: styles.iconContainer },
433
+ react_1.default.createElement(react_native_1.Text, { style: styles.iconText }, "\u26A1\uFE0F"))),
434
+ react_1.default.createElement(react_native_1.TouchableOpacity, { style: styles.iconButton, onPress: handleClose, accessibilityLabel: mergedStrings.cancel, accessibilityRole: "button" },
435
+ react_1.default.createElement(react_native_1.View, { style: styles.iconContainer },
436
+ react_1.default.createElement(react_native_1.Text, { style: styles.closeIconText }, "\u00D7")))),
428
437
  (mergedStrings.captureHint || mergedStrings.manualHint) && (react_1.default.createElement(react_native_1.View, { style: styles.instructionsContainer, pointerEvents: "none" },
429
438
  react_1.default.createElement(react_native_1.View, { style: styles.instructions },
430
439
  mergedStrings.captureHint && (react_1.default.createElement(react_native_1.Text, { style: styles.captureText }, mergedStrings.captureHint)),
431
440
  mergedStrings.manualHint && (react_1.default.createElement(react_native_1.Text, { style: styles.captureText }, mergedStrings.manualHint))))),
432
441
  react_1.default.createElement(react_native_1.View, { style: styles.shutterContainer, pointerEvents: "box-none" },
433
- react_1.default.createElement(react_native_1.View, { style: styles.leftButtonsContainer },
434
- enableGallery && (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.galleryButton, processing && styles.buttonDisabled], onPress: handleGalleryPick, disabled: processing, accessibilityLabel: mergedStrings.galleryButton, accessibilityRole: "button" },
435
- react_1.default.createElement(react_native_1.Text, { style: styles.galleryButtonText }, "\uD83D\uDCC1"))),
436
- react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.flashButton, processing && styles.buttonDisabled], onPress: handleFlashToggle, disabled: processing, accessibilityLabel: "Toggle flash", accessibilityRole: "button" },
437
- react_1.default.createElement(react_native_1.Text, { style: styles.flashButtonText }, flashEnabled ? '⚡' : '⚡️'))),
442
+ enableGallery && (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.iconButton, processing && styles.buttonDisabled], onPress: handleGalleryPick, disabled: processing, accessibilityLabel: mergedStrings.galleryButton, accessibilityRole: "button" },
443
+ react_1.default.createElement(react_native_1.View, { style: styles.iconContainer },
444
+ react_1.default.createElement(react_native_1.Text, { style: styles.iconText }, "\uD83D\uDDBC\uFE0F")))),
438
445
  react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.shutterButton, processing && styles.buttonDisabled], onPress: triggerManualCapture, disabled: processing, accessibilityLabel: mergedStrings.manualHint, accessibilityRole: "button" },
439
446
  react_1.default.createElement(react_native_1.View, { style: [
440
447
  styles.shutterInner,
@@ -457,7 +464,11 @@ const styles = react_native_1.StyleSheet.create({
457
464
  overlayTop: {
458
465
  position: 'absolute',
459
466
  top: 48,
467
+ left: 24,
460
468
  right: 24,
469
+ flexDirection: 'row',
470
+ justifyContent: 'space-between',
471
+ alignItems: 'center',
461
472
  zIndex: 10,
462
473
  },
463
474
  instructionsContainer: {
@@ -479,28 +490,34 @@ const styles = react_native_1.StyleSheet.create({
479
490
  paddingHorizontal: 40,
480
491
  zIndex: 10,
481
492
  },
482
- leftButtonsContainer: {
483
- flexDirection: 'row',
484
- gap: 12,
485
- alignItems: 'center',
486
- flex: 1,
487
- },
488
493
  rightButtonsPlaceholder: {
489
- flex: 1,
494
+ width: 56,
490
495
  },
491
- closeButton: {
492
- width: 40,
493
- height: 40,
494
- borderRadius: 20,
495
- backgroundColor: 'rgba(0,0,0,0.5)',
496
+ iconButton: {
497
+ width: 44,
498
+ height: 44,
499
+ borderRadius: 22,
500
+ backgroundColor: 'rgba(50,50,50,0.8)',
496
501
  justifyContent: 'center',
497
502
  alignItems: 'center',
503
+ borderWidth: 1,
504
+ borderColor: 'rgba(255,255,255,0.3)',
498
505
  },
499
- closeButtonLabel: {
506
+ iconContainer: {
507
+ justifyContent: 'center',
508
+ alignItems: 'center',
509
+ },
510
+ iconText: {
511
+ fontSize: 22,
512
+ },
513
+ closeIconText: {
514
+ fontSize: 32,
515
+ fontWeight: '300',
500
516
  color: '#fff',
501
- fontSize: 28,
502
- lineHeight: 32,
503
- marginTop: -3,
517
+ },
518
+ flashButtonActive: {
519
+ backgroundColor: 'rgba(255,215,0,0.5)',
520
+ borderColor: '#FFD700',
504
521
  },
505
522
  instructions: {
506
523
  backgroundColor: 'rgba(0,0,0,0.55)',
@@ -513,32 +530,6 @@ const styles = react_native_1.StyleSheet.create({
513
530
  fontSize: 15,
514
531
  textAlign: 'center',
515
532
  },
516
- galleryButton: {
517
- width: 56,
518
- height: 56,
519
- borderRadius: 28,
520
- borderWidth: 3,
521
- borderColor: '#fff',
522
- justifyContent: 'center',
523
- alignItems: 'center',
524
- backgroundColor: 'rgba(255,255,255,0.1)',
525
- },
526
- galleryButtonText: {
527
- fontSize: 24,
528
- },
529
- flashButton: {
530
- width: 56,
531
- height: 56,
532
- borderRadius: 28,
533
- borderWidth: 3,
534
- borderColor: '#fff',
535
- justifyContent: 'center',
536
- alignItems: 'center',
537
- backgroundColor: 'rgba(255,255,255,0.1)',
538
- },
539
- flashButtonText: {
540
- fontSize: 24,
541
- },
542
533
  shutterButton: {
543
534
  width: 80,
544
535
  height: 80,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "3.88.0",
3
+ "version": "3.89.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -412,7 +412,8 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
412
412
  const imageUri = result.assets[0].uri;
413
413
  console.log('[FullDocScanner] Gallery image selected:', imageUri);
414
414
 
415
- await openCropper(imageUri);
415
+ // Skip waitForModalDismissal for gallery - go directly to cropper
416
+ await openCropper(imageUri, { waitForPickerDismissal: false });
416
417
  } catch (error) {
417
418
  console.error('[FullDocScanner] Gallery pick error:', error);
418
419
  setIsGalleryOpen(false);
@@ -578,12 +579,29 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
578
579
  >
579
580
  <View style={styles.overlayTop} pointerEvents="box-none">
580
581
  <TouchableOpacity
581
- style={styles.closeButton}
582
+ style={[
583
+ styles.iconButton,
584
+ processing && styles.buttonDisabled,
585
+ flashEnabled && styles.flashButtonActive
586
+ ]}
587
+ onPress={handleFlashToggle}
588
+ disabled={processing}
589
+ accessibilityLabel="Toggle flash"
590
+ accessibilityRole="button"
591
+ >
592
+ <View style={styles.iconContainer}>
593
+ <Text style={styles.iconText}>⚡️</Text>
594
+ </View>
595
+ </TouchableOpacity>
596
+ <TouchableOpacity
597
+ style={styles.iconButton}
582
598
  onPress={handleClose}
583
599
  accessibilityLabel={mergedStrings.cancel}
584
600
  accessibilityRole="button"
585
601
  >
586
- <Text style={styles.closeButtonLabel}>×</Text>
602
+ <View style={styles.iconContainer}>
603
+ <Text style={styles.closeIconText}>×</Text>
604
+ </View>
587
605
  </TouchableOpacity>
588
606
  </View>
589
607
  {(mergedStrings.captureHint || mergedStrings.manualHint) && (
@@ -599,28 +617,19 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
599
617
  </View>
600
618
  )}
601
619
  <View style={styles.shutterContainer} pointerEvents="box-none">
602
- <View style={styles.leftButtonsContainer}>
603
- {enableGallery && (
604
- <TouchableOpacity
605
- style={[styles.galleryButton, processing && styles.buttonDisabled]}
606
- onPress={handleGalleryPick}
607
- disabled={processing}
608
- accessibilityLabel={mergedStrings.galleryButton}
609
- accessibilityRole="button"
610
- >
611
- <Text style={styles.galleryButtonText}>📁</Text>
612
- </TouchableOpacity>
613
- )}
620
+ {enableGallery && (
614
621
  <TouchableOpacity
615
- style={[styles.flashButton, processing && styles.buttonDisabled]}
616
- onPress={handleFlashToggle}
622
+ style={[styles.iconButton, processing && styles.buttonDisabled]}
623
+ onPress={handleGalleryPick}
617
624
  disabled={processing}
618
- accessibilityLabel="Toggle flash"
625
+ accessibilityLabel={mergedStrings.galleryButton}
619
626
  accessibilityRole="button"
620
627
  >
621
- <Text style={styles.flashButtonText}>{flashEnabled ? '⚡' : '⚡️'}</Text>
628
+ <View style={styles.iconContainer}>
629
+ <Text style={styles.iconText}>🖼️</Text>
630
+ </View>
622
631
  </TouchableOpacity>
623
- </View>
632
+ )}
624
633
  <TouchableOpacity
625
634
  style={[styles.shutterButton, processing && styles.buttonDisabled]}
626
635
  onPress={triggerManualCapture}
@@ -662,7 +671,11 @@ const styles = StyleSheet.create({
662
671
  overlayTop: {
663
672
  position: 'absolute',
664
673
  top: 48,
674
+ left: 24,
665
675
  right: 24,
676
+ flexDirection: 'row',
677
+ justifyContent: 'space-between',
678
+ alignItems: 'center',
666
679
  zIndex: 10,
667
680
  },
668
681
  instructionsContainer: {
@@ -684,28 +697,34 @@ const styles = StyleSheet.create({
684
697
  paddingHorizontal: 40,
685
698
  zIndex: 10,
686
699
  },
687
- leftButtonsContainer: {
688
- flexDirection: 'row',
689
- gap: 12,
690
- alignItems: 'center',
691
- flex: 1,
692
- },
693
700
  rightButtonsPlaceholder: {
694
- flex: 1,
701
+ width: 56,
702
+ },
703
+ iconButton: {
704
+ width: 44,
705
+ height: 44,
706
+ borderRadius: 22,
707
+ backgroundColor: 'rgba(50,50,50,0.8)',
708
+ justifyContent: 'center',
709
+ alignItems: 'center',
710
+ borderWidth: 1,
711
+ borderColor: 'rgba(255,255,255,0.3)',
695
712
  },
696
- closeButton: {
697
- width: 40,
698
- height: 40,
699
- borderRadius: 20,
700
- backgroundColor: 'rgba(0,0,0,0.5)',
713
+ iconContainer: {
701
714
  justifyContent: 'center',
702
715
  alignItems: 'center',
703
716
  },
704
- closeButtonLabel: {
717
+ iconText: {
718
+ fontSize: 22,
719
+ },
720
+ closeIconText: {
721
+ fontSize: 32,
722
+ fontWeight: '300',
705
723
  color: '#fff',
706
- fontSize: 28,
707
- lineHeight: 32,
708
- marginTop: -3,
724
+ },
725
+ flashButtonActive: {
726
+ backgroundColor: 'rgba(255,215,0,0.5)',
727
+ borderColor: '#FFD700',
709
728
  },
710
729
  instructions: {
711
730
  backgroundColor: 'rgba(0,0,0,0.55)',
@@ -718,32 +737,6 @@ const styles = StyleSheet.create({
718
737
  fontSize: 15,
719
738
  textAlign: 'center',
720
739
  },
721
- galleryButton: {
722
- width: 56,
723
- height: 56,
724
- borderRadius: 28,
725
- borderWidth: 3,
726
- borderColor: '#fff',
727
- justifyContent: 'center',
728
- alignItems: 'center',
729
- backgroundColor: 'rgba(255,255,255,0.1)',
730
- },
731
- galleryButtonText: {
732
- fontSize: 24,
733
- },
734
- flashButton: {
735
- width: 56,
736
- height: 56,
737
- borderRadius: 28,
738
- borderWidth: 3,
739
- borderColor: '#fff',
740
- justifyContent: 'center',
741
- alignItems: 'center',
742
- backgroundColor: 'rgba(255,255,255,0.1)',
743
- },
744
- flashButtonText: {
745
- fontSize: 24,
746
- },
747
740
  shutterButton: {
748
741
  width: 80,
749
742
  height: 80,
@@ -3,6 +3,7 @@
3
3
 
4
4
  @implementation DocumentScannerView {
5
5
  BOOL _hasSetupCamera;
6
+ BOOL _cameraStarted;
6
7
  IPDFRectangeType _lastDetectionType;
7
8
  }
8
9
 
@@ -12,6 +13,7 @@
12
13
  [self setEnableBorderDetection:YES];
13
14
  [self setDelegate: self];
14
15
  _hasSetupCamera = NO;
16
+ _cameraStarted = NO;
15
17
  self.manualOnly = NO; // Changed from YES to NO - allow manual capture to work
16
18
  self.detectionCountBeforeCapture = 99999; // High threshold to prevent auto-capture
17
19
  }
@@ -28,25 +30,24 @@
28
30
  [self setupCameraView];
29
31
  [self start];
30
32
  _hasSetupCamera = YES;
31
- } else if (_hasSetupCamera && self.window && !CGRectIsEmpty(self.bounds)) {
32
- // Restart camera if needed (defensive check)
33
- NSLog(@"[DocumentScanner] Layout update, ensuring camera is running");
34
- [self start];
33
+ _cameraStarted = YES;
35
34
  }
36
35
  }
37
36
 
38
37
  - (void)didMoveToWindow {
39
38
  [super didMoveToWindow];
40
- if (self.window && _hasSetupCamera) {
41
- // Restart camera when view is added back to window
39
+ if (self.window && _hasSetupCamera && !_cameraStarted) {
40
+ // Restart camera when view is added back to window (only if it was stopped)
42
41
  NSLog(@"[DocumentScanner] View added to window, restarting camera...");
43
42
  dispatch_async(dispatch_get_main_queue(), ^{
44
43
  [self start];
44
+ self->_cameraStarted = YES;
45
45
  });
46
- } else if (!self.window && _hasSetupCamera) {
46
+ } else if (!self.window && _hasSetupCamera && _cameraStarted) {
47
47
  // Stop camera when view is removed from window
48
48
  NSLog(@"[DocumentScanner] View removed from window, stopping camera");
49
49
  [self stop];
50
+ _cameraStarted = NO;
50
51
  }
51
52
  }
52
53