capacitor-card-scanner 0.0.1
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/CapacitorCardScanner.podspec +17 -0
- package/Package.swift +28 -0
- package/README.md +268 -0
- package/android/build.gradle +64 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/pt/tcgclassifier/cardscanner/CardScanner.java +195 -0
- package/android/src/main/java/pt/tcgclassifier/cardscanner/CardScannerPlugin.java +131 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +296 -0
- package/dist/esm/definitions.d.ts +52 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +19 -0
- package/dist/esm/web.js +86 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +100 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +103 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/CardScannerPlugin/CardScanner.swift +151 -0
- package/ios/Sources/CardScannerPlugin/CardScannerPlugin.swift +119 -0
- package/ios/Tests/CardScannerPluginTests/CardScannerTests.swift +15 -0
- package/package.json +80 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
package pt.tcgclassifier.cardscanner;
|
|
2
|
+
|
|
3
|
+
import android.Manifest;
|
|
4
|
+
import com.getcapacitor.JSObject;
|
|
5
|
+
import com.getcapacitor.PermissionState;
|
|
6
|
+
import com.getcapacitor.Plugin;
|
|
7
|
+
import com.getcapacitor.PluginCall;
|
|
8
|
+
import com.getcapacitor.PluginMethod;
|
|
9
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
10
|
+
import com.getcapacitor.annotation.Permission;
|
|
11
|
+
import com.getcapacitor.annotation.PermissionCallback;
|
|
12
|
+
|
|
13
|
+
@CapacitorPlugin(name = "CardScanner", permissions = { @Permission(strings = { Manifest.permission.CAMERA }, alias = CardScannerPlugin.CAMERA) })
|
|
14
|
+
public class CardScannerPlugin extends Plugin {
|
|
15
|
+
|
|
16
|
+
static final String CAMERA = "camera";
|
|
17
|
+
|
|
18
|
+
private CardScanner implementation;
|
|
19
|
+
|
|
20
|
+
@Override
|
|
21
|
+
public void load() {
|
|
22
|
+
implementation = new CardScanner(getActivity(), getBridge().getWebView());
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@Override
|
|
26
|
+
protected void handleOnDestroy() {
|
|
27
|
+
getActivity().runOnUiThread(() -> implementation.stop());
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@PluginMethod
|
|
31
|
+
public void start(PluginCall call) {
|
|
32
|
+
if (getPermissionState(CAMERA) != PermissionState.GRANTED) {
|
|
33
|
+
requestPermissionForAlias(CAMERA, call, "cameraPermsCallback");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
doStart(call);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@PermissionCallback
|
|
40
|
+
private void cameraPermsCallback(PluginCall call) {
|
|
41
|
+
if (getPermissionState(CAMERA) == PermissionState.GRANTED) {
|
|
42
|
+
doStart(call);
|
|
43
|
+
} else {
|
|
44
|
+
call.reject("Camera permission denied", "PERMISSION_DENIED");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private void doStart(PluginCall call) {
|
|
49
|
+
boolean front = "front".equals(call.getString("position", "rear"));
|
|
50
|
+
getActivity().runOnUiThread(() -> implementation.start(front, voidCallback(call)));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@PluginMethod
|
|
54
|
+
public void stop(PluginCall call) {
|
|
55
|
+
getActivity().runOnUiThread(() -> {
|
|
56
|
+
implementation.stop();
|
|
57
|
+
call.resolve();
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@PluginMethod
|
|
62
|
+
public void flip(PluginCall call) {
|
|
63
|
+
if (!ensureRunning(call)) return;
|
|
64
|
+
getActivity().runOnUiThread(() -> implementation.flip(voidCallback(call)));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@PluginMethod
|
|
68
|
+
public void capture(PluginCall call) {
|
|
69
|
+
if (!ensureRunning(call)) return;
|
|
70
|
+
int quality = Math.max(0, Math.min(100, call.getInt("quality", 85)));
|
|
71
|
+
implementation.capture(
|
|
72
|
+
quality,
|
|
73
|
+
new CardScanner.Callback<>() {
|
|
74
|
+
@Override
|
|
75
|
+
public void onSuccess(CardScanner.Photo photo) {
|
|
76
|
+
JSObject ret = new JSObject();
|
|
77
|
+
ret.put("base64", photo.base64);
|
|
78
|
+
ret.put("width", photo.width);
|
|
79
|
+
ret.put("height", photo.height);
|
|
80
|
+
call.resolve(ret);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@Override
|
|
84
|
+
public void onError(String message, Exception e) {
|
|
85
|
+
call.reject(message, e);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@PluginMethod
|
|
92
|
+
public void setTorch(PluginCall call) {
|
|
93
|
+
if (!ensureRunning(call)) return;
|
|
94
|
+
implementation.setTorch(Boolean.TRUE.equals(call.getBoolean("enabled", false)));
|
|
95
|
+
call.resolve();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@PluginMethod
|
|
99
|
+
public void setZoom(PluginCall call) {
|
|
100
|
+
if (!ensureRunning(call)) return;
|
|
101
|
+
Float ratio = call.getFloat("ratio");
|
|
102
|
+
if (ratio == null) {
|
|
103
|
+
call.reject("Missing 'ratio'");
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
implementation.setZoom(ratio);
|
|
107
|
+
call.resolve();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private boolean ensureRunning(PluginCall call) {
|
|
111
|
+
if (!implementation.isRunning()) {
|
|
112
|
+
call.reject("Camera is not running", "NOT_RUNNING");
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private CardScanner.Callback<Void> voidCallback(PluginCall call) {
|
|
119
|
+
return new CardScanner.Callback<>() {
|
|
120
|
+
@Override
|
|
121
|
+
public void onSuccess(Void result) {
|
|
122
|
+
call.resolve();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@Override
|
|
126
|
+
public void onError(String message, Exception e) {
|
|
127
|
+
call.reject(message, e);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
File without changes
|
package/dist/docs.json
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
{
|
|
2
|
+
"api": {
|
|
3
|
+
"name": "CardScannerPlugin",
|
|
4
|
+
"slug": "cardscannerplugin",
|
|
5
|
+
"docs": "",
|
|
6
|
+
"tags": [],
|
|
7
|
+
"methods": [
|
|
8
|
+
{
|
|
9
|
+
"name": "start",
|
|
10
|
+
"signature": "(options?: StartOptions | undefined) => Promise<void>",
|
|
11
|
+
"parameters": [
|
|
12
|
+
{
|
|
13
|
+
"name": "options",
|
|
14
|
+
"docs": "",
|
|
15
|
+
"type": "StartOptions | undefined"
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"returns": "Promise<void>",
|
|
19
|
+
"tags": [],
|
|
20
|
+
"docs": "Opens the camera **behind** the WebView. The WebView background is made\ntransparent, so the HTML page must also use transparent backgrounds\nwhere the camera should be visible.",
|
|
21
|
+
"complexTypes": [
|
|
22
|
+
"StartOptions"
|
|
23
|
+
],
|
|
24
|
+
"slug": "start"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "stop",
|
|
28
|
+
"signature": "() => Promise<void>",
|
|
29
|
+
"parameters": [],
|
|
30
|
+
"returns": "Promise<void>",
|
|
31
|
+
"tags": [],
|
|
32
|
+
"docs": "Stops the camera and removes the preview.",
|
|
33
|
+
"complexTypes": [],
|
|
34
|
+
"slug": "stop"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "capture",
|
|
38
|
+
"signature": "(options?: CaptureOptions | undefined) => Promise<CaptureResult>",
|
|
39
|
+
"parameters": [
|
|
40
|
+
{
|
|
41
|
+
"name": "options",
|
|
42
|
+
"docs": "",
|
|
43
|
+
"type": "CaptureOptions | undefined"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"returns": "Promise<CaptureResult>",
|
|
47
|
+
"tags": [],
|
|
48
|
+
"docs": "Takes a photo from the running camera.",
|
|
49
|
+
"complexTypes": [
|
|
50
|
+
"CaptureResult",
|
|
51
|
+
"CaptureOptions"
|
|
52
|
+
],
|
|
53
|
+
"slug": "capture"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "setTorch",
|
|
57
|
+
"signature": "(options: TorchOptions) => Promise<void>",
|
|
58
|
+
"parameters": [
|
|
59
|
+
{
|
|
60
|
+
"name": "options",
|
|
61
|
+
"docs": "",
|
|
62
|
+
"type": "TorchOptions"
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
"returns": "Promise<void>",
|
|
66
|
+
"tags": [],
|
|
67
|
+
"docs": "Turns the flashlight on/off.",
|
|
68
|
+
"complexTypes": [
|
|
69
|
+
"TorchOptions"
|
|
70
|
+
],
|
|
71
|
+
"slug": "settorch"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "setZoom",
|
|
75
|
+
"signature": "(options: ZoomOptions) => Promise<void>",
|
|
76
|
+
"parameters": [
|
|
77
|
+
{
|
|
78
|
+
"name": "options",
|
|
79
|
+
"docs": "",
|
|
80
|
+
"type": "ZoomOptions"
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"returns": "Promise<void>",
|
|
84
|
+
"tags": [],
|
|
85
|
+
"docs": "Sets the zoom ratio.",
|
|
86
|
+
"complexTypes": [
|
|
87
|
+
"ZoomOptions"
|
|
88
|
+
],
|
|
89
|
+
"slug": "setzoom"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "flip",
|
|
93
|
+
"signature": "() => Promise<void>",
|
|
94
|
+
"parameters": [],
|
|
95
|
+
"returns": "Promise<void>",
|
|
96
|
+
"tags": [],
|
|
97
|
+
"docs": "Switches between the rear and front camera.",
|
|
98
|
+
"complexTypes": [],
|
|
99
|
+
"slug": "flip"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"name": "checkPermissions",
|
|
103
|
+
"signature": "() => Promise<PermissionStatus>",
|
|
104
|
+
"parameters": [],
|
|
105
|
+
"returns": "Promise<PermissionStatus>",
|
|
106
|
+
"tags": [],
|
|
107
|
+
"docs": "",
|
|
108
|
+
"complexTypes": [
|
|
109
|
+
"PermissionStatus"
|
|
110
|
+
],
|
|
111
|
+
"slug": "checkpermissions"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "requestPermissions",
|
|
115
|
+
"signature": "() => Promise<PermissionStatus>",
|
|
116
|
+
"parameters": [],
|
|
117
|
+
"returns": "Promise<PermissionStatus>",
|
|
118
|
+
"tags": [],
|
|
119
|
+
"docs": "",
|
|
120
|
+
"complexTypes": [
|
|
121
|
+
"PermissionStatus"
|
|
122
|
+
],
|
|
123
|
+
"slug": "requestpermissions"
|
|
124
|
+
}
|
|
125
|
+
],
|
|
126
|
+
"properties": []
|
|
127
|
+
},
|
|
128
|
+
"interfaces": [
|
|
129
|
+
{
|
|
130
|
+
"name": "StartOptions",
|
|
131
|
+
"slug": "startoptions",
|
|
132
|
+
"docs": "",
|
|
133
|
+
"tags": [],
|
|
134
|
+
"methods": [],
|
|
135
|
+
"properties": [
|
|
136
|
+
{
|
|
137
|
+
"name": "position",
|
|
138
|
+
"tags": [
|
|
139
|
+
{
|
|
140
|
+
"text": "'rear'",
|
|
141
|
+
"name": "default"
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
"docs": "Which camera to use.",
|
|
145
|
+
"complexTypes": [
|
|
146
|
+
"CameraPosition"
|
|
147
|
+
],
|
|
148
|
+
"type": "CameraPosition"
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"name": "CaptureResult",
|
|
154
|
+
"slug": "captureresult",
|
|
155
|
+
"docs": "",
|
|
156
|
+
"tags": [],
|
|
157
|
+
"methods": [],
|
|
158
|
+
"properties": [
|
|
159
|
+
{
|
|
160
|
+
"name": "base64",
|
|
161
|
+
"tags": [],
|
|
162
|
+
"docs": "Base64 encoded JPEG (without the `data:` prefix).",
|
|
163
|
+
"complexTypes": [],
|
|
164
|
+
"type": "string"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"name": "width",
|
|
168
|
+
"tags": [],
|
|
169
|
+
"docs": "",
|
|
170
|
+
"complexTypes": [],
|
|
171
|
+
"type": "number"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"name": "height",
|
|
175
|
+
"tags": [],
|
|
176
|
+
"docs": "",
|
|
177
|
+
"complexTypes": [],
|
|
178
|
+
"type": "number"
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"name": "CaptureOptions",
|
|
184
|
+
"slug": "captureoptions",
|
|
185
|
+
"docs": "",
|
|
186
|
+
"tags": [],
|
|
187
|
+
"methods": [],
|
|
188
|
+
"properties": [
|
|
189
|
+
{
|
|
190
|
+
"name": "quality",
|
|
191
|
+
"tags": [
|
|
192
|
+
{
|
|
193
|
+
"text": "85",
|
|
194
|
+
"name": "default"
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
"docs": "JPEG quality (0-100).",
|
|
198
|
+
"complexTypes": [],
|
|
199
|
+
"type": "number | undefined"
|
|
200
|
+
}
|
|
201
|
+
]
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "TorchOptions",
|
|
205
|
+
"slug": "torchoptions",
|
|
206
|
+
"docs": "",
|
|
207
|
+
"tags": [],
|
|
208
|
+
"methods": [],
|
|
209
|
+
"properties": [
|
|
210
|
+
{
|
|
211
|
+
"name": "enabled",
|
|
212
|
+
"tags": [],
|
|
213
|
+
"docs": "",
|
|
214
|
+
"complexTypes": [],
|
|
215
|
+
"type": "boolean"
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"name": "ZoomOptions",
|
|
221
|
+
"slug": "zoomoptions",
|
|
222
|
+
"docs": "",
|
|
223
|
+
"tags": [],
|
|
224
|
+
"methods": [],
|
|
225
|
+
"properties": [
|
|
226
|
+
{
|
|
227
|
+
"name": "ratio",
|
|
228
|
+
"tags": [],
|
|
229
|
+
"docs": "Zoom ratio, clamped between the camera's min and max.",
|
|
230
|
+
"complexTypes": [],
|
|
231
|
+
"type": "number"
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"name": "PermissionStatus",
|
|
237
|
+
"slug": "permissionstatus",
|
|
238
|
+
"docs": "",
|
|
239
|
+
"tags": [],
|
|
240
|
+
"methods": [],
|
|
241
|
+
"properties": [
|
|
242
|
+
{
|
|
243
|
+
"name": "camera",
|
|
244
|
+
"tags": [],
|
|
245
|
+
"docs": "",
|
|
246
|
+
"complexTypes": [
|
|
247
|
+
"PermissionState"
|
|
248
|
+
],
|
|
249
|
+
"type": "PermissionState"
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
}
|
|
253
|
+
],
|
|
254
|
+
"enums": [],
|
|
255
|
+
"typeAliases": [
|
|
256
|
+
{
|
|
257
|
+
"name": "CameraPosition",
|
|
258
|
+
"slug": "cameraposition",
|
|
259
|
+
"docs": "",
|
|
260
|
+
"types": [
|
|
261
|
+
{
|
|
262
|
+
"text": "'rear'",
|
|
263
|
+
"complexTypes": []
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"text": "'front'",
|
|
267
|
+
"complexTypes": []
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"name": "PermissionState",
|
|
273
|
+
"slug": "permissionstate",
|
|
274
|
+
"docs": "",
|
|
275
|
+
"types": [
|
|
276
|
+
{
|
|
277
|
+
"text": "'prompt'",
|
|
278
|
+
"complexTypes": []
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"text": "'prompt-with-rationale'",
|
|
282
|
+
"complexTypes": []
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"text": "'granted'",
|
|
286
|
+
"complexTypes": []
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"text": "'denied'",
|
|
290
|
+
"complexTypes": []
|
|
291
|
+
}
|
|
292
|
+
]
|
|
293
|
+
}
|
|
294
|
+
],
|
|
295
|
+
"pluginConfigs": []
|
|
296
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { PermissionState } from '@capacitor/core';
|
|
2
|
+
export type CameraPosition = 'rear' | 'front';
|
|
3
|
+
export interface StartOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Which camera to use.
|
|
6
|
+
* @default 'rear'
|
|
7
|
+
*/
|
|
8
|
+
position?: CameraPosition;
|
|
9
|
+
}
|
|
10
|
+
export interface CaptureOptions {
|
|
11
|
+
/**
|
|
12
|
+
* JPEG quality (0-100).
|
|
13
|
+
* @default 85
|
|
14
|
+
*/
|
|
15
|
+
quality?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface CaptureResult {
|
|
18
|
+
/** Base64 encoded JPEG (without the `data:` prefix). */
|
|
19
|
+
base64: string;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
}
|
|
23
|
+
export interface TorchOptions {
|
|
24
|
+
enabled: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface ZoomOptions {
|
|
27
|
+
/** Zoom ratio, clamped between the camera's min and max. */
|
|
28
|
+
ratio: number;
|
|
29
|
+
}
|
|
30
|
+
export interface PermissionStatus {
|
|
31
|
+
camera: PermissionState;
|
|
32
|
+
}
|
|
33
|
+
export interface CardScannerPlugin {
|
|
34
|
+
/**
|
|
35
|
+
* Opens the camera **behind** the WebView. The WebView background is made
|
|
36
|
+
* transparent, so the HTML page must also use transparent backgrounds
|
|
37
|
+
* where the camera should be visible.
|
|
38
|
+
*/
|
|
39
|
+
start(options?: StartOptions): Promise<void>;
|
|
40
|
+
/** Stops the camera and removes the preview. */
|
|
41
|
+
stop(): Promise<void>;
|
|
42
|
+
/** Takes a photo from the running camera. */
|
|
43
|
+
capture(options?: CaptureOptions): Promise<CaptureResult>;
|
|
44
|
+
/** Turns the flashlight on/off. */
|
|
45
|
+
setTorch(options: TorchOptions): Promise<void>;
|
|
46
|
+
/** Sets the zoom ratio. */
|
|
47
|
+
setZoom(options: ZoomOptions): Promise<void>;
|
|
48
|
+
/** Switches between the rear and front camera. */
|
|
49
|
+
flip(): Promise<void>;
|
|
50
|
+
checkPermissions(): Promise<PermissionStatus>;
|
|
51
|
+
requestPermissions(): Promise<PermissionStatus>;
|
|
52
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PermissionState } from '@capacitor/core';\n\nexport type CameraPosition = 'rear' | 'front';\n\nexport interface StartOptions {\n /**\n * Which camera to use.\n * @default 'rear'\n */\n position?: CameraPosition;\n}\n\nexport interface CaptureOptions {\n /**\n * JPEG quality (0-100).\n * @default 85\n */\n quality?: number;\n}\n\nexport interface CaptureResult {\n /** Base64 encoded JPEG (without the `data:` prefix). */\n base64: string;\n width: number;\n height: number;\n}\n\nexport interface TorchOptions {\n enabled: boolean;\n}\n\nexport interface ZoomOptions {\n /** Zoom ratio, clamped between the camera's min and max. */\n ratio: number;\n}\n\nexport interface PermissionStatus {\n camera: PermissionState;\n}\n\nexport interface CardScannerPlugin {\n /**\n * Opens the camera **behind** the WebView. The WebView background is made\n * transparent, so the HTML page must also use transparent backgrounds\n * where the camera should be visible.\n */\n start(options?: StartOptions): Promise<void>;\n\n /** Stops the camera and removes the preview. */\n stop(): Promise<void>;\n\n /** Takes a photo from the running camera. */\n capture(options?: CaptureOptions): Promise<CaptureResult>;\n\n /** Turns the flashlight on/off. */\n setTorch(options: TorchOptions): Promise<void>;\n\n /** Sets the zoom ratio. */\n setZoom(options: ZoomOptions): Promise<void>;\n\n /** Switches between the rear and front camera. */\n flip(): Promise<void>;\n\n checkPermissions(): Promise<PermissionStatus>;\n\n requestPermissions(): Promise<PermissionStatus>;\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { registerPlugin } from '@capacitor/core';
|
|
2
|
+
const CardScanner = registerPlugin('CardScanner', {
|
|
3
|
+
web: () => import('./web').then((m) => new m.CardScannerWeb()),
|
|
4
|
+
});
|
|
5
|
+
export * from './definitions';
|
|
6
|
+
export { CardScanner };
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAIjD,MAAM,WAAW,GAAG,cAAc,CAAoB,aAAa,EAAE;IACnE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,cAAc,EAAE,CAAC;CAC/D,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { CardScannerPlugin } from './definitions';\n\nconst CardScanner = registerPlugin<CardScannerPlugin>('CardScanner', {\n web: () => import('./web').then((m) => new m.CardScannerWeb()),\n});\n\nexport * from './definitions';\nexport { CardScanner };\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
import type { CaptureOptions, CaptureResult, CardScannerPlugin, PermissionStatus, StartOptions, TorchOptions, ZoomOptions } from './definitions';
|
|
3
|
+
/**
|
|
4
|
+
* Browser implementation, useful for testing the layout on a desktop.
|
|
5
|
+
* The <video> element is placed fixed behind the page (z-index -1).
|
|
6
|
+
*/
|
|
7
|
+
export declare class CardScannerWeb extends WebPlugin implements CardScannerPlugin {
|
|
8
|
+
private video;
|
|
9
|
+
private stream;
|
|
10
|
+
private position;
|
|
11
|
+
start(options?: StartOptions): Promise<void>;
|
|
12
|
+
stop(): Promise<void>;
|
|
13
|
+
capture(options?: CaptureOptions): Promise<CaptureResult>;
|
|
14
|
+
setTorch(_options: TorchOptions): Promise<void>;
|
|
15
|
+
setZoom(_options: ZoomOptions): Promise<void>;
|
|
16
|
+
flip(): Promise<void>;
|
|
17
|
+
checkPermissions(): Promise<PermissionStatus>;
|
|
18
|
+
requestPermissions(): Promise<PermissionStatus>;
|
|
19
|
+
}
|
package/dist/esm/web.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { WebPlugin } from '@capacitor/core';
|
|
2
|
+
/**
|
|
3
|
+
* Browser implementation, useful for testing the layout on a desktop.
|
|
4
|
+
* The <video> element is placed fixed behind the page (z-index -1).
|
|
5
|
+
*/
|
|
6
|
+
export class CardScannerWeb extends WebPlugin {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
this.video = null;
|
|
10
|
+
this.stream = null;
|
|
11
|
+
this.position = 'rear';
|
|
12
|
+
}
|
|
13
|
+
async start(options) {
|
|
14
|
+
var _a;
|
|
15
|
+
await this.stop();
|
|
16
|
+
this.position = (_a = options === null || options === void 0 ? void 0 : options.position) !== null && _a !== void 0 ? _a : 'rear';
|
|
17
|
+
this.stream = await navigator.mediaDevices.getUserMedia({
|
|
18
|
+
video: { facingMode: this.position === 'front' ? 'user' : 'environment' },
|
|
19
|
+
audio: false,
|
|
20
|
+
});
|
|
21
|
+
const video = document.createElement('video');
|
|
22
|
+
video.setAttribute('playsinline', '');
|
|
23
|
+
video.muted = true;
|
|
24
|
+
video.autoplay = true;
|
|
25
|
+
Object.assign(video.style, {
|
|
26
|
+
position: 'fixed',
|
|
27
|
+
inset: '0',
|
|
28
|
+
width: '100%',
|
|
29
|
+
height: '100%',
|
|
30
|
+
objectFit: 'cover',
|
|
31
|
+
zIndex: '-1',
|
|
32
|
+
});
|
|
33
|
+
video.srcObject = this.stream;
|
|
34
|
+
document.body.appendChild(video);
|
|
35
|
+
await video.play();
|
|
36
|
+
this.video = video;
|
|
37
|
+
}
|
|
38
|
+
async stop() {
|
|
39
|
+
var _a, _b;
|
|
40
|
+
(_a = this.stream) === null || _a === void 0 ? void 0 : _a.getTracks().forEach((t) => t.stop());
|
|
41
|
+
this.stream = null;
|
|
42
|
+
(_b = this.video) === null || _b === void 0 ? void 0 : _b.remove();
|
|
43
|
+
this.video = null;
|
|
44
|
+
}
|
|
45
|
+
async capture(options) {
|
|
46
|
+
var _a, _b;
|
|
47
|
+
if (!this.video)
|
|
48
|
+
throw new Error('Camera is not running');
|
|
49
|
+
const canvas = document.createElement('canvas');
|
|
50
|
+
canvas.width = this.video.videoWidth;
|
|
51
|
+
canvas.height = this.video.videoHeight;
|
|
52
|
+
(_a = canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.drawImage(this.video, 0, 0);
|
|
53
|
+
const quality = ((_b = options === null || options === void 0 ? void 0 : options.quality) !== null && _b !== void 0 ? _b : 85) / 100;
|
|
54
|
+
const base64 = canvas.toDataURL('image/jpeg', quality).split(',')[1];
|
|
55
|
+
return { base64, width: canvas.width, height: canvas.height };
|
|
56
|
+
}
|
|
57
|
+
async setTorch(_options) {
|
|
58
|
+
throw this.unavailable('Torch is not available on web');
|
|
59
|
+
}
|
|
60
|
+
async setZoom(_options) {
|
|
61
|
+
throw this.unavailable('Zoom is not available on web');
|
|
62
|
+
}
|
|
63
|
+
async flip() {
|
|
64
|
+
await this.start({ position: this.position === 'rear' ? 'front' : 'rear' });
|
|
65
|
+
}
|
|
66
|
+
async checkPermissions() {
|
|
67
|
+
try {
|
|
68
|
+
const status = await navigator.permissions.query({ name: 'camera' });
|
|
69
|
+
return { camera: status.state };
|
|
70
|
+
}
|
|
71
|
+
catch (_a) {
|
|
72
|
+
return { camera: 'prompt' };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async requestPermissions() {
|
|
76
|
+
try {
|
|
77
|
+
const s = await navigator.mediaDevices.getUserMedia({ video: true });
|
|
78
|
+
s.getTracks().forEach((t) => t.stop());
|
|
79
|
+
return { camera: 'granted' };
|
|
80
|
+
}
|
|
81
|
+
catch (_a) {
|
|
82
|
+
return { camera: 'denied' };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"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","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type {\n CameraPosition,\n CaptureOptions,\n CaptureResult,\n CardScannerPlugin,\n PermissionStatus,\n StartOptions,\n TorchOptions,\n ZoomOptions,\n} from './definitions';\n\n/**\n * Browser implementation, useful for testing the layout on a desktop.\n * The <video> element is placed fixed behind the page (z-index -1).\n */\nexport class CardScannerWeb extends WebPlugin implements CardScannerPlugin {\n private video: HTMLVideoElement | null = null;\n private stream: MediaStream | null = null;\n private position: CameraPosition = 'rear';\n\n async start(options?: StartOptions): Promise<void> {\n await this.stop();\n this.position = options?.position ?? 'rear';\n\n this.stream = await navigator.mediaDevices.getUserMedia({\n video: { facingMode: this.position === 'front' ? 'user' : 'environment' },\n audio: false,\n });\n\n const video = document.createElement('video');\n video.setAttribute('playsinline', '');\n video.muted = true;\n video.autoplay = true;\n Object.assign(video.style, {\n position: 'fixed',\n inset: '0',\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n zIndex: '-1',\n });\n video.srcObject = this.stream;\n document.body.appendChild(video);\n await video.play();\n this.video = video;\n }\n\n async stop(): Promise<void> {\n this.stream?.getTracks().forEach((t) => t.stop());\n this.stream = null;\n this.video?.remove();\n this.video = null;\n }\n\n async capture(options?: CaptureOptions): Promise<CaptureResult> {\n if (!this.video) throw new Error('Camera is not running');\n const canvas = document.createElement('canvas');\n canvas.width = this.video.videoWidth;\n canvas.height = this.video.videoHeight;\n canvas.getContext('2d')?.drawImage(this.video, 0, 0);\n const quality = (options?.quality ?? 85) / 100;\n const base64 = canvas.toDataURL('image/jpeg', quality).split(',')[1];\n return { base64, width: canvas.width, height: canvas.height };\n }\n\n async setTorch(_options: TorchOptions): Promise<void> {\n throw this.unavailable('Torch is not available on web');\n }\n\n async setZoom(_options: ZoomOptions): Promise<void> {\n throw this.unavailable('Zoom is not available on web');\n }\n\n async flip(): Promise<void> {\n await this.start({ position: this.position === 'rear' ? 'front' : 'rear' });\n }\n\n async checkPermissions(): Promise<PermissionStatus> {\n try {\n const status = await navigator.permissions.query({ name: 'camera' as PermissionName });\n return { camera: status.state };\n } catch {\n return { camera: 'prompt' };\n }\n }\n\n async requestPermissions(): Promise<PermissionStatus> {\n try {\n const s = await navigator.mediaDevices.getUserMedia({ video: true });\n s.getTracks().forEach((t) => t.stop());\n return { camera: 'granted' };\n } catch {\n return { camera: 'denied' };\n }\n }\n}\n"]}
|