rn-document-scanner-vision 1.0.9 → 2.0.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/android/build.gradle +4 -1
- package/android/src/main/java/com/rndocumentscanner/RNDocumentScannerModule.java +153 -64
- package/lib/commonjs/index.js +62 -12
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +62 -12
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/index.d.ts +86 -18
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.tsx +104 -22
package/android/build.gradle
CHANGED
|
@@ -76,5 +76,8 @@ dependencies {
|
|
|
76
76
|
compileOnly "com.facebook.react:react-native:+"
|
|
77
77
|
|
|
78
78
|
implementation "androidx.appcompat:appcompat:1.6.1"
|
|
79
|
-
|
|
79
|
+
|
|
80
|
+
// Google ML Kit Document Scanner
|
|
81
|
+
def mlkitDocumentScannerVersion = safeExtGet('mlkitDocumentScannerVersion', '16.0.0')
|
|
82
|
+
implementation "com.google.android.gms:play-services-mlkit-document-scanner:${mlkitDocumentScannerVersion}"
|
|
80
83
|
}
|
|
@@ -2,7 +2,8 @@ package com.rndocumentscanner;
|
|
|
2
2
|
|
|
3
3
|
import android.app.Activity;
|
|
4
4
|
import android.content.Intent;
|
|
5
|
-
import
|
|
5
|
+
import android.content.IntentSender;
|
|
6
|
+
import android.net.Uri;
|
|
6
7
|
|
|
7
8
|
import com.facebook.react.bridge.ActivityEventListener;
|
|
8
9
|
import com.facebook.react.bridge.Arguments;
|
|
@@ -15,26 +16,23 @@ import com.facebook.react.bridge.ReadableMap;
|
|
|
15
16
|
import com.facebook.react.bridge.WritableArray;
|
|
16
17
|
import com.facebook.react.bridge.WritableMap;
|
|
17
18
|
|
|
18
|
-
import com.
|
|
19
|
-
import com.
|
|
20
|
-
|
|
21
|
-
import
|
|
19
|
+
import com.google.android.gms.common.moduleinstall.ModuleInstall;
|
|
20
|
+
import com.google.android.gms.common.moduleinstall.ModuleInstallClient;
|
|
21
|
+
import com.google.mlkit.vision.documentscanner.GmsDocumentScanner;
|
|
22
|
+
import com.google.mlkit.vision.documentscanner.GmsDocumentScannerOptions;
|
|
23
|
+
import com.google.mlkit.vision.documentscanner.GmsDocumentScanning;
|
|
24
|
+
import com.google.mlkit.vision.documentscanner.GmsDocumentScanningResult;
|
|
22
25
|
|
|
23
26
|
public class RNDocumentScannerModule extends ReactContextBaseJavaModule {
|
|
24
27
|
|
|
25
|
-
private static final int DOCUMENT_SCAN_REQUEST =
|
|
28
|
+
private static final int DOCUMENT_SCAN_REQUEST = 1001;
|
|
26
29
|
private Promise scanPromise;
|
|
27
|
-
private DocumentScanner documentScanner;
|
|
28
30
|
|
|
29
31
|
private final ActivityEventListener activityEventListener = new BaseActivityEventListener() {
|
|
30
32
|
@Override
|
|
31
33
|
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
|
|
32
34
|
if (requestCode == DOCUMENT_SCAN_REQUEST) {
|
|
33
|
-
|
|
34
|
-
// Use a wrapper ActivityResult object
|
|
35
|
-
ActivityResult result = new ActivityResult(resultCode, data);
|
|
36
|
-
documentScanner.handleDocumentScanIntentResult(result);
|
|
37
|
-
}
|
|
35
|
+
handleScanResult(resultCode, data);
|
|
38
36
|
}
|
|
39
37
|
}
|
|
40
38
|
};
|
|
@@ -49,10 +47,64 @@ public class RNDocumentScannerModule extends ReactContextBaseJavaModule {
|
|
|
49
47
|
return "RNDocumentScanner";
|
|
50
48
|
}
|
|
51
49
|
|
|
50
|
+
private void handleScanResult(int resultCode, Intent data) {
|
|
51
|
+
if (scanPromise == null) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (resultCode == Activity.RESULT_OK && data != null) {
|
|
56
|
+
GmsDocumentScanningResult result = GmsDocumentScanningResult.fromActivityResultIntent(data);
|
|
57
|
+
|
|
58
|
+
if (result != null) {
|
|
59
|
+
WritableMap response = Arguments.createMap();
|
|
60
|
+
WritableArray scannedImages = Arguments.createArray();
|
|
61
|
+
|
|
62
|
+
// Get scanned page images
|
|
63
|
+
if (result.getPages() != null) {
|
|
64
|
+
for (GmsDocumentScanningResult.Page page : result.getPages()) {
|
|
65
|
+
Uri imageUri = page.getImageUri();
|
|
66
|
+
scannedImages.pushString(imageUri.toString());
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
response.putArray("scannedImages", scannedImages);
|
|
71
|
+
response.putString("status", "success");
|
|
72
|
+
|
|
73
|
+
// Get PDF if available
|
|
74
|
+
if (result.getPdf() != null) {
|
|
75
|
+
WritableMap pdfInfo = Arguments.createMap();
|
|
76
|
+
pdfInfo.putString("uri", result.getPdf().getUri().toString());
|
|
77
|
+
pdfInfo.putInt("pageCount", result.getPdf().getPageCount());
|
|
78
|
+
response.putMap("pdf", pdfInfo);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
scanPromise.resolve(response);
|
|
82
|
+
} else {
|
|
83
|
+
// No result
|
|
84
|
+
WritableMap response = Arguments.createMap();
|
|
85
|
+
WritableArray emptyArray = Arguments.createArray();
|
|
86
|
+
response.putArray("scannedImages", emptyArray);
|
|
87
|
+
response.putString("status", "cancel");
|
|
88
|
+
scanPromise.resolve(response);
|
|
89
|
+
}
|
|
90
|
+
} else if (resultCode == Activity.RESULT_CANCELED) {
|
|
91
|
+
// User cancelled
|
|
92
|
+
WritableMap response = Arguments.createMap();
|
|
93
|
+
WritableArray emptyArray = Arguments.createArray();
|
|
94
|
+
response.putArray("scannedImages", emptyArray);
|
|
95
|
+
response.putString("status", "cancel");
|
|
96
|
+
scanPromise.resolve(response);
|
|
97
|
+
} else {
|
|
98
|
+
scanPromise.reject("SCAN_ERROR", "Document scan failed with result code: " + resultCode);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
scanPromise = null;
|
|
102
|
+
}
|
|
103
|
+
|
|
52
104
|
@ReactMethod
|
|
53
105
|
public void scanDocument(ReadableMap options, Promise promise) {
|
|
54
106
|
Activity activity = getCurrentActivity();
|
|
55
|
-
|
|
107
|
+
|
|
56
108
|
if (activity == null) {
|
|
57
109
|
promise.reject("NO_ACTIVITY", "Activity doesn't exist");
|
|
58
110
|
return;
|
|
@@ -61,66 +113,103 @@ public class RNDocumentScannerModule extends ReactContextBaseJavaModule {
|
|
|
61
113
|
scanPromise = promise;
|
|
62
114
|
|
|
63
115
|
// Get options with defaults
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
116
|
+
boolean galleryImportAllowed = options.hasKey("galleryImportAllowed") ? options.getBoolean("galleryImportAllowed") : false;
|
|
117
|
+
int pageLimit = options.hasKey("pageLimit") ? options.getInt("pageLimit") : 10;
|
|
118
|
+
String resultFormats = options.hasKey("resultFormats") ? options.getString("resultFormats") : "JPEG";
|
|
119
|
+
String scannerMode = options.hasKey("scannerMode") ? options.getString("scannerMode") : "FULL";
|
|
68
120
|
|
|
69
121
|
try {
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
122
|
+
// Determine scanner mode
|
|
123
|
+
int gmsScannerMode;
|
|
124
|
+
switch (scannerMode.toUpperCase()) {
|
|
125
|
+
case "BASE":
|
|
126
|
+
gmsScannerMode = GmsDocumentScannerOptions.SCANNER_MODE_BASE;
|
|
127
|
+
break;
|
|
128
|
+
case "BASE_WITH_FILTER":
|
|
129
|
+
gmsScannerMode = GmsDocumentScannerOptions.SCANNER_MODE_BASE_WITH_FILTER;
|
|
130
|
+
break;
|
|
131
|
+
case "FULL":
|
|
132
|
+
default:
|
|
133
|
+
gmsScannerMode = GmsDocumentScannerOptions.SCANNER_MODE_FULL;
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Build scanner options
|
|
138
|
+
GmsDocumentScannerOptions.Builder optionsBuilder = new GmsDocumentScannerOptions.Builder()
|
|
139
|
+
.setGalleryImportAllowed(galleryImportAllowed)
|
|
140
|
+
.setPageLimit(pageLimit)
|
|
141
|
+
.setScannerMode(gmsScannerMode);
|
|
142
|
+
|
|
143
|
+
// Set result formats
|
|
144
|
+
switch (resultFormats.toUpperCase()) {
|
|
145
|
+
case "PDF":
|
|
146
|
+
optionsBuilder.setResultFormats(GmsDocumentScannerOptions.RESULT_FORMAT_PDF);
|
|
147
|
+
break;
|
|
148
|
+
case "JPEG_PDF":
|
|
149
|
+
optionsBuilder.setResultFormats(
|
|
150
|
+
GmsDocumentScannerOptions.RESULT_FORMAT_JPEG,
|
|
151
|
+
GmsDocumentScannerOptions.RESULT_FORMAT_PDF
|
|
152
|
+
);
|
|
153
|
+
break;
|
|
154
|
+
case "JPEG":
|
|
155
|
+
default:
|
|
156
|
+
optionsBuilder.setResultFormats(GmsDocumentScannerOptions.RESULT_FORMAT_JPEG);
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
GmsDocumentScanner scanner = GmsDocumentScanning.getClient(optionsBuilder.build());
|
|
161
|
+
|
|
162
|
+
// Get the scan intent and start activity
|
|
163
|
+
scanner.getStartScanIntent(activity)
|
|
164
|
+
.addOnSuccessListener(intentSender -> {
|
|
165
|
+
try {
|
|
166
|
+
activity.startIntentSenderForResult(
|
|
167
|
+
intentSender,
|
|
168
|
+
DOCUMENT_SCAN_REQUEST,
|
|
169
|
+
null,
|
|
170
|
+
0,
|
|
171
|
+
0,
|
|
172
|
+
0
|
|
173
|
+
);
|
|
174
|
+
} catch (IntentSender.SendIntentException e) {
|
|
175
|
+
if (scanPromise != null) {
|
|
176
|
+
scanPromise.reject("INTENT_ERROR", "Failed to start scan intent: " + e.getMessage());
|
|
177
|
+
scanPromise = null;
|
|
178
|
+
}
|
|
96
179
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
() -> {
|
|
100
|
-
// Cancel callback
|
|
101
|
-
WritableMap response = Arguments.createMap();
|
|
102
|
-
WritableArray emptyArray = Arguments.createArray();
|
|
103
|
-
response.putArray("scannedImages", emptyArray);
|
|
104
|
-
response.putString("status", "cancel");
|
|
105
|
-
|
|
180
|
+
})
|
|
181
|
+
.addOnFailureListener(e -> {
|
|
106
182
|
if (scanPromise != null) {
|
|
107
|
-
scanPromise.
|
|
183
|
+
scanPromise.reject("SCAN_ERROR", "Failed to get scan intent: " + e.getMessage());
|
|
108
184
|
scanPromise = null;
|
|
109
185
|
}
|
|
110
|
-
|
|
111
|
-
},
|
|
112
|
-
responseType,
|
|
113
|
-
letUserAdjustCrop,
|
|
114
|
-
maxNumDocuments,
|
|
115
|
-
croppedImageQuality
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
// Launch the document scanner
|
|
119
|
-
Intent scanIntent = documentScanner.createDocumentScanIntent();
|
|
120
|
-
activity.startActivityForResult(scanIntent, DOCUMENT_SCAN_REQUEST);
|
|
186
|
+
});
|
|
121
187
|
|
|
122
188
|
} catch (Exception e) {
|
|
123
189
|
promise.reject("INITIALIZATION_ERROR", "Failed to initialize document scanner: " + e.getMessage());
|
|
190
|
+
scanPromise = null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@ReactMethod
|
|
195
|
+
public void isGoogleDocumentScannerModuleAvailable(Promise promise) {
|
|
196
|
+
try {
|
|
197
|
+
GmsDocumentScanner scanner = GmsDocumentScanning.getClient(
|
|
198
|
+
new GmsDocumentScannerOptions.Builder().build()
|
|
199
|
+
);
|
|
200
|
+
ModuleInstallClient moduleInstallClient = ModuleInstall.getClient(getReactApplicationContext());
|
|
201
|
+
|
|
202
|
+
moduleInstallClient.areModulesAvailable(scanner)
|
|
203
|
+
.addOnSuccessListener(response -> {
|
|
204
|
+
WritableMap result = Arguments.createMap();
|
|
205
|
+
result.putBoolean("available", response.areModulesAvailable());
|
|
206
|
+
promise.resolve(result);
|
|
207
|
+
})
|
|
208
|
+
.addOnFailureListener(e -> {
|
|
209
|
+
promise.reject("CHECK_ERROR", "Failed to check module availability: " + e.getMessage());
|
|
210
|
+
});
|
|
211
|
+
} catch (Exception e) {
|
|
212
|
+
promise.reject("CHECK_ERROR", "Failed to check module availability: " + e.getMessage());
|
|
124
213
|
}
|
|
125
214
|
}
|
|
126
215
|
}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = exports.DocumentScanner = void 0;
|
|
7
7
|
var _reactNative = require("react-native");
|
|
8
|
-
const LINKING_ERROR = 'The package \'
|
|
8
|
+
const LINKING_ERROR = 'The package \'rn-document-scanner-vision\' doesn\'t seem to be linked. Make sure: \n\n' + _reactNative.Platform.select({
|
|
9
9
|
ios: "- You have run 'pod install'\n",
|
|
10
10
|
default: ''
|
|
11
11
|
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
|
|
@@ -15,38 +15,64 @@ const RNDocumentScanner = _reactNative.NativeModules.RNDocumentScanner ? _reactN
|
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Scanner mode options (Android only)
|
|
20
|
+
* - BASE: Basic editing (crop, rotate, reorder pages)
|
|
21
|
+
* - BASE_WITH_FILTER: Adds image filters (grayscale, auto enhancement)
|
|
22
|
+
* - FULL: Adds ML-enabled cleaning (erase stains, fingers, etc.)
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Result format options (Android only)
|
|
27
|
+
* - JPEG: Return JPEG images only
|
|
28
|
+
* - PDF: Return PDF only
|
|
29
|
+
* - JPEG_PDF: Return both JPEG images and PDF
|
|
30
|
+
*/
|
|
31
|
+
|
|
18
32
|
/**
|
|
19
33
|
* Options for document scanning
|
|
20
34
|
*/
|
|
21
35
|
|
|
36
|
+
/**
|
|
37
|
+
* PDF info from scan result (Android only)
|
|
38
|
+
*/
|
|
39
|
+
|
|
22
40
|
/**
|
|
23
41
|
* Response from document scanning
|
|
24
42
|
*/
|
|
25
43
|
|
|
26
44
|
/**
|
|
27
|
-
*
|
|
45
|
+
* Result of module availability check
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Document Scanner module using Google ML Kit
|
|
28
50
|
*/
|
|
29
51
|
const DocumentScanner = exports.DocumentScanner = {
|
|
30
52
|
/**
|
|
31
|
-
* Start document scanning
|
|
53
|
+
* Start document scanning using Google ML Kit Document Scanner (Android)
|
|
54
|
+
* or VisionKit (iOS)
|
|
32
55
|
*
|
|
33
56
|
* @param options - Optional configuration for the document scanner
|
|
34
57
|
* @returns Promise that resolves with scanned document data or rejects with error
|
|
35
58
|
*
|
|
36
59
|
* @example
|
|
37
60
|
* ```typescript
|
|
38
|
-
* import { DocumentScanner } from '
|
|
61
|
+
* import { DocumentScanner } from 'rn-document-scanner-vision';
|
|
39
62
|
*
|
|
40
63
|
* try {
|
|
41
64
|
* const result = await DocumentScanner.scanDocument({
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
65
|
+
* pageLimit: 5,
|
|
66
|
+
* galleryImportAllowed: true,
|
|
67
|
+
* scannerMode: 'FULL',
|
|
68
|
+
* resultFormats: 'JPEG_PDF'
|
|
46
69
|
* });
|
|
47
70
|
*
|
|
48
71
|
* if (result.status === 'success') {
|
|
49
72
|
* console.log('Scanned images:', result.scannedImages);
|
|
73
|
+
* if (result.pdf) {
|
|
74
|
+
* console.log('PDF:', result.pdf.uri);
|
|
75
|
+
* }
|
|
50
76
|
* } else {
|
|
51
77
|
* console.log('User cancelled');
|
|
52
78
|
* }
|
|
@@ -57,16 +83,40 @@ const DocumentScanner = exports.DocumentScanner = {
|
|
|
57
83
|
*/
|
|
58
84
|
scanDocument(options) {
|
|
59
85
|
const defaultOptions = {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
86
|
+
pageLimit: 10,
|
|
87
|
+
galleryImportAllowed: false,
|
|
88
|
+
scannerMode: 'FULL',
|
|
89
|
+
resultFormats: 'JPEG',
|
|
90
|
+
croppedImageQuality: 100
|
|
64
91
|
};
|
|
65
92
|
const finalOptions = {
|
|
66
93
|
...defaultOptions,
|
|
67
94
|
...options
|
|
68
95
|
};
|
|
69
96
|
return RNDocumentScanner.scanDocument(finalOptions);
|
|
97
|
+
},
|
|
98
|
+
/**
|
|
99
|
+
* Check if Google Document Scanner module is available (Android only)
|
|
100
|
+
* The ML Kit Document Scanner models are downloaded on-demand.
|
|
101
|
+
*
|
|
102
|
+
* @returns Promise that resolves with availability status
|
|
103
|
+
* @platform android
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const { available } = await DocumentScanner.isGoogleDocumentScannerModuleAvailable();
|
|
108
|
+
* if (!available) {
|
|
109
|
+
* console.log('Module needs to be downloaded');
|
|
110
|
+
* }
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
isGoogleDocumentScannerModuleAvailable() {
|
|
114
|
+
if (_reactNative.Platform.OS !== 'android') {
|
|
115
|
+
return Promise.resolve({
|
|
116
|
+
available: true
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return RNDocumentScanner.isGoogleDocumentScannerModuleAvailable();
|
|
70
120
|
}
|
|
71
121
|
};
|
|
72
122
|
var _default = exports.default = DocumentScanner;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","RNDocumentScanner","NativeModules","Proxy","get","Error","DocumentScanner","exports","scanDocument","options","defaultOptions","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","RNDocumentScanner","NativeModules","Proxy","get","Error","DocumentScanner","exports","scanDocument","options","defaultOptions","pageLimit","galleryImportAllowed","scannerMode","resultFormats","croppedImageQuality","finalOptions","isGoogleDocumentScannerModuleAvailable","OS","Promise","resolve","available","_default"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,MAAMC,aAAa,GACjB,wFAAwF,GACxFC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,iBAAiB,GAAGC,0BAAa,CAACD,iBAAiB,GACrDC,0BAAa,CAACD,iBAAiB,GAC/B,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACT,aAAa,CAAC;EAChC;AACF,CACF,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;;AAuCA;AACA;AACA;;AAYA;AACA;AACA;;AAkBA;AACA;AACA;;AAQA;AACA;AACA;AACO,MAAMU,eAAe,GAAAC,OAAA,CAAAD,eAAA,GAAG;EAC7B;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEE,YAAYA,CAACC,OAA6B,EAAiC;IACzE,MAAMC,cAAmC,GAAG;MAC1CC,SAAS,EAAE,EAAE;MACbC,oBAAoB,EAAE,KAAK;MAC3BC,WAAW,EAAE,MAAM;MACnBC,aAAa,EAAE,MAAM;MACrBC,mBAAmB,EAAE;IACvB,CAAC;IAED,MAAMC,YAAY,GAAG;MAAE,GAAGN,cAAc;MAAE,GAAGD;IAAQ,CAAC;IAEtD,OAAOR,iBAAiB,CAACO,YAAY,CAACQ,YAAY,CAAC;EACrD,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,sCAAsCA,CAAA,EAAmC;IACvE,IAAIpB,qBAAQ,CAACqB,EAAE,KAAK,SAAS,EAAE;MAC7B,OAAOC,OAAO,CAACC,OAAO,CAAC;QAAEC,SAAS,EAAE;MAAK,CAAC,CAAC;IAC7C;IACA,OAAOpB,iBAAiB,CAACgB,sCAAsC,CAAC,CAAC;EACnE;AACF,CAAC;AAAC,IAAAK,QAAA,GAAAf,OAAA,CAAAP,OAAA,GAEaM,eAAe","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NativeModules, Platform } from 'react-native';
|
|
2
|
-
const LINKING_ERROR = 'The package \'
|
|
2
|
+
const LINKING_ERROR = 'The package \'rn-document-scanner-vision\' doesn\'t seem to be linked. Make sure: \n\n' + Platform.select({
|
|
3
3
|
ios: "- You have run 'pod install'\n",
|
|
4
4
|
default: ''
|
|
5
5
|
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
|
|
@@ -9,38 +9,64 @@ const RNDocumentScanner = NativeModules.RNDocumentScanner ? NativeModules.RNDocu
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Scanner mode options (Android only)
|
|
14
|
+
* - BASE: Basic editing (crop, rotate, reorder pages)
|
|
15
|
+
* - BASE_WITH_FILTER: Adds image filters (grayscale, auto enhancement)
|
|
16
|
+
* - FULL: Adds ML-enabled cleaning (erase stains, fingers, etc.)
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Result format options (Android only)
|
|
21
|
+
* - JPEG: Return JPEG images only
|
|
22
|
+
* - PDF: Return PDF only
|
|
23
|
+
* - JPEG_PDF: Return both JPEG images and PDF
|
|
24
|
+
*/
|
|
25
|
+
|
|
12
26
|
/**
|
|
13
27
|
* Options for document scanning
|
|
14
28
|
*/
|
|
15
29
|
|
|
30
|
+
/**
|
|
31
|
+
* PDF info from scan result (Android only)
|
|
32
|
+
*/
|
|
33
|
+
|
|
16
34
|
/**
|
|
17
35
|
* Response from document scanning
|
|
18
36
|
*/
|
|
19
37
|
|
|
20
38
|
/**
|
|
21
|
-
*
|
|
39
|
+
* Result of module availability check
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Document Scanner module using Google ML Kit
|
|
22
44
|
*/
|
|
23
45
|
export const DocumentScanner = {
|
|
24
46
|
/**
|
|
25
|
-
* Start document scanning
|
|
47
|
+
* Start document scanning using Google ML Kit Document Scanner (Android)
|
|
48
|
+
* or VisionKit (iOS)
|
|
26
49
|
*
|
|
27
50
|
* @param options - Optional configuration for the document scanner
|
|
28
51
|
* @returns Promise that resolves with scanned document data or rejects with error
|
|
29
52
|
*
|
|
30
53
|
* @example
|
|
31
54
|
* ```typescript
|
|
32
|
-
* import { DocumentScanner } from '
|
|
55
|
+
* import { DocumentScanner } from 'rn-document-scanner-vision';
|
|
33
56
|
*
|
|
34
57
|
* try {
|
|
35
58
|
* const result = await DocumentScanner.scanDocument({
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
59
|
+
* pageLimit: 5,
|
|
60
|
+
* galleryImportAllowed: true,
|
|
61
|
+
* scannerMode: 'FULL',
|
|
62
|
+
* resultFormats: 'JPEG_PDF'
|
|
40
63
|
* });
|
|
41
64
|
*
|
|
42
65
|
* if (result.status === 'success') {
|
|
43
66
|
* console.log('Scanned images:', result.scannedImages);
|
|
67
|
+
* if (result.pdf) {
|
|
68
|
+
* console.log('PDF:', result.pdf.uri);
|
|
69
|
+
* }
|
|
44
70
|
* } else {
|
|
45
71
|
* console.log('User cancelled');
|
|
46
72
|
* }
|
|
@@ -51,16 +77,40 @@ export const DocumentScanner = {
|
|
|
51
77
|
*/
|
|
52
78
|
scanDocument(options) {
|
|
53
79
|
const defaultOptions = {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
80
|
+
pageLimit: 10,
|
|
81
|
+
galleryImportAllowed: false,
|
|
82
|
+
scannerMode: 'FULL',
|
|
83
|
+
resultFormats: 'JPEG',
|
|
84
|
+
croppedImageQuality: 100
|
|
58
85
|
};
|
|
59
86
|
const finalOptions = {
|
|
60
87
|
...defaultOptions,
|
|
61
88
|
...options
|
|
62
89
|
};
|
|
63
90
|
return RNDocumentScanner.scanDocument(finalOptions);
|
|
91
|
+
},
|
|
92
|
+
/**
|
|
93
|
+
* Check if Google Document Scanner module is available (Android only)
|
|
94
|
+
* The ML Kit Document Scanner models are downloaded on-demand.
|
|
95
|
+
*
|
|
96
|
+
* @returns Promise that resolves with availability status
|
|
97
|
+
* @platform android
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* const { available } = await DocumentScanner.isGoogleDocumentScannerModuleAvailable();
|
|
102
|
+
* if (!available) {
|
|
103
|
+
* console.log('Module needs to be downloaded');
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
isGoogleDocumentScannerModuleAvailable() {
|
|
108
|
+
if (Platform.OS !== 'android') {
|
|
109
|
+
return Promise.resolve({
|
|
110
|
+
available: true
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return RNDocumentScanner.isGoogleDocumentScannerModuleAvailable();
|
|
64
114
|
}
|
|
65
115
|
};
|
|
66
116
|
export default DocumentScanner;
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","RNDocumentScanner","Proxy","get","Error","DocumentScanner","scanDocument","options","defaultOptions","
|
|
1
|
+
{"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","default","RNDocumentScanner","Proxy","get","Error","DocumentScanner","scanDocument","options","defaultOptions","pageLimit","galleryImportAllowed","scannerMode","resultFormats","croppedImageQuality","finalOptions","isGoogleDocumentScannerModuleAvailable","OS","Promise","resolve","available"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,aAAa,GACjB,wFAAwF,GACxFD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAEjC,MAAMC,iBAAiB,GAAGN,aAAa,CAACM,iBAAiB,GACrDN,aAAa,CAACM,iBAAiB,GAC/B,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACP,aAAa,CAAC;EAChC;AACF,CACF,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;;AAuCA;AACA;AACA;;AAYA;AACA;AACA;;AAkBA;AACA;AACA;;AAQA;AACA;AACA;AACA,OAAO,MAAMQ,eAAe,GAAG;EAC7B;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,YAAYA,CAACC,OAA6B,EAAiC;IACzE,MAAMC,cAAmC,GAAG;MAC1CC,SAAS,EAAE,EAAE;MACbC,oBAAoB,EAAE,KAAK;MAC3BC,WAAW,EAAE,MAAM;MACnBC,aAAa,EAAE,MAAM;MACrBC,mBAAmB,EAAE;IACvB,CAAC;IAED,MAAMC,YAAY,GAAG;MAAE,GAAGN,cAAc;MAAE,GAAGD;IAAQ,CAAC;IAEtD,OAAON,iBAAiB,CAACK,YAAY,CAACQ,YAAY,CAAC;EACrD,CAAC;EAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACEC,sCAAsCA,CAAA,EAAmC;IACvE,IAAInB,QAAQ,CAACoB,EAAE,KAAK,SAAS,EAAE;MAC7B,OAAOC,OAAO,CAACC,OAAO,CAAC;QAAEC,SAAS,EAAE;MAAK,CAAC,CAAC;IAC7C;IACA,OAAOlB,iBAAiB,CAACc,sCAAsC,CAAC,CAAC;EACnE;AACF,CAAC;AAED,eAAeV,eAAe","ignoreList":[]}
|
|
@@ -1,67 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scanner mode options (Android only)
|
|
3
|
+
* - BASE: Basic editing (crop, rotate, reorder pages)
|
|
4
|
+
* - BASE_WITH_FILTER: Adds image filters (grayscale, auto enhancement)
|
|
5
|
+
* - FULL: Adds ML-enabled cleaning (erase stains, fingers, etc.)
|
|
6
|
+
*/
|
|
7
|
+
export type ScannerMode = 'BASE' | 'BASE_WITH_FILTER' | 'FULL';
|
|
8
|
+
/**
|
|
9
|
+
* Result format options (Android only)
|
|
10
|
+
* - JPEG: Return JPEG images only
|
|
11
|
+
* - PDF: Return PDF only
|
|
12
|
+
* - JPEG_PDF: Return both JPEG images and PDF
|
|
13
|
+
*/
|
|
14
|
+
export type ResultFormats = 'JPEG' | 'PDF' | 'JPEG_PDF';
|
|
1
15
|
/**
|
|
2
16
|
* Options for document scanning
|
|
3
17
|
*/
|
|
4
18
|
export interface ScanDocumentOptions {
|
|
5
19
|
/**
|
|
6
|
-
* Maximum number of
|
|
7
|
-
* @default
|
|
20
|
+
* Maximum number of pages to scan (Android)
|
|
21
|
+
* @default 10
|
|
22
|
+
* @platform android
|
|
23
|
+
*/
|
|
24
|
+
pageLimit?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Allow importing from photo gallery (Android)
|
|
27
|
+
* @default false
|
|
28
|
+
* @platform android
|
|
29
|
+
*/
|
|
30
|
+
galleryImportAllowed?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Scanner mode (Android)
|
|
33
|
+
* @default 'FULL'
|
|
8
34
|
* @platform android
|
|
9
35
|
*/
|
|
10
|
-
|
|
36
|
+
scannerMode?: ScannerMode;
|
|
11
37
|
/**
|
|
12
|
-
*
|
|
13
|
-
* @default
|
|
38
|
+
* Result formats (Android)
|
|
39
|
+
* @default 'JPEG'
|
|
14
40
|
* @platform android
|
|
15
41
|
*/
|
|
16
|
-
|
|
42
|
+
resultFormats?: ResultFormats;
|
|
17
43
|
/**
|
|
18
|
-
* Quality of the cropped image (0-100)
|
|
44
|
+
* Quality of the cropped image (0-100) - iOS only
|
|
19
45
|
* @default 100
|
|
46
|
+
* @platform ios
|
|
20
47
|
*/
|
|
21
48
|
croppedImageQuality?: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* PDF info from scan result (Android only)
|
|
52
|
+
*/
|
|
53
|
+
export interface PdfInfo {
|
|
54
|
+
/**
|
|
55
|
+
* URI to the generated PDF file
|
|
56
|
+
*/
|
|
57
|
+
uri: string;
|
|
22
58
|
/**
|
|
23
|
-
*
|
|
24
|
-
* @default 'imageFilePath'
|
|
59
|
+
* Number of pages in the PDF
|
|
25
60
|
*/
|
|
26
|
-
|
|
61
|
+
pageCount: number;
|
|
27
62
|
}
|
|
28
63
|
/**
|
|
29
64
|
* Response from document scanning
|
|
30
65
|
*/
|
|
31
66
|
export interface ScanDocumentResponse {
|
|
32
67
|
/**
|
|
33
|
-
* Array of scanned
|
|
68
|
+
* Array of scanned image URIs
|
|
34
69
|
*/
|
|
35
70
|
scannedImages: string[];
|
|
36
71
|
/**
|
|
37
72
|
* Status of the scan operation
|
|
38
73
|
*/
|
|
39
74
|
status: 'success' | 'cancel';
|
|
75
|
+
/**
|
|
76
|
+
* PDF info if resultFormats includes PDF (Android only)
|
|
77
|
+
*/
|
|
78
|
+
pdf?: PdfInfo;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Result of module availability check
|
|
82
|
+
*/
|
|
83
|
+
export interface ModuleAvailableResult {
|
|
84
|
+
/**
|
|
85
|
+
* Whether the Google Document Scanner module is available
|
|
86
|
+
*/
|
|
87
|
+
available: boolean;
|
|
40
88
|
}
|
|
41
89
|
/**
|
|
42
|
-
* Document Scanner module
|
|
90
|
+
* Document Scanner module using Google ML Kit
|
|
43
91
|
*/
|
|
44
92
|
export declare const DocumentScanner: {
|
|
45
93
|
/**
|
|
46
|
-
* Start document scanning
|
|
94
|
+
* Start document scanning using Google ML Kit Document Scanner (Android)
|
|
95
|
+
* or VisionKit (iOS)
|
|
47
96
|
*
|
|
48
97
|
* @param options - Optional configuration for the document scanner
|
|
49
98
|
* @returns Promise that resolves with scanned document data or rejects with error
|
|
50
99
|
*
|
|
51
100
|
* @example
|
|
52
101
|
* ```typescript
|
|
53
|
-
* import { DocumentScanner } from '
|
|
102
|
+
* import { DocumentScanner } from 'rn-document-scanner-vision';
|
|
54
103
|
*
|
|
55
104
|
* try {
|
|
56
105
|
* const result = await DocumentScanner.scanDocument({
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
106
|
+
* pageLimit: 5,
|
|
107
|
+
* galleryImportAllowed: true,
|
|
108
|
+
* scannerMode: 'FULL',
|
|
109
|
+
* resultFormats: 'JPEG_PDF'
|
|
61
110
|
* });
|
|
62
111
|
*
|
|
63
112
|
* if (result.status === 'success') {
|
|
64
113
|
* console.log('Scanned images:', result.scannedImages);
|
|
114
|
+
* if (result.pdf) {
|
|
115
|
+
* console.log('PDF:', result.pdf.uri);
|
|
116
|
+
* }
|
|
65
117
|
* } else {
|
|
66
118
|
* console.log('User cancelled');
|
|
67
119
|
* }
|
|
@@ -71,6 +123,22 @@ export declare const DocumentScanner: {
|
|
|
71
123
|
* ```
|
|
72
124
|
*/
|
|
73
125
|
scanDocument(options?: ScanDocumentOptions): Promise<ScanDocumentResponse>;
|
|
126
|
+
/**
|
|
127
|
+
* Check if Google Document Scanner module is available (Android only)
|
|
128
|
+
* The ML Kit Document Scanner models are downloaded on-demand.
|
|
129
|
+
*
|
|
130
|
+
* @returns Promise that resolves with availability status
|
|
131
|
+
* @platform android
|
|
132
|
+
*
|
|
133
|
+
* @example
|
|
134
|
+
* ```typescript
|
|
135
|
+
* const { available } = await DocumentScanner.isGoogleDocumentScannerModuleAvailable();
|
|
136
|
+
* if (!available) {
|
|
137
|
+
* console.log('Module needs to be downloaded');
|
|
138
|
+
* }
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
isGoogleDocumentScannerModuleAvailable(): Promise<ModuleAvailableResult>;
|
|
74
142
|
};
|
|
75
143
|
export default DocumentScanner;
|
|
76
144
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAmBA;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAmBA;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,UAAU,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;OAIG;IACH,WAAW,CAAC,EAAE,WAAW,CAAC;IAE1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;IAG9B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,aAAa,EAAE,MAAM,EAAE,CAAC;IAExB;;OAEG;IACH,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAE7B;;OAEG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe;IAC1B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA+BG;2BACoB,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAc1E;;;;;;;;;;;;;;OAcG;8CACuC,OAAO,CAAC,qBAAqB,CAAC;CAMzE,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
package/package.json
CHANGED
package/src/index.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NativeModules, Platform } from 'react-native';
|
|
2
2
|
|
|
3
3
|
const LINKING_ERROR =
|
|
4
|
-
'The package \'
|
|
4
|
+
'The package \'rn-document-scanner-vision\' doesn\'t seem to be linked. Make sure: \n\n' +
|
|
5
5
|
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
|
|
6
6
|
'- You rebuilt the app after installing the package\n' +
|
|
7
7
|
'- You are not using Expo Go\n';
|
|
@@ -17,35 +17,75 @@ const RNDocumentScanner = NativeModules.RNDocumentScanner
|
|
|
17
17
|
}
|
|
18
18
|
);
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Scanner mode options (Android only)
|
|
22
|
+
* - BASE: Basic editing (crop, rotate, reorder pages)
|
|
23
|
+
* - BASE_WITH_FILTER: Adds image filters (grayscale, auto enhancement)
|
|
24
|
+
* - FULL: Adds ML-enabled cleaning (erase stains, fingers, etc.)
|
|
25
|
+
*/
|
|
26
|
+
export type ScannerMode = 'BASE' | 'BASE_WITH_FILTER' | 'FULL';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Result format options (Android only)
|
|
30
|
+
* - JPEG: Return JPEG images only
|
|
31
|
+
* - PDF: Return PDF only
|
|
32
|
+
* - JPEG_PDF: Return both JPEG images and PDF
|
|
33
|
+
*/
|
|
34
|
+
export type ResultFormats = 'JPEG' | 'PDF' | 'JPEG_PDF';
|
|
35
|
+
|
|
20
36
|
/**
|
|
21
37
|
* Options for document scanning
|
|
22
38
|
*/
|
|
23
39
|
export interface ScanDocumentOptions {
|
|
24
40
|
/**
|
|
25
|
-
* Maximum number of
|
|
26
|
-
* @default
|
|
41
|
+
* Maximum number of pages to scan (Android)
|
|
42
|
+
* @default 10
|
|
43
|
+
* @platform android
|
|
44
|
+
*/
|
|
45
|
+
pageLimit?: number;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Allow importing from photo gallery (Android)
|
|
49
|
+
* @default false
|
|
27
50
|
* @platform android
|
|
28
51
|
*/
|
|
29
|
-
|
|
52
|
+
galleryImportAllowed?: boolean;
|
|
30
53
|
|
|
31
54
|
/**
|
|
32
|
-
*
|
|
33
|
-
* @default
|
|
55
|
+
* Scanner mode (Android)
|
|
56
|
+
* @default 'FULL'
|
|
34
57
|
* @platform android
|
|
35
58
|
*/
|
|
36
|
-
|
|
59
|
+
scannerMode?: ScannerMode;
|
|
37
60
|
|
|
38
61
|
/**
|
|
39
|
-
*
|
|
62
|
+
* Result formats (Android)
|
|
63
|
+
* @default 'JPEG'
|
|
64
|
+
* @platform android
|
|
65
|
+
*/
|
|
66
|
+
resultFormats?: ResultFormats;
|
|
67
|
+
|
|
68
|
+
// iOS specific options
|
|
69
|
+
/**
|
|
70
|
+
* Quality of the cropped image (0-100) - iOS only
|
|
40
71
|
* @default 100
|
|
72
|
+
* @platform ios
|
|
41
73
|
*/
|
|
42
74
|
croppedImageQuality?: number;
|
|
75
|
+
}
|
|
43
76
|
|
|
77
|
+
/**
|
|
78
|
+
* PDF info from scan result (Android only)
|
|
79
|
+
*/
|
|
80
|
+
export interface PdfInfo {
|
|
81
|
+
/**
|
|
82
|
+
* URI to the generated PDF file
|
|
83
|
+
*/
|
|
84
|
+
uri: string;
|
|
44
85
|
/**
|
|
45
|
-
*
|
|
46
|
-
* @default 'imageFilePath'
|
|
86
|
+
* Number of pages in the PDF
|
|
47
87
|
*/
|
|
48
|
-
|
|
88
|
+
pageCount: number;
|
|
49
89
|
}
|
|
50
90
|
|
|
51
91
|
/**
|
|
@@ -53,7 +93,7 @@ export interface ScanDocumentOptions {
|
|
|
53
93
|
*/
|
|
54
94
|
export interface ScanDocumentResponse {
|
|
55
95
|
/**
|
|
56
|
-
* Array of scanned
|
|
96
|
+
* Array of scanned image URIs
|
|
57
97
|
*/
|
|
58
98
|
scannedImages: string[];
|
|
59
99
|
|
|
@@ -61,32 +101,51 @@ export interface ScanDocumentResponse {
|
|
|
61
101
|
* Status of the scan operation
|
|
62
102
|
*/
|
|
63
103
|
status: 'success' | 'cancel';
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* PDF info if resultFormats includes PDF (Android only)
|
|
107
|
+
*/
|
|
108
|
+
pdf?: PdfInfo;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Result of module availability check
|
|
113
|
+
*/
|
|
114
|
+
export interface ModuleAvailableResult {
|
|
115
|
+
/**
|
|
116
|
+
* Whether the Google Document Scanner module is available
|
|
117
|
+
*/
|
|
118
|
+
available: boolean;
|
|
64
119
|
}
|
|
65
120
|
|
|
66
121
|
/**
|
|
67
|
-
* Document Scanner module
|
|
122
|
+
* Document Scanner module using Google ML Kit
|
|
68
123
|
*/
|
|
69
124
|
export const DocumentScanner = {
|
|
70
125
|
/**
|
|
71
|
-
* Start document scanning
|
|
126
|
+
* Start document scanning using Google ML Kit Document Scanner (Android)
|
|
127
|
+
* or VisionKit (iOS)
|
|
72
128
|
*
|
|
73
129
|
* @param options - Optional configuration for the document scanner
|
|
74
130
|
* @returns Promise that resolves with scanned document data or rejects with error
|
|
75
131
|
*
|
|
76
132
|
* @example
|
|
77
133
|
* ```typescript
|
|
78
|
-
* import { DocumentScanner } from '
|
|
134
|
+
* import { DocumentScanner } from 'rn-document-scanner-vision';
|
|
79
135
|
*
|
|
80
136
|
* try {
|
|
81
137
|
* const result = await DocumentScanner.scanDocument({
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
138
|
+
* pageLimit: 5,
|
|
139
|
+
* galleryImportAllowed: true,
|
|
140
|
+
* scannerMode: 'FULL',
|
|
141
|
+
* resultFormats: 'JPEG_PDF'
|
|
86
142
|
* });
|
|
87
143
|
*
|
|
88
144
|
* if (result.status === 'success') {
|
|
89
145
|
* console.log('Scanned images:', result.scannedImages);
|
|
146
|
+
* if (result.pdf) {
|
|
147
|
+
* console.log('PDF:', result.pdf.uri);
|
|
148
|
+
* }
|
|
90
149
|
* } else {
|
|
91
150
|
* console.log('User cancelled');
|
|
92
151
|
* }
|
|
@@ -97,16 +156,39 @@ export const DocumentScanner = {
|
|
|
97
156
|
*/
|
|
98
157
|
scanDocument(options?: ScanDocumentOptions): Promise<ScanDocumentResponse> {
|
|
99
158
|
const defaultOptions: ScanDocumentOptions = {
|
|
100
|
-
|
|
101
|
-
|
|
159
|
+
pageLimit: 10,
|
|
160
|
+
galleryImportAllowed: false,
|
|
161
|
+
scannerMode: 'FULL',
|
|
162
|
+
resultFormats: 'JPEG',
|
|
102
163
|
croppedImageQuality: 100,
|
|
103
|
-
responseType: 'imageFilePath',
|
|
104
164
|
};
|
|
105
165
|
|
|
106
166
|
const finalOptions = { ...defaultOptions, ...options };
|
|
107
167
|
|
|
108
168
|
return RNDocumentScanner.scanDocument(finalOptions);
|
|
109
169
|
},
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Check if Google Document Scanner module is available (Android only)
|
|
173
|
+
* The ML Kit Document Scanner models are downloaded on-demand.
|
|
174
|
+
*
|
|
175
|
+
* @returns Promise that resolves with availability status
|
|
176
|
+
* @platform android
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* const { available } = await DocumentScanner.isGoogleDocumentScannerModuleAvailable();
|
|
181
|
+
* if (!available) {
|
|
182
|
+
* console.log('Module needs to be downloaded');
|
|
183
|
+
* }
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
186
|
+
isGoogleDocumentScannerModuleAvailable(): Promise<ModuleAvailableResult> {
|
|
187
|
+
if (Platform.OS !== 'android') {
|
|
188
|
+
return Promise.resolve({ available: true });
|
|
189
|
+
}
|
|
190
|
+
return RNDocumentScanner.isGoogleDocumentScannerModuleAvailable();
|
|
191
|
+
},
|
|
110
192
|
};
|
|
111
193
|
|
|
112
194
|
export default DocumentScanner;
|