react-native-rectangle-doc-scanner 3.48.0 → 3.50.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.
@@ -60,7 +60,7 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
60
60
  const [rectangleDetected, setRectangleDetected] = (0, react_1.useState)(false);
61
61
  const resolvedGridColor = gridColor ?? overlayColor;
62
62
  const docScannerRef = (0, react_1.useRef)(null);
63
- const manualCapturePending = (0, react_1.useRef)(false);
63
+ const captureModeRef = (0, react_1.useRef)(null);
64
64
  const mergedStrings = (0, react_1.useMemo)(() => ({
65
65
  captureHint: strings?.captureHint,
66
66
  manualHint: strings?.manualHint,
@@ -121,69 +121,52 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
121
121
  croppedPath: document.croppedPath,
122
122
  initialPath: document.initialPath,
123
123
  });
124
+ const captureMode = captureModeRef.current;
125
+ captureModeRef.current = null;
124
126
  const normalizedDoc = normalizeCapturedDocument(document);
125
- // Reset manual capture pending flag BEFORE processing
126
- if (manualCapturePending.current) {
127
- console.log('[FullDocScanner] Resetting manualCapturePending');
128
- manualCapturePending.current = false;
127
+ if (captureMode === 'no-grid') {
128
+ console.log('[FullDocScanner] No grid at capture button press: opening cropper for manual selection');
129
+ await openCropper(normalizedDoc.path);
130
+ return;
129
131
  }
130
- // If grid detected and cropped image exists, show it directly in check_DP
131
132
  if (normalizedDoc.croppedPath) {
132
133
  console.log('[FullDocScanner] Grid detected: using pre-cropped image', normalizedDoc.croppedPath);
133
134
  setCroppedImageData({
134
135
  path: normalizedDoc.croppedPath,
135
136
  });
137
+ return;
136
138
  }
137
- else {
138
- // No grid: open cropper for manual crop
139
- console.log('[FullDocScanner] No grid detected: opening cropper for manual crop', normalizedDoc.path);
140
- await openCropper(normalizedDoc.path);
141
- }
139
+ console.log('[FullDocScanner] Fallback to manual crop (no croppedPath available)');
140
+ await openCropper(normalizedDoc.path);
142
141
  }, [openCropper]);
143
142
  const triggerManualCapture = (0, react_1.useCallback)(() => {
144
143
  console.log('[FullDocScanner] triggerManualCapture called', {
145
144
  processing,
146
- manualCapturePending: manualCapturePending.current,
147
145
  hasRef: !!docScannerRef.current,
146
+ rectangleDetected,
148
147
  });
149
148
  if (processing) {
150
149
  console.log('[FullDocScanner] Already processing, skipping manual capture');
151
150
  return;
152
151
  }
153
- if (manualCapturePending.current) {
154
- console.log('[FullDocScanner] Manual capture already pending, skipping');
155
- return;
156
- }
157
152
  if (!docScannerRef.current) {
158
153
  console.error('[FullDocScanner] DocScanner ref not available');
159
154
  return;
160
155
  }
161
156
  console.log('[FullDocScanner] Starting manual capture');
162
- manualCapturePending.current = true;
163
- try {
164
- const capturePromise = docScannerRef.current.capture();
165
- console.log('[FullDocScanner] Capture promise:', capturePromise);
166
- if (capturePromise && typeof capturePromise.then === 'function') {
167
- capturePromise
168
- .then((result) => {
169
- console.log('[FullDocScanner] Manual capture success:', result);
170
- manualCapturePending.current = false;
171
- })
172
- .catch((error) => {
173
- console.error('[FullDocScanner] Manual capture failed:', error);
174
- manualCapturePending.current = false;
175
- });
176
- }
177
- else {
178
- console.warn('[FullDocScanner] No promise returned from capture()');
179
- manualCapturePending.current = false;
157
+ captureModeRef.current = rectangleDetected ? 'grid' : 'no-grid';
158
+ docScannerRef.current.capture()
159
+ .then((result) => {
160
+ console.log('[FullDocScanner] Manual capture success:', result);
161
+ })
162
+ .catch((error) => {
163
+ captureModeRef.current = null;
164
+ console.error('[FullDocScanner] Manual capture failed:', error);
165
+ if (error instanceof Error && error.message !== 'capture_in_progress') {
166
+ emitError(error, 'Failed to capture image.');
180
167
  }
181
- }
182
- catch (error) {
183
- console.error('[FullDocScanner] Exception during capture:', error);
184
- manualCapturePending.current = false;
185
- }
186
- }, [processing]);
168
+ });
169
+ }, [processing, rectangleDetected, emitError]);
187
170
  const handleGalleryPick = (0, react_1.useCallback)(async () => {
188
171
  console.log('[FullDocScanner] handleGalleryPick called');
189
172
  if (processing || isGalleryOpen) {
@@ -227,6 +210,7 @@ const FullDocScanner = ({ onResult, onClose, detectionConfig, overlayColor = '#3
227
210
  setCroppedImageData(null);
228
211
  setProcessing(false);
229
212
  setRectangleDetected(false);
213
+ captureModeRef.current = null;
230
214
  // Reset DocScanner state
231
215
  if (docScannerRef.current?.reset) {
232
216
  docScannerRef.current.reset();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-rectangle-doc-scanner",
3
- "version": "3.48.0",
3
+ "version": "3.50.0",
4
4
  "description": "Native-backed document scanner for React Native with customizable overlays.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -85,7 +85,7 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
85
85
  const [rectangleDetected, setRectangleDetected] = useState(false);
86
86
  const resolvedGridColor = gridColor ?? overlayColor;
87
87
  const docScannerRef = useRef<DocScannerHandle | null>(null);
88
- const manualCapturePending = useRef(false);
88
+ const captureModeRef = useRef<'grid' | 'no-grid' | null>(null);
89
89
 
90
90
  const mergedStrings = useMemo(
91
91
  () => ({
@@ -165,25 +165,27 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
165
165
  initialPath: document.initialPath,
166
166
  });
167
167
 
168
+ const captureMode = captureModeRef.current;
169
+ captureModeRef.current = null;
170
+
168
171
  const normalizedDoc = normalizeCapturedDocument(document);
169
172
 
170
- // Reset manual capture pending flag BEFORE processing
171
- if (manualCapturePending.current) {
172
- console.log('[FullDocScanner] Resetting manualCapturePending');
173
- manualCapturePending.current = false;
173
+ if (captureMode === 'no-grid') {
174
+ console.log('[FullDocScanner] No grid at capture button press: opening cropper for manual selection');
175
+ await openCropper(normalizedDoc.path);
176
+ return;
174
177
  }
175
178
 
176
- // If grid detected and cropped image exists, show it directly in check_DP
177
179
  if (normalizedDoc.croppedPath) {
178
180
  console.log('[FullDocScanner] Grid detected: using pre-cropped image', normalizedDoc.croppedPath);
179
181
  setCroppedImageData({
180
182
  path: normalizedDoc.croppedPath,
181
183
  });
182
- } else {
183
- // No grid: open cropper for manual crop
184
- console.log('[FullDocScanner] No grid detected: opening cropper for manual crop', normalizedDoc.path);
185
- await openCropper(normalizedDoc.path);
184
+ return;
186
185
  }
186
+
187
+ console.log('[FullDocScanner] Fallback to manual crop (no croppedPath available)');
188
+ await openCropper(normalizedDoc.path);
187
189
  },
188
190
  [openCropper],
189
191
  );
@@ -191,8 +193,8 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
191
193
  const triggerManualCapture = useCallback(() => {
192
194
  console.log('[FullDocScanner] triggerManualCapture called', {
193
195
  processing,
194
- manualCapturePending: manualCapturePending.current,
195
196
  hasRef: !!docScannerRef.current,
197
+ rectangleDetected,
196
198
  });
197
199
 
198
200
  if (processing) {
@@ -200,42 +202,30 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
200
202
  return;
201
203
  }
202
204
 
203
- if (manualCapturePending.current) {
204
- console.log('[FullDocScanner] Manual capture already pending, skipping');
205
- return;
206
- }
207
-
208
205
  if (!docScannerRef.current) {
209
206
  console.error('[FullDocScanner] DocScanner ref not available');
210
207
  return;
211
208
  }
212
209
 
213
210
  console.log('[FullDocScanner] Starting manual capture');
214
- manualCapturePending.current = true;
215
211
 
216
- try {
217
- const capturePromise = docScannerRef.current.capture();
218
- console.log('[FullDocScanner] Capture promise:', capturePromise);
219
-
220
- if (capturePromise && typeof capturePromise.then === 'function') {
221
- capturePromise
222
- .then((result) => {
223
- console.log('[FullDocScanner] Manual capture success:', result);
224
- manualCapturePending.current = false;
225
- })
226
- .catch((error: unknown) => {
227
- console.error('[FullDocScanner] Manual capture failed:', error);
228
- manualCapturePending.current = false;
229
- });
230
- } else {
231
- console.warn('[FullDocScanner] No promise returned from capture()');
232
- manualCapturePending.current = false;
233
- }
234
- } catch (error) {
235
- console.error('[FullDocScanner] Exception during capture:', error);
236
- manualCapturePending.current = false;
237
- }
238
- }, [processing]);
212
+ captureModeRef.current = rectangleDetected ? 'grid' : 'no-grid';
213
+
214
+ docScannerRef.current.capture()
215
+ .then((result) => {
216
+ console.log('[FullDocScanner] Manual capture success:', result);
217
+ })
218
+ .catch((error: unknown) => {
219
+ captureModeRef.current = null;
220
+ console.error('[FullDocScanner] Manual capture failed:', error);
221
+ if (error instanceof Error && error.message !== 'capture_in_progress') {
222
+ emitError(
223
+ error,
224
+ 'Failed to capture image.',
225
+ );
226
+ }
227
+ });
228
+ }, [processing, rectangleDetected, emitError]);
239
229
 
240
230
  const handleGalleryPick = useCallback(async () => {
241
231
  console.log('[FullDocScanner] handleGalleryPick called');
@@ -290,6 +280,7 @@ export const FullDocScanner: React.FC<FullDocScannerProps> = ({
290
280
  setCroppedImageData(null);
291
281
  setProcessing(false);
292
282
  setRectangleDetected(false);
283
+ captureModeRef.current = null;
293
284
  // Reset DocScanner state
294
285
  if (docScannerRef.current?.reset) {
295
286
  docScannerRef.current.reset();