react-native-rectangle-doc-scanner 1.13.0 → 1.14.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 +49 -120
- package/dist/DocScanner.d.ts +6 -8
- package/dist/DocScanner.js +55 -108
- package/package.json +4 -2
- package/src/DocScanner.tsx +121 -241
- package/src/external.d.ts +28 -12
- package/android/build.gradle +0 -55
- package/android/consumer-rules.pro +0 -1
- package/android/proguard-rules.pro +0 -1
- package/android/src/main/java/com/reactnativerectangledocscanner/RNRDocScannerModule.kt +0 -37
- package/android/src/main/java/com/reactnativerectangledocscanner/RNRDocScannerPackage.kt +0 -16
- package/android/src/main/java/com/reactnativerectangledocscanner/RNRDocScannerView.kt +0 -568
- package/android/src/main/java/com/reactnativerectangledocscanner/RNRDocScannerViewManager.kt +0 -50
- package/docs/native-module-architecture.md +0 -178
- package/ios/RNRDocScannerModule.swift +0 -49
- package/ios/RNRDocScannerView.swift +0 -694
- package/ios/RNRDocScannerViewManager.m +0 -22
- package/ios/RNRDocScannerViewManager.swift +0 -47
- package/react-native-rectangle-doc-scanner.podspec +0 -22
- package/src/utils/overlay.tsx +0 -208
- package/src/utils/quad.ts +0 -181
- package/src/utils/stability.ts +0 -32
package/src/DocScanner.tsx
CHANGED
|
@@ -5,73 +5,17 @@ import React, {
|
|
|
5
5
|
useImperativeHandle,
|
|
6
6
|
useMemo,
|
|
7
7
|
useRef,
|
|
8
|
-
useState,
|
|
9
8
|
} from 'react';
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
findNodeHandle,
|
|
13
|
-
NativeModules,
|
|
14
|
-
requireNativeComponent,
|
|
15
|
-
StyleSheet,
|
|
16
|
-
TouchableOpacity,
|
|
17
|
-
View,
|
|
18
|
-
} from 'react-native';
|
|
19
|
-
import type { NativeSyntheticEvent } from 'react-native';
|
|
20
|
-
import { Overlay } from './utils/overlay';
|
|
21
|
-
import type { Point } from './types';
|
|
22
|
-
|
|
23
|
-
const MODULE_NAME = 'RNRDocScannerModule';
|
|
24
|
-
const VIEW_NAME = 'RNRDocScannerView';
|
|
25
|
-
|
|
26
|
-
const NativeDocScannerModule = NativeModules[MODULE_NAME];
|
|
27
|
-
|
|
28
|
-
if (!NativeDocScannerModule) {
|
|
29
|
-
const fallbackMessage =
|
|
30
|
-
`The native module '${MODULE_NAME}' is not linked. Make sure you have run pod install, ` +
|
|
31
|
-
`synced Gradle, and rebuilt the app after installing 'react-native-rectangle-doc-scanner'.`;
|
|
32
|
-
throw new Error(fallbackMessage);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
type NativeRectangle = {
|
|
36
|
-
topLeft: Point;
|
|
37
|
-
topRight: Point;
|
|
38
|
-
bottomRight: Point;
|
|
39
|
-
bottomLeft: Point;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
type RectangleEvent = {
|
|
43
|
-
rectangleCoordinates: NativeRectangle | null;
|
|
44
|
-
stableCounter: number;
|
|
45
|
-
frameWidth: number;
|
|
46
|
-
frameHeight: number;
|
|
47
|
-
};
|
|
9
|
+
import { Platform, StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
10
|
+
import DocumentScanner from 'react-native-document-scanner';
|
|
48
11
|
|
|
49
12
|
type PictureEvent = {
|
|
50
13
|
croppedImage?: string | null;
|
|
51
|
-
initialImage?: string;
|
|
14
|
+
initialImage?: string | null;
|
|
52
15
|
width?: number;
|
|
53
16
|
height?: number;
|
|
54
17
|
};
|
|
55
18
|
|
|
56
|
-
type NativeDocScannerProps = {
|
|
57
|
-
style?: object;
|
|
58
|
-
detectionCountBeforeCapture?: number;
|
|
59
|
-
autoCapture?: boolean;
|
|
60
|
-
enableTorch?: boolean;
|
|
61
|
-
quality?: number;
|
|
62
|
-
useBase64?: boolean;
|
|
63
|
-
onRectangleDetect?: (event: NativeSyntheticEvent<RectangleEvent>) => void;
|
|
64
|
-
onPictureTaken?: (event: NativeSyntheticEvent<PictureEvent>) => void;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
type DocScannerHandle = {
|
|
68
|
-
capture: () => Promise<PictureEvent>;
|
|
69
|
-
reset: () => void;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const NativeDocScanner = requireNativeComponent<NativeDocScannerProps>(VIEW_NAME);
|
|
73
|
-
type NativeDocScannerInstance = React.ElementRef<typeof NativeDocScanner>;
|
|
74
|
-
|
|
75
19
|
export interface DetectionConfig {
|
|
76
20
|
processingWidth?: number;
|
|
77
21
|
cannyLowThreshold?: number;
|
|
@@ -82,7 +26,7 @@ export interface DetectionConfig {
|
|
|
82
26
|
}
|
|
83
27
|
|
|
84
28
|
interface Props {
|
|
85
|
-
onCapture?: (photo: { path: string; quad:
|
|
29
|
+
onCapture?: (photo: { path: string; quad: null; width: number; height: number }) => void;
|
|
86
30
|
overlayColor?: string;
|
|
87
31
|
autoCapture?: boolean;
|
|
88
32
|
minStableFrames?: number;
|
|
@@ -94,200 +38,136 @@ interface Props {
|
|
|
94
38
|
gridColor?: string;
|
|
95
39
|
gridLineWidth?: number;
|
|
96
40
|
detectionConfig?: DetectionConfig;
|
|
97
|
-
useNativeOverlay?: boolean;
|
|
98
41
|
}
|
|
99
42
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
onCapture,
|
|
105
|
-
overlayColor = DEFAULT_OVERLAY_COLOR,
|
|
106
|
-
autoCapture = true,
|
|
107
|
-
minStableFrames = 8,
|
|
108
|
-
enableTorch = false,
|
|
109
|
-
quality = 90,
|
|
110
|
-
useBase64 = false,
|
|
111
|
-
children,
|
|
112
|
-
showGrid = true,
|
|
113
|
-
gridColor,
|
|
114
|
-
gridLineWidth = 2,
|
|
115
|
-
useNativeOverlay,
|
|
116
|
-
}, ref) => {
|
|
117
|
-
const viewRef = useRef<NativeDocScannerInstance | null>(null);
|
|
118
|
-
const capturingRef = useRef(false);
|
|
119
|
-
const [quad, setQuad] = useState<Point[] | null>(null);
|
|
120
|
-
const [stable, setStable] = useState(0);
|
|
121
|
-
const [frameSize, setFrameSize] = useState<{ width: number; height: number } | null>(null);
|
|
122
|
-
|
|
123
|
-
const shouldUseNativeOverlay = useMemo(() => {
|
|
124
|
-
if (typeof useNativeOverlay === 'boolean') {
|
|
125
|
-
return useNativeOverlay;
|
|
126
|
-
}
|
|
127
|
-
return Platform.OS === 'ios';
|
|
128
|
-
}, [useNativeOverlay]);
|
|
129
|
-
|
|
130
|
-
const effectiveGridColor = useMemo(
|
|
131
|
-
() => gridColor ?? GRID_COLOR_FALLBACK,
|
|
132
|
-
[gridColor],
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
const ensureViewHandle = useCallback(() => {
|
|
136
|
-
const nodeHandle = findNodeHandle(viewRef.current);
|
|
137
|
-
if (!nodeHandle) {
|
|
138
|
-
throw new Error('Unable to obtain native view handle for DocScanner.');
|
|
139
|
-
}
|
|
140
|
-
return nodeHandle;
|
|
141
|
-
}, []);
|
|
142
|
-
|
|
143
|
-
const resetNativeStability = useCallback(() => {
|
|
144
|
-
try {
|
|
145
|
-
const handle = ensureViewHandle();
|
|
146
|
-
NativeDocScannerModule.reset(handle);
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.warn('[DocScanner] unable to reset native stability', error);
|
|
149
|
-
}
|
|
150
|
-
}, [ensureViewHandle]);
|
|
151
|
-
|
|
152
|
-
const emitCaptureResult = useCallback(
|
|
153
|
-
(payload: PictureEvent) => {
|
|
154
|
-
capturingRef.current = false;
|
|
155
|
-
|
|
156
|
-
const path = payload.croppedImage ?? payload.initialImage;
|
|
157
|
-
if (!path) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
43
|
+
type DocScannerHandle = {
|
|
44
|
+
capture: () => Promise<PictureEvent>;
|
|
45
|
+
reset: () => void;
|
|
46
|
+
};
|
|
160
47
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
48
|
+
const DEFAULT_OVERLAY_COLOR = '#0b7ef4';
|
|
49
|
+
|
|
50
|
+
export const DocScanner = forwardRef<DocScannerHandle, Props>(
|
|
51
|
+
(
|
|
52
|
+
{
|
|
53
|
+
onCapture,
|
|
54
|
+
overlayColor = DEFAULT_OVERLAY_COLOR,
|
|
55
|
+
autoCapture = true,
|
|
56
|
+
minStableFrames = 8,
|
|
57
|
+
enableTorch = false,
|
|
58
|
+
quality = 90,
|
|
59
|
+
useBase64 = false,
|
|
60
|
+
children,
|
|
61
|
+
showGrid = true,
|
|
171
62
|
},
|
|
172
|
-
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (
|
|
182
|
-
|
|
183
|
-
return;
|
|
63
|
+
ref,
|
|
64
|
+
) => {
|
|
65
|
+
const scannerRef = useRef<any>(null);
|
|
66
|
+
const captureResolvers = useRef<{
|
|
67
|
+
resolve: (value: PictureEvent) => void;
|
|
68
|
+
reject: (reason?: unknown) => void;
|
|
69
|
+
} | null>(null);
|
|
70
|
+
|
|
71
|
+
const normalizedQuality = useMemo(() => {
|
|
72
|
+
if (Platform.OS === 'ios') {
|
|
73
|
+
// iOS expects 0-1
|
|
74
|
+
return Math.min(1, Math.max(0, quality / 100));
|
|
184
75
|
}
|
|
76
|
+
return Math.min(100, Math.max(0, quality));
|
|
77
|
+
}, [quality]);
|
|
78
|
+
|
|
79
|
+
const handlePictureTaken = useCallback(
|
|
80
|
+
(event: PictureEvent) => {
|
|
81
|
+
const path = event.croppedImage ?? event.initialImage;
|
|
82
|
+
if (path) {
|
|
83
|
+
onCapture?.({
|
|
84
|
+
path,
|
|
85
|
+
quad: null,
|
|
86
|
+
width: event.width ?? 0,
|
|
87
|
+
height: event.height ?? 0,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (captureResolvers.current) {
|
|
92
|
+
captureResolvers.current.resolve(event);
|
|
93
|
+
captureResolvers.current = null;
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
[onCapture],
|
|
97
|
+
);
|
|
185
98
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
rectangleCoordinates.bottomLeft,
|
|
191
|
-
]);
|
|
192
|
-
|
|
193
|
-
if (autoCapture && stableCounter >= minStableFrames) {
|
|
194
|
-
triggerCapture();
|
|
99
|
+
const handleError = useCallback((error: Error) => {
|
|
100
|
+
if (captureResolvers.current) {
|
|
101
|
+
captureResolvers.current.reject(error);
|
|
102
|
+
captureResolvers.current = null;
|
|
195
103
|
}
|
|
196
|
-
},
|
|
197
|
-
[autoCapture, minStableFrames],
|
|
198
|
-
);
|
|
199
|
-
|
|
200
|
-
const handlePictureTaken = useCallback(
|
|
201
|
-
(event: NativeSyntheticEvent<PictureEvent>) => {
|
|
202
|
-
emitCaptureResult(event.nativeEvent);
|
|
203
|
-
},
|
|
204
|
-
[emitCaptureResult],
|
|
205
|
-
);
|
|
104
|
+
}, []);
|
|
206
105
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
106
|
+
const capture = useCallback((): Promise<PictureEvent> => {
|
|
107
|
+
const instance = scannerRef.current;
|
|
108
|
+
if (!instance || typeof instance.capture !== 'function') {
|
|
109
|
+
return Promise.reject(new Error('DocumentScanner native instance is not ready'));
|
|
110
|
+
}
|
|
111
|
+
if (captureResolvers.current) {
|
|
112
|
+
return Promise.reject(new Error('capture_in_progress'));
|
|
113
|
+
}
|
|
211
114
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
emitCaptureResult(result);
|
|
218
|
-
return result;
|
|
219
|
-
})
|
|
220
|
-
.catch((error: Error) => {
|
|
221
|
-
capturingRef.current = false;
|
|
222
|
-
throw error;
|
|
115
|
+
const result = instance.capture();
|
|
116
|
+
if (result && typeof result.then === 'function') {
|
|
117
|
+
return result.then((payload: PictureEvent) => {
|
|
118
|
+
handlePictureTaken(payload);
|
|
119
|
+
return payload;
|
|
223
120
|
});
|
|
224
|
-
|
|
225
|
-
capturingRef.current = false;
|
|
226
|
-
return Promise.reject(error);
|
|
227
|
-
}
|
|
228
|
-
}, [emitCaptureResult, ensureViewHandle]);
|
|
229
|
-
|
|
230
|
-
const triggerCapture = useCallback(() => {
|
|
231
|
-
if (capturingRef.current) {
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
captureNative().catch((error: Error) => {
|
|
236
|
-
console.warn('[DocScanner] capture failed', error);
|
|
237
|
-
});
|
|
238
|
-
}, [captureNative]);
|
|
239
|
-
|
|
240
|
-
const handleManualCapture = useCallback(() => {
|
|
241
|
-
if (autoCapture) {
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
captureNative().catch((error: Error) => {
|
|
245
|
-
console.warn('[DocScanner] manual capture failed', error);
|
|
246
|
-
});
|
|
247
|
-
}, [autoCapture, captureNative]);
|
|
121
|
+
}
|
|
248
122
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
reset: () => {
|
|
254
|
-
setStable(0);
|
|
255
|
-
resetNativeStability();
|
|
256
|
-
},
|
|
257
|
-
}),
|
|
258
|
-
[captureNative, resetNativeStability],
|
|
259
|
-
);
|
|
123
|
+
return new Promise<PictureEvent>((resolve, reject) => {
|
|
124
|
+
captureResolvers.current = { resolve, reject };
|
|
125
|
+
});
|
|
126
|
+
}, [handlePictureTaken]);
|
|
260
127
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
128
|
+
const handleManualCapture = useCallback(() => {
|
|
129
|
+
if (autoCapture) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
capture().catch((error) => {
|
|
133
|
+
console.warn('[DocScanner] manual capture failed', error);
|
|
134
|
+
});
|
|
135
|
+
}, [autoCapture, capture]);
|
|
136
|
+
|
|
137
|
+
useImperativeHandle(
|
|
138
|
+
ref,
|
|
139
|
+
() => ({
|
|
140
|
+
capture,
|
|
141
|
+
reset: () => {
|
|
142
|
+
if (captureResolvers.current) {
|
|
143
|
+
captureResolvers.current.reject(new Error('reset'));
|
|
144
|
+
captureResolvers.current = null;
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
}),
|
|
148
|
+
[capture],
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<View style={styles.container}>
|
|
153
|
+
<DocumentScanner
|
|
154
|
+
ref={scannerRef}
|
|
155
|
+
style={StyleSheet.absoluteFillObject}
|
|
156
|
+
detectionCountBeforeCapture={minStableFrames}
|
|
157
|
+
overlayColor={overlayColor}
|
|
158
|
+
enableTorch={enableTorch}
|
|
159
|
+
quality={normalizedQuality}
|
|
160
|
+
useBase64={useBase64}
|
|
161
|
+
manualOnly={!autoCapture}
|
|
162
|
+
onPictureTaken={handlePictureTaken}
|
|
163
|
+
onError={handleError}
|
|
282
164
|
/>
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
);
|
|
290
|
-
});
|
|
165
|
+
{!autoCapture && <TouchableOpacity style={styles.button} onPress={handleManualCapture} />}
|
|
166
|
+
{children}
|
|
167
|
+
</View>
|
|
168
|
+
);
|
|
169
|
+
},
|
|
170
|
+
);
|
|
291
171
|
|
|
292
172
|
const styles = StyleSheet.create({
|
|
293
173
|
container: {
|
package/src/external.d.ts
CHANGED
|
@@ -31,18 +31,6 @@ declare module '@shopify/react-native-skia' {
|
|
|
31
31
|
export const Path: ComponentType<PathProps>;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
declare module 'react-native-rectangle-doc-scanner/RNRDocScannerModule' {
|
|
35
|
-
export type NativeCaptureResult = {
|
|
36
|
-
croppedImage?: string | null;
|
|
37
|
-
initialImage?: string;
|
|
38
|
-
width?: number;
|
|
39
|
-
height?: number;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export function capture(viewTag: number): Promise<NativeCaptureResult>;
|
|
43
|
-
export function reset(viewTag: number): void;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
34
|
declare module 'react-native-perspective-image-cropper' {
|
|
47
35
|
import type { ComponentType } from 'react';
|
|
48
36
|
|
|
@@ -69,3 +57,31 @@ declare module 'react-native-perspective-image-cropper' {
|
|
|
69
57
|
const CustomImageCropperDefault: ComponentType<CustomImageCropperProps>;
|
|
70
58
|
export default CustomImageCropperDefault;
|
|
71
59
|
}
|
|
60
|
+
|
|
61
|
+
declare module 'react-native-document-scanner' {
|
|
62
|
+
import type { Component } from 'react';
|
|
63
|
+
import type { ViewStyle } from 'react-native';
|
|
64
|
+
|
|
65
|
+
export type DocumentScannerResult = {
|
|
66
|
+
croppedImage?: string | null;
|
|
67
|
+
initialImage?: string | null;
|
|
68
|
+
width?: number;
|
|
69
|
+
height?: number;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export interface DocumentScannerProps {
|
|
73
|
+
style?: ViewStyle;
|
|
74
|
+
detectionCountBeforeCapture?: number;
|
|
75
|
+
overlayColor?: string;
|
|
76
|
+
enableTorch?: boolean;
|
|
77
|
+
useBase64?: boolean;
|
|
78
|
+
quality?: number;
|
|
79
|
+
manualOnly?: boolean;
|
|
80
|
+
onPictureTaken?: (event: DocumentScannerResult) => void;
|
|
81
|
+
onError?: (error: Error) => void;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default class DocumentScanner extends Component<DocumentScannerProps> {
|
|
85
|
+
capture(): Promise<DocumentScannerResult>;
|
|
86
|
+
}
|
|
87
|
+
}
|
package/android/build.gradle
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
buildscript {
|
|
2
|
-
repositories {
|
|
3
|
-
google()
|
|
4
|
-
mavenCentral()
|
|
5
|
-
}
|
|
6
|
-
dependencies {
|
|
7
|
-
classpath("com.android.tools.build:gradle:8.1.1")
|
|
8
|
-
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10")
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
apply plugin: "com.android.library"
|
|
13
|
-
apply plugin: "org.jetbrains.kotlin.android"
|
|
14
|
-
|
|
15
|
-
android {
|
|
16
|
-
namespace "com.reactnativerectangledocscanner"
|
|
17
|
-
compileSdkVersion 34
|
|
18
|
-
|
|
19
|
-
defaultConfig {
|
|
20
|
-
minSdkVersion 24
|
|
21
|
-
targetSdkVersion 34
|
|
22
|
-
consumerProguardFiles "consumer-rules.pro"
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
buildTypes {
|
|
26
|
-
release {
|
|
27
|
-
minifyEnabled false
|
|
28
|
-
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
compileOptions {
|
|
33
|
-
sourceCompatibility JavaVersion.VERSION_11
|
|
34
|
-
targetCompatibility JavaVersion.VERSION_11
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
kotlinOptions {
|
|
38
|
-
jvmTarget = "11"
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
repositories {
|
|
43
|
-
google()
|
|
44
|
-
mavenCentral()
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
dependencies {
|
|
48
|
-
implementation "com.facebook.react:react-native:+"
|
|
49
|
-
implementation "androidx.camera:camera-core:1.3.1"
|
|
50
|
-
implementation "androidx.camera:camera-camera2:1.3.1"
|
|
51
|
-
implementation "androidx.camera:camera-lifecycle:1.3.1"
|
|
52
|
-
implementation "androidx.camera:camera-view:1.3.1"
|
|
53
|
-
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
|
|
54
|
-
implementation "org.opencv:opencv-android:4.9.0"
|
|
55
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Consumer ProGuard rules will be added once native implementation is complete.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Keep default empty; add rules when native implementation is added.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
package com.reactnativerectangledocscanner
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.Arguments
|
|
4
|
-
import com.facebook.react.bridge.Promise
|
|
5
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
-
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
7
|
-
import com.facebook.react.bridge.ReactMethod
|
|
8
|
-
import com.facebook.react.bridge.UiThreadUtil
|
|
9
|
-
import com.facebook.react.uimanager.UIManagerHelper
|
|
10
|
-
import com.facebook.react.uimanager.events.EventDispatcher
|
|
11
|
-
|
|
12
|
-
class RNRDocScannerModule(
|
|
13
|
-
private val reactContext: ReactApplicationContext,
|
|
14
|
-
) : ReactContextBaseJavaModule(reactContext) {
|
|
15
|
-
|
|
16
|
-
override fun getName() = "RNRDocScannerModule"
|
|
17
|
-
|
|
18
|
-
@ReactMethod
|
|
19
|
-
fun capture(viewTag: Int, promise: Promise) {
|
|
20
|
-
UiThreadUtil.runOnUiThread {
|
|
21
|
-
val view = UIManagerHelper.getView(reactContext, viewTag) as? RNRDocScannerView
|
|
22
|
-
if (view == null) {
|
|
23
|
-
promise.reject("view_not_found", "Unable to locate DocScanner view.")
|
|
24
|
-
return@runOnUiThread
|
|
25
|
-
}
|
|
26
|
-
view.capture(promise)
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
@ReactMethod
|
|
31
|
-
fun reset(viewTag: Int) {
|
|
32
|
-
UiThreadUtil.runOnUiThread {
|
|
33
|
-
val view = UIManagerHelper.getView(reactContext, viewTag) as? RNRDocScannerView
|
|
34
|
-
view?.reset()
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
package com.reactnativerectangledocscanner
|
|
2
|
-
|
|
3
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
-
import com.facebook.react.bridge.ReactPackage
|
|
5
|
-
import com.facebook.react.bridge.NativeModule
|
|
6
|
-
import com.facebook.react.uimanager.ViewManager
|
|
7
|
-
|
|
8
|
-
class RNRDocScannerPackage : ReactPackage {
|
|
9
|
-
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
10
|
-
return listOf(RNRDocScannerModule(reactContext))
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
14
|
-
return listOf(RNRDocScannerViewManager(reactContext))
|
|
15
|
-
}
|
|
16
|
-
}
|