@ekyc_qoobiss/qbs-ect-cmp 1.5.11
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/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/assets/animations/face/LookDown.gif +0 -0
- package/dist/assets/animations/face/LookLeft.gif +0 -0
- package/dist/assets/animations/face/LookRight.gif +0 -0
- package/dist/assets/animations/face/LookUp.gif +0 -0
- package/dist/assets/animations/face/TiltLeft.gif +0 -0
- package/dist/assets/animations/face/TiltRight.gif +0 -0
- package/dist/assets/animations/face/general.gif +0 -0
- package/dist/assets/animations/id/present-id.gif +0 -0
- package/dist/assets/animations/id/straighten-id.gif +0 -0
- package/dist/assets/animations/id/tilt-id.gif +0 -0
- package/dist/assets/buletin/metadata.json +1 -0
- package/dist/assets/buletin/model.json +1 -0
- package/dist/assets/buletin/weights.bin +0 -0
- package/dist/assets/buletin-v2/metadata.json +1 -0
- package/dist/assets/buletin-v2/model.json +1 -0
- package/dist/assets/buletin-v2/weights.bin +0 -0
- package/dist/assets/canvas-masks/face_green.svg +8 -0
- package/dist/assets/canvas-masks/face_white.svg +8 -0
- package/dist/assets/canvas-masks/id_green.svg +6 -0
- package/dist/assets/canvas-masks/id_white.svg +6 -0
- package/dist/assets/capture-error/idError.png +0 -0
- package/dist/assets/capture-error/idError.svg +8 -0
- package/dist/assets/capture-error/selfieError.png +0 -0
- package/dist/assets/capture-error/selfieError.svg +11 -0
- package/dist/assets/complete.svg +4 -0
- package/dist/assets/howtos/circle.svg +11 -0
- package/dist/assets/howtos/idscan.svg +293 -0
- package/dist/assets/howtos/liveness.svg +97 -0
- package/dist/assets/landing/device.svg +14 -0
- package/dist/assets/landing/id.svg +3 -0
- package/dist/assets/landing/info.svg +3 -0
- package/dist/assets/landing/validation.svg +16 -0
- package/dist/cjs/agreement-check_12.cjs.entry.js +6143 -0
- package/dist/cjs/index-9ebcada7.js +1487 -0
- package/dist/cjs/index.cjs.js +2 -0
- package/dist/cjs/loader-dots.cjs.entry.js +19 -0
- package/dist/cjs/loader.cjs.js +21 -0
- package/dist/cjs/qbs-ect-cmp.cjs.js +19 -0
- package/dist/collection/assets/canvas-masks/face_green.svg +8 -0
- package/dist/collection/assets/canvas-masks/face_white.svg +8 -0
- package/dist/collection/assets/canvas-masks/id_green.svg +6 -0
- package/dist/collection/assets/canvas-masks/id_white.svg +6 -0
- package/dist/collection/assets/capture-error/idError.svg +8 -0
- package/dist/collection/assets/capture-error/selfieError.svg +11 -0
- package/dist/collection/assets/complete.svg +4 -0
- package/dist/collection/assets/howtos/circle.svg +11 -0
- package/dist/collection/assets/howtos/idscan.svg +293 -0
- package/dist/collection/assets/howtos/liveness.svg +97 -0
- package/dist/collection/assets/landing/device.svg +14 -0
- package/dist/collection/assets/landing/id.svg +3 -0
- package/dist/collection/assets/landing/info.svg +3 -0
- package/dist/collection/assets/landing/validation.svg +16 -0
- package/dist/collection/collection-manifest.json +24 -0
- package/dist/collection/components/agreement-check/agreement-check.css +0 -0
- package/dist/collection/components/agreement-check/agreement-check.js +75 -0
- package/dist/collection/components/agreement-info/agreement-info.css +0 -0
- package/dist/collection/components/agreement-info/agreement-info.js +72 -0
- package/dist/collection/components/capture-error/capture-error.css +0 -0
- package/dist/collection/components/capture-error/capture-error.js +107 -0
- package/dist/collection/components/controls/camera/camera.css +43 -0
- package/dist/collection/components/controls/camera/camera.js +306 -0
- package/dist/collection/components/controls/loader-dots/loader-dots.css +61 -0
- package/dist/collection/components/controls/loader-dots/loader-dots.js +18 -0
- package/dist/collection/components/end-redirect/end-redirect.css +128 -0
- package/dist/collection/components/end-redirect/end-redirect.js +25 -0
- package/dist/collection/components/how-to-info/how-to-info.css +0 -0
- package/dist/collection/components/how-to-info/how-to-info.js +105 -0
- package/dist/collection/components/id-back-capture/id-back-capture.css +35 -0
- package/dist/collection/components/id-back-capture/id-back-capture.js +201 -0
- package/dist/collection/components/id-capture/id-capture.css +35 -0
- package/dist/collection/components/id-capture/id-capture.js +201 -0
- package/dist/collection/components/identification-component/identification-component.css +999 -0
- package/dist/collection/components/identification-component/identification-component.js +397 -0
- package/dist/collection/components/landing-validation/landing-validation.css +0 -0
- package/dist/collection/components/landing-validation/landing-validation.js +78 -0
- package/dist/collection/components/selfie-capture/selfie-capture.css +22 -0
- package/dist/collection/components/selfie-capture/selfie-capture.js +198 -0
- package/dist/collection/components/sms-code-validation/sms-code-validation.css +0 -0
- package/dist/collection/components/sms-code-validation/sms-code-validation.js +91 -0
- package/dist/collection/global.js +0 -0
- package/dist/collection/helpers/ApiCall.js +153 -0
- package/dist/collection/helpers/Cameras.js +98 -0
- package/dist/collection/helpers/Events.js +79 -0
- package/dist/collection/helpers/ML5.js +20 -0
- package/dist/collection/helpers/Stream.js +223 -0
- package/dist/collection/helpers/canvas.js +10 -0
- package/dist/collection/helpers/index.js +54 -0
- package/dist/collection/helpers/security.js +25 -0
- package/dist/collection/helpers/store.js +15 -0
- package/dist/collection/helpers/textValues.js +82 -0
- package/dist/collection/index.js +1 -0
- package/dist/collection/libs/FaceML5Detector/FaceML5Detector.js +206 -0
- package/dist/collection/libs/FaceML5Detector/FacePose.js +84 -0
- package/dist/collection/libs/IDML5Detector/IDML5Detector.js +110 -0
- package/dist/collection/libs/IDML5Detector/IDPose.js +5 -0
- package/dist/collection/models/ICamera.js +1 -0
- package/dist/collection/models/IConstraints.js +1 -0
- package/dist/collection/models/IDevice.js +1 -0
- package/dist/collection/utils/utils.js +10 -0
- package/dist/esm/agreement-check_12.entry.js +6128 -0
- package/dist/esm/index-3fe6775c.js +1457 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/loader-dots.entry.js +15 -0
- package/dist/esm/loader.js +17 -0
- package/dist/esm/polyfills/core-js.js +11 -0
- package/dist/esm/polyfills/css-shim.js +1 -0
- package/dist/esm/polyfills/dom.js +79 -0
- package/dist/esm/polyfills/es5-html-element.js +1 -0
- package/dist/esm/polyfills/index.js +34 -0
- package/dist/esm/polyfills/system.js +6 -0
- package/dist/esm/qbs-ect-cmp.js +17 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/loader/cdn.js +3 -0
- package/dist/loader/index.cjs.js +3 -0
- package/dist/loader/index.d.ts +12 -0
- package/dist/loader/index.es2017.js +3 -0
- package/dist/loader/index.js +4 -0
- package/dist/loader/package.json +11 -0
- package/dist/qbs-ect-cmp/index.esm.js +0 -0
- package/dist/qbs-ect-cmp/p-3ef0bad2.entry.js +1373 -0
- package/dist/qbs-ect-cmp/p-3fa495e4.js +2 -0
- package/dist/qbs-ect-cmp/p-a69bb428.entry.js +1 -0
- package/dist/qbs-ect-cmp/qbs-ect-cmp.css +1 -0
- package/dist/qbs-ect-cmp/qbs-ect-cmp.esm.js +1 -0
- package/dist/types/components/agreement-check/agreement-check.d.ts +11 -0
- package/dist/types/components/agreement-info/agreement-info.d.ts +13 -0
- package/dist/types/components/capture-error/capture-error.d.ts +11 -0
- package/dist/types/components/controls/camera/camera.d.ts +33 -0
- package/dist/types/components/controls/loader-dots/loader-dots.d.ts +3 -0
- package/dist/types/components/end-redirect/end-redirect.d.ts +4 -0
- package/dist/types/components/how-to-info/how-to-info.d.ts +13 -0
- package/dist/types/components/id-back-capture/id-back-capture.d.ts +26 -0
- package/dist/types/components/id-capture/id-capture.d.ts +26 -0
- package/dist/types/components/identification-component/identification-component.d.ts +31 -0
- package/dist/types/components/landing-validation/landing-validation.d.ts +11 -0
- package/dist/types/components/selfie-capture/selfie-capture.d.ts +26 -0
- package/dist/types/components/sms-code-validation/sms-code-validation.d.ts +14 -0
- package/dist/types/components.d.ts +262 -0
- package/dist/types/global.d.ts +0 -0
- package/dist/types/helpers/ApiCall.d.ts +12 -0
- package/dist/types/helpers/Cameras.d.ts +8 -0
- package/dist/types/helpers/Events.d.ts +12 -0
- package/dist/types/helpers/ML5.d.ts +8 -0
- package/dist/types/helpers/Stream.d.ts +58 -0
- package/dist/types/helpers/canvas.d.ts +2 -0
- package/dist/types/helpers/index.d.ts +4 -0
- package/dist/types/helpers/security.d.ts +4 -0
- package/dist/types/helpers/store.d.ts +10 -0
- package/dist/types/helpers/textValues.d.ts +78 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/libs/FaceML5Detector/FaceML5Detector.d.ts +43 -0
- package/dist/types/libs/FaceML5Detector/FacePose.d.ts +37 -0
- package/dist/types/libs/IDML5Detector/IDML5Detector.d.ts +22 -0
- package/dist/types/libs/IDML5Detector/IDPose.d.ts +4 -0
- package/dist/types/models/ICamera.d.ts +10 -0
- package/dist/types/models/IConstraints.d.ts +21 -0
- package/dist/types/models/IDevice.d.ts +11 -0
- package/dist/types/stencil-public-runtime.d.ts +1581 -0
- package/dist/types/utils/utils.d.ts +2 -0
- package/package.json +51 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { h } from '@stencil/core';
|
|
2
|
+
import { ApiCall } from '../../helpers/ApiCall';
|
|
3
|
+
import store from '../../helpers/store';
|
|
4
|
+
import { PhoneValidationValues, CodeValidationValues } from '../../helpers/textValues';
|
|
5
|
+
export class SmsCodeValidation {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.title = undefined;
|
|
8
|
+
this.details = undefined;
|
|
9
|
+
this.buttonText = undefined;
|
|
10
|
+
this.phoneNumber = undefined;
|
|
11
|
+
this.code = undefined;
|
|
12
|
+
this.apiCall = new ApiCall();
|
|
13
|
+
}
|
|
14
|
+
async doAction() {
|
|
15
|
+
if (store.flowStatus == 'CODE' || store.flowStatus == 'CODEERROR') {
|
|
16
|
+
var codeChecked = await this.apiCall.CheckOTPCode(store.requestId, this.code);
|
|
17
|
+
if (typeof codeChecked === 'boolean' && codeChecked) {
|
|
18
|
+
store.flowStatus = 'HOWTOID';
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
store.flowStatus = 'CODEERROR';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (store.flowStatus == 'PHONE') {
|
|
25
|
+
var codeSent = await this.apiCall.SendOTPCode(store.requestId, this.phoneNumber);
|
|
26
|
+
if (typeof codeSent === 'boolean' && codeSent) {
|
|
27
|
+
store.flowStatus = 'CODE';
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
componentWillRender() {
|
|
32
|
+
if (store.flowStatus == 'PHONE') {
|
|
33
|
+
this.title = PhoneValidationValues.Title;
|
|
34
|
+
this.details = PhoneValidationValues.Description;
|
|
35
|
+
this.buttonText = PhoneValidationValues.Button;
|
|
36
|
+
}
|
|
37
|
+
if (store.flowStatus == 'CODE' || store.flowStatus == 'CODEERROR') {
|
|
38
|
+
this.title = CodeValidationValues.Title;
|
|
39
|
+
this.details = CodeValidationValues.Description;
|
|
40
|
+
this.buttonText = CodeValidationValues.Button;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
handleChangePhone(ev) {
|
|
44
|
+
let value = ev.target ? ev.target.value : '';
|
|
45
|
+
this.phoneNumber = value.replace(/\D/g, '');
|
|
46
|
+
if (this.phoneNumber.length > 10)
|
|
47
|
+
this.phoneNumber = this.phoneNumber.substring(0, 10);
|
|
48
|
+
ev.target.value = this.phoneNumber;
|
|
49
|
+
}
|
|
50
|
+
handleChangeCode(ev) {
|
|
51
|
+
let value = ev.target ? ev.target.value : '';
|
|
52
|
+
this.code = value;
|
|
53
|
+
if (this.code.length > 4)
|
|
54
|
+
this.code = this.code.substring(0, 4);
|
|
55
|
+
ev.target.value = this.code;
|
|
56
|
+
}
|
|
57
|
+
render() {
|
|
58
|
+
let inputBlock;
|
|
59
|
+
let errorBlock;
|
|
60
|
+
if (store.flowStatus == 'CODEERROR') {
|
|
61
|
+
errorBlock = h("p", { class: "main-text font-size-18 mt-15 color-red" }, CodeValidationValues.Error);
|
|
62
|
+
}
|
|
63
|
+
if (store.flowStatus == 'PHONE') {
|
|
64
|
+
inputBlock = (h("div", { class: "input-container mb-15" }, h("label", { class: "font-size-18 mb-1" }, h("b", null, PhoneValidationValues.Label)), h("input", { type: "tel", id: "phoneInput", class: "main-input", onInput: ev => this.handleChangePhone(ev), value: this.phoneNumber })));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
inputBlock = (h("div", { class: "input-container mb-15" }, h("input", { type: "text", id: "codeInput", class: "main-input", onInput: ev => this.handleChangeCode(ev), value: this.code })));
|
|
68
|
+
}
|
|
69
|
+
return (h("div", { class: "container" }, h("div", { class: "row row-validare" }, h("div", null, h("h1", null, this.title), errorBlock == null ? h("p", { class: "main-text font-size-2 mt-15 mb-20" }, this.details) : errorBlock), inputBlock, h("div", { class: "btn-buletin" }, h("button", { id: "action", class: "main-button", onClick: () => this.doAction() }, this.buttonText), h("p", { class: "main-text font-size-18 text-right mb-0" }, PhoneValidationValues.FooterText)))));
|
|
70
|
+
}
|
|
71
|
+
static get is() { return "sms-code-validation"; }
|
|
72
|
+
static get originalStyleUrls() {
|
|
73
|
+
return {
|
|
74
|
+
"$": ["sms-code-validation.css"]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
static get styleUrls() {
|
|
78
|
+
return {
|
|
79
|
+
"$": ["sms-code-validation.css"]
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
static get states() {
|
|
83
|
+
return {
|
|
84
|
+
"title": {},
|
|
85
|
+
"details": {},
|
|
86
|
+
"buttonText": {},
|
|
87
|
+
"phoneNumber": {},
|
|
88
|
+
"code": {}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import store from './store';
|
|
2
|
+
export class ApiCall {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.toBase64 = (file) => new Promise((resolve, reject) => {
|
|
5
|
+
const reader = new FileReader();
|
|
6
|
+
reader.readAsDataURL(file);
|
|
7
|
+
reader.onload = () => resolve(reader.result);
|
|
8
|
+
reader.onerror = error => reject(error);
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
async Post(url, data) {
|
|
12
|
+
try {
|
|
13
|
+
let resp = await fetch(store.apiBaseUrl + url, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
body: data,
|
|
16
|
+
headers: {
|
|
17
|
+
'Content-Type': 'application/json',
|
|
18
|
+
'Authorization': 'IDKYC-TOKEN ' + store.token,
|
|
19
|
+
// 'ApiKey': '2E1DF612-E9F3-4B8A-9154-5256E412D90C',
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
if (!resp.ok) {
|
|
23
|
+
return new Error(resp.statusText);
|
|
24
|
+
}
|
|
25
|
+
return await resp.json();
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
console.log(err);
|
|
29
|
+
return err;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async Get(url) {
|
|
33
|
+
try {
|
|
34
|
+
let resp = await fetch(store.apiBaseUrl + url, {
|
|
35
|
+
method: 'GET',
|
|
36
|
+
headers: {
|
|
37
|
+
'Content-Type': 'application/json',
|
|
38
|
+
'Authorization': 'IDKYC-TOKEN ' + store.token,
|
|
39
|
+
// 'ApiKey': '2E1DF612-E9F3-4B8A-9154-5256E412D90C',
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
if (!resp.ok) {
|
|
43
|
+
return new Error(resp.statusText);
|
|
44
|
+
}
|
|
45
|
+
return await resp.json();
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
console.log(err);
|
|
49
|
+
return err;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async SendOTPCode(requestId, phoneNumber) {
|
|
53
|
+
let data = { requestId: requestId, phone: phoneNumber };
|
|
54
|
+
let jsonResp = await this.Post('/validation/otp/send', JSON.stringify(data));
|
|
55
|
+
if (typeof jsonResp != 'boolean') {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return jsonResp;
|
|
59
|
+
}
|
|
60
|
+
async CheckOTPCode(requestId, otpCode) {
|
|
61
|
+
let data = { requestId: requestId, otp: otpCode };
|
|
62
|
+
let jsonResp = await this.Post('/validation/otp/check', JSON.stringify(data));
|
|
63
|
+
if (typeof jsonResp != 'boolean') {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return jsonResp;
|
|
67
|
+
}
|
|
68
|
+
async AddIdentificationRequest(requestId, deviceInfo) {
|
|
69
|
+
let data = { requestId: requestId, clientDeviceInfo: deviceInfo };
|
|
70
|
+
let jsonResp = await this.Post('/validation/identity/insert', JSON.stringify(data));
|
|
71
|
+
if (typeof jsonResp.hasIdBack == 'boolean') {
|
|
72
|
+
store.hasIdBack = jsonResp.hasIdBack;
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async UploadFileForRequestB64(requestId, type, file) {
|
|
80
|
+
let data = {
|
|
81
|
+
requestId: requestId,
|
|
82
|
+
type: type,
|
|
83
|
+
data: await this.toBase64(file),
|
|
84
|
+
};
|
|
85
|
+
let respJson = await this.Post('/validation/upload/capture', JSON.stringify(data));
|
|
86
|
+
if (respJson && respJson.file_path) {
|
|
87
|
+
if (type == 'IdFront') {
|
|
88
|
+
return respJson.isValid;
|
|
89
|
+
}
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async UploadFileForRequest(requestId, type, file) {
|
|
97
|
+
try {
|
|
98
|
+
let data = new FormData();
|
|
99
|
+
data.append('requestId', requestId);
|
|
100
|
+
data.append('type', type);
|
|
101
|
+
data.append('file', file);
|
|
102
|
+
let resp = await fetch(store.apiBaseUrl + '/validation/upload/file', {
|
|
103
|
+
method: 'POST',
|
|
104
|
+
body: data,
|
|
105
|
+
});
|
|
106
|
+
if (!resp.ok) {
|
|
107
|
+
console.log(resp.statusText);
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
let respJson = await resp.json();
|
|
111
|
+
if (respJson && respJson.file_path) {
|
|
112
|
+
if (type == 'IdFront') {
|
|
113
|
+
return respJson.isValid;
|
|
114
|
+
}
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
console.log(err);
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async GetAgreement(agreementType) {
|
|
127
|
+
try {
|
|
128
|
+
let resp = await this.Get('/validation/agreement/content?type=' + agreementType + '&requestId=' + store.requestId);
|
|
129
|
+
if (resp) {
|
|
130
|
+
return resp.htmlText;
|
|
131
|
+
}
|
|
132
|
+
return '';
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
console.log(err);
|
|
136
|
+
return '';
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
async GenerateAgreement(agreementType) {
|
|
140
|
+
try {
|
|
141
|
+
let data = { requestId: store.requestId, documentType: agreementType };
|
|
142
|
+
let resp = await this.Post('/validation/agreement/generate', JSON.stringify(data));
|
|
143
|
+
if (typeof resp != 'boolean') {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
return resp;
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
console.log(err);
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export class Cameras {
|
|
2
|
+
async GetCameras(deviceInfo) {
|
|
3
|
+
var allDevices = [];
|
|
4
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
5
|
+
const videoDevices = devices.filter(device => device.kind === 'videoinput');
|
|
6
|
+
for (const device of videoDevices) {
|
|
7
|
+
const updatedConstraints = this.GetConstraints(device.deviceId, deviceInfo);
|
|
8
|
+
const stream = await navigator.mediaDevices.getUserMedia(updatedConstraints);
|
|
9
|
+
stream.getVideoTracks().forEach(track => {
|
|
10
|
+
if (deviceInfo.isFirefox) {
|
|
11
|
+
const settings = track.getSettings();
|
|
12
|
+
let facingMode = settings.facingMode && settings.facingMode.length > 0 ? settings.facingMode[0] : '';
|
|
13
|
+
facingMode = facingMode === 'e' ? 'environment' : facingMode;
|
|
14
|
+
allDevices.push({
|
|
15
|
+
deviceId: device.deviceId,
|
|
16
|
+
name: device.label,
|
|
17
|
+
height: settings.height,
|
|
18
|
+
width: settings.width,
|
|
19
|
+
frameRate: Number(settings.frameRate.max),
|
|
20
|
+
torch: false,
|
|
21
|
+
recommended: false,
|
|
22
|
+
facingMode: facingMode,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
const capabilities = track.getCapabilities();
|
|
27
|
+
let facingMode = capabilities.facingMode && capabilities.facingMode.length > 0 ? capabilities.facingMode[0] : '';
|
|
28
|
+
facingMode = facingMode === 'e' ? 'environment' : facingMode;
|
|
29
|
+
allDevices.push({
|
|
30
|
+
deviceId: device.deviceId,
|
|
31
|
+
name: device.label,
|
|
32
|
+
height: capabilities.height.max,
|
|
33
|
+
width: capabilities.width.max,
|
|
34
|
+
frameRate: Number(capabilities.frameRate.max),
|
|
35
|
+
torch: capabilities.torch,
|
|
36
|
+
recommended: false,
|
|
37
|
+
facingMode: facingMode,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
stream.getTracks().forEach(track => {
|
|
42
|
+
track.stop();
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (allDevices.length > 0) {
|
|
46
|
+
allDevices = allDevices.sort((a, b) => b.frameRate - a.frameRate);
|
|
47
|
+
var firstOption = allDevices.find(i => i.name.indexOf('0,') != -1 && i.facingMode === 'environment');
|
|
48
|
+
if (firstOption) {
|
|
49
|
+
allDevices[allDevices.indexOf(firstOption)].recommended = true;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
var firstEnv = allDevices.find(i => i.facingMode === 'environment');
|
|
53
|
+
if (firstEnv) {
|
|
54
|
+
allDevices[allDevices.indexOf(firstEnv)].recommended = true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return allDevices;
|
|
59
|
+
}
|
|
60
|
+
GetConstraints(selectedDeviceId, device, portrait = false) {
|
|
61
|
+
let constraints = {
|
|
62
|
+
audio: false,
|
|
63
|
+
video: {
|
|
64
|
+
frameRate: 30
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
if (selectedDeviceId) {
|
|
68
|
+
constraints.video.deviceId = {
|
|
69
|
+
exact: selectedDeviceId,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (device.isWin) {
|
|
73
|
+
constraints.video.width = { ideal: 1280 };
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
if (portrait) {
|
|
77
|
+
constraints.video.facingMode = 'user';
|
|
78
|
+
constraints.video.width = { ideal: 1280 };
|
|
79
|
+
constraints.video.height = { ideal: 720 };
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
constraints.video.facingMode = 'environment';
|
|
83
|
+
constraints.video.width = { ideal: 740 };
|
|
84
|
+
constraints.video.aspectRatio = 1;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return constraints;
|
|
88
|
+
}
|
|
89
|
+
GetRecommendedCamera(cameras) {
|
|
90
|
+
if (cameras && cameras.length > 0) {
|
|
91
|
+
var recommDevice = cameras.find(c => c.recommended);
|
|
92
|
+
if (recommDevice) {
|
|
93
|
+
return recommDevice;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
export default class Events {
|
|
2
|
+
static init(element) {
|
|
3
|
+
this.cameraModule = element;
|
|
4
|
+
}
|
|
5
|
+
static captureEvent(photos) {
|
|
6
|
+
this.cameraModule.dispatchEvent(new CustomEvent('capture', {
|
|
7
|
+
detail: {
|
|
8
|
+
photos,
|
|
9
|
+
},
|
|
10
|
+
bubbles: true,
|
|
11
|
+
cancelable: true,
|
|
12
|
+
composed: true,
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
static recordingAvailable(recording) {
|
|
16
|
+
this.cameraModule.dispatchEvent(new CustomEvent('recordingAvailable', {
|
|
17
|
+
detail: {
|
|
18
|
+
recording,
|
|
19
|
+
},
|
|
20
|
+
bubbles: true,
|
|
21
|
+
cancelable: true,
|
|
22
|
+
composed: true,
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
static closeEvent() {
|
|
26
|
+
this.cameraModule.dispatchEvent(new CustomEvent('close', {
|
|
27
|
+
bubbles: false,
|
|
28
|
+
cancelable: true,
|
|
29
|
+
composed: true,
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
static cameraReadyEvent() {
|
|
33
|
+
this.cameraModule.dispatchEvent(new CustomEvent('cameraReady', {
|
|
34
|
+
bubbles: false,
|
|
35
|
+
cancelable: true,
|
|
36
|
+
composed: true,
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
static errorEvent(error) {
|
|
40
|
+
this.cameraModule.dispatchEvent(new CustomEvent('error', {
|
|
41
|
+
detail: {
|
|
42
|
+
error,
|
|
43
|
+
},
|
|
44
|
+
bubbles: true,
|
|
45
|
+
cancelable: true,
|
|
46
|
+
composed: true,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
static detectionError(error) {
|
|
50
|
+
this.cameraModule.dispatchEvent(new CustomEvent('detectionError', {
|
|
51
|
+
detail: {
|
|
52
|
+
error,
|
|
53
|
+
},
|
|
54
|
+
bubbles: true,
|
|
55
|
+
cancelable: true,
|
|
56
|
+
composed: true,
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
static loadedModels(loadedModels) {
|
|
60
|
+
this.cameraModule.dispatchEvent(new CustomEvent('loadedModels', {
|
|
61
|
+
detail: {
|
|
62
|
+
loadedModels,
|
|
63
|
+
},
|
|
64
|
+
bubbles: true,
|
|
65
|
+
cancelable: true,
|
|
66
|
+
composed: true,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
static detectorInitialized(initializationTime) {
|
|
70
|
+
this.cameraModule.dispatchEvent(new CustomEvent('detectorInitialized', {
|
|
71
|
+
detail: {
|
|
72
|
+
initializationTime,
|
|
73
|
+
},
|
|
74
|
+
bubbles: true,
|
|
75
|
+
cancelable: true,
|
|
76
|
+
composed: true,
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import ml5 from 'ml5';
|
|
2
|
+
export class ML5 {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.init();
|
|
5
|
+
}
|
|
6
|
+
static getInstance() {
|
|
7
|
+
if (!ML5.instance) {
|
|
8
|
+
ML5.instance = new ML5();
|
|
9
|
+
}
|
|
10
|
+
return ML5.instance;
|
|
11
|
+
}
|
|
12
|
+
async init() {
|
|
13
|
+
return new Promise(async (resolve) => {
|
|
14
|
+
this.classifier = await ml5.imageClassifier('../../assets/buletin-v2/model.json');
|
|
15
|
+
this.faceapi = await ml5.faceApi({ withLandmarks: true, withDescriptors: false });
|
|
16
|
+
resolve();
|
|
17
|
+
console.log('ML5 LOADED!!!');
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import Events from './Events';
|
|
2
|
+
import { IDML5Detector } from '../libs/IDML5Detector/IDML5Detector';
|
|
3
|
+
import { FaceML5Detector } from '../libs/FaceML5Detector/FaceML5Detector';
|
|
4
|
+
import { FacePose } from '../libs/FaceML5Detector/FacePose';
|
|
5
|
+
import { FacePosePick } from '../libs/FaceML5Detector/FacePose';
|
|
6
|
+
import { addExifInImg } from './security';
|
|
7
|
+
var ImageFormat;
|
|
8
|
+
(function (ImageFormat) {
|
|
9
|
+
ImageFormat["JPEG"] = "image/jpeg";
|
|
10
|
+
ImageFormat["PNG"] = "image/png";
|
|
11
|
+
})(ImageFormat || (ImageFormat = {}));
|
|
12
|
+
export class Stream {
|
|
13
|
+
constructor(device, _modelPath) {
|
|
14
|
+
this.streamPaused = false;
|
|
15
|
+
this.recordedChunks = [];
|
|
16
|
+
this.videoSize = { width: 0, height: 0 };
|
|
17
|
+
this.pauseStream = () => {
|
|
18
|
+
this.streamPaused = true;
|
|
19
|
+
this.mediaRecorder.pause();
|
|
20
|
+
this.videoElement.pause();
|
|
21
|
+
// this.dropMask();
|
|
22
|
+
// if (this.faceDetection) Detector.getInstance().stopDetector();
|
|
23
|
+
};
|
|
24
|
+
this.device = device;
|
|
25
|
+
this.idML5Detector = IDML5Detector.getInstance(this, device.isMobile);
|
|
26
|
+
this.faceML5Detector = FaceML5Detector.getInstance(this, device.isMobile);
|
|
27
|
+
}
|
|
28
|
+
setFaceDetection(val) {
|
|
29
|
+
this.faceDetection = val;
|
|
30
|
+
this.idDetection = !val;
|
|
31
|
+
}
|
|
32
|
+
setIdDetection(val) {
|
|
33
|
+
this.idDetection = val;
|
|
34
|
+
this.faceDetection = !val;
|
|
35
|
+
}
|
|
36
|
+
// public setProbabilityThreshold(val: number): void {
|
|
37
|
+
// Detector.getInstance().setProbabilityThreshold(val);
|
|
38
|
+
// }
|
|
39
|
+
setCallbackChangeTitle(fun) {
|
|
40
|
+
this.callbackChangeTitle = fun;
|
|
41
|
+
}
|
|
42
|
+
setCallbackStopAnimation(fun) {
|
|
43
|
+
this.callbackStopAnimation = fun;
|
|
44
|
+
}
|
|
45
|
+
setCallbackVideoStarted(fun) {
|
|
46
|
+
this.callbackVideoStarted = fun;
|
|
47
|
+
}
|
|
48
|
+
setCallbackErrors(fun) {
|
|
49
|
+
this.callbackErrors = fun;
|
|
50
|
+
}
|
|
51
|
+
setCallbackAutoCapturing(fun) {
|
|
52
|
+
this.callbackAutoCapturing = fun;
|
|
53
|
+
}
|
|
54
|
+
// public setCallbackFaceDetectionErrors(fun: (e: PipelineResult) => void): void {
|
|
55
|
+
// this.callbackFaceDetectionErrors = fun;
|
|
56
|
+
// }
|
|
57
|
+
setCallbackRecordingReady(fun) {
|
|
58
|
+
this.callbackRecordingReady = fun;
|
|
59
|
+
}
|
|
60
|
+
setCallbackTimeElapsed(fun) {
|
|
61
|
+
this.callbackTimeElapsed = fun;
|
|
62
|
+
}
|
|
63
|
+
static getInstance(device, modelPath) {
|
|
64
|
+
if (!Stream.instance) {
|
|
65
|
+
Stream.instance = new Stream(device, modelPath);
|
|
66
|
+
}
|
|
67
|
+
return Stream.instance;
|
|
68
|
+
}
|
|
69
|
+
// public returnErrors(errors: PipelineResult) {
|
|
70
|
+
// this.callbackFaceDetectionErrors(errors);
|
|
71
|
+
// }
|
|
72
|
+
autoCapturing() {
|
|
73
|
+
this.callbackAutoCapturing();
|
|
74
|
+
}
|
|
75
|
+
timeElapsed() {
|
|
76
|
+
this.callbackTimeElapsed();
|
|
77
|
+
}
|
|
78
|
+
updateHtmlElements(videoElement, canvasElement, component) {
|
|
79
|
+
this.videoElement = videoElement;
|
|
80
|
+
this.canvasElement = canvasElement;
|
|
81
|
+
this.idML5Detector.updateHtmlElements(this.videoElement, this.canvasElement, component);
|
|
82
|
+
this.faceML5Detector.updateHtmlElements(this.videoElement, this.canvasElement, component);
|
|
83
|
+
}
|
|
84
|
+
static orientationChange() { }
|
|
85
|
+
startStream(stream) {
|
|
86
|
+
if (this.stream)
|
|
87
|
+
this.stream.getTracks().forEach((track) => track.stop());
|
|
88
|
+
this.stream = stream;
|
|
89
|
+
if ('srcObject' in this.videoElement) {
|
|
90
|
+
this.videoElement.srcObject = stream;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
this.videoElement.src = window.URL.createObjectURL(stream);
|
|
94
|
+
}
|
|
95
|
+
this.videoElement.addEventListener('loadedmetadata', async (_e) => {
|
|
96
|
+
this.videoElement.play().then(() => {
|
|
97
|
+
this.streamPaused = false;
|
|
98
|
+
Events.cameraReadyEvent();
|
|
99
|
+
this.updateCanvasSize(this.canvasElement);
|
|
100
|
+
this.updateVideoSize(this.videoElement);
|
|
101
|
+
this.callbackVideoStarted();
|
|
102
|
+
if (this.idDetection)
|
|
103
|
+
this.startIdDetection();
|
|
104
|
+
if (this.faceDetection)
|
|
105
|
+
this.startFaceDetection();
|
|
106
|
+
});
|
|
107
|
+
}, false);
|
|
108
|
+
}
|
|
109
|
+
async initStream(stream) {
|
|
110
|
+
this.startStream(stream);
|
|
111
|
+
this.recordStream();
|
|
112
|
+
}
|
|
113
|
+
async resumeStream() {
|
|
114
|
+
this.streamPaused = false;
|
|
115
|
+
this.mediaRecorder.resume();
|
|
116
|
+
await this.videoElement.play();
|
|
117
|
+
// this.drawMask();
|
|
118
|
+
// if (this.faceDetection) await Detector.getInstance().startDetector();
|
|
119
|
+
}
|
|
120
|
+
recordStream() {
|
|
121
|
+
var options = { mimeType: 'video/webm;codecs=vp8', videoBitsPerSecond: 1500000 };
|
|
122
|
+
if (!MediaRecorder.isTypeSupported(options.mimeType)) {
|
|
123
|
+
if (this.device.isIos || this.device.isSafari)
|
|
124
|
+
options.mimeType = 'video/mp4;codecs:h264';
|
|
125
|
+
}
|
|
126
|
+
this.recordedChunks = [];
|
|
127
|
+
this.mediaRecorder = new MediaRecorder(this.stream, options);
|
|
128
|
+
this.mediaRecorder.ondataavailable = event => {
|
|
129
|
+
this.recordedChunks.push(event.data);
|
|
130
|
+
};
|
|
131
|
+
this.mediaRecorder.onstop = async () => {
|
|
132
|
+
this.saveVideoRecording(this.recordedChunks, options.mimeType);
|
|
133
|
+
this.recordedChunks = [];
|
|
134
|
+
};
|
|
135
|
+
this.mediaRecorder.start(); // Start recording, and dump data every second
|
|
136
|
+
}
|
|
137
|
+
async saveVideoRecording(videoTosave, mimeType) {
|
|
138
|
+
var blob = new Blob(videoTosave, {
|
|
139
|
+
type: mimeType.split(';')[0],
|
|
140
|
+
});
|
|
141
|
+
this.callbackRecordingReady(blob);
|
|
142
|
+
}
|
|
143
|
+
updateCanvasSize(canvas) {
|
|
144
|
+
this.videoSize = { width: this.videoElement.videoWidth, height: this.videoElement.videoHeight };
|
|
145
|
+
canvas.width = this.videoSize.width;
|
|
146
|
+
canvas.height = this.videoSize.height;
|
|
147
|
+
}
|
|
148
|
+
updateVideoSize(video) {
|
|
149
|
+
this.videoSize = { width: this.videoElement.videoWidth, height: this.videoElement.videoHeight };
|
|
150
|
+
video.width = this.videoSize.width;
|
|
151
|
+
video.height = this.videoSize.height;
|
|
152
|
+
}
|
|
153
|
+
dropStream() {
|
|
154
|
+
if (!this.streamStopped()) {
|
|
155
|
+
this.stream.getTracks().forEach((track) => track.stop());
|
|
156
|
+
this.videoElement.srcObject = null;
|
|
157
|
+
}
|
|
158
|
+
if (this.mediaRecorder && this.mediaRecorder.state != 'inactive') {
|
|
159
|
+
this.mediaRecorder.stop();
|
|
160
|
+
}
|
|
161
|
+
// if (this.faceDetection) Detector.getInstance().stopDetector();
|
|
162
|
+
}
|
|
163
|
+
streamStopped() {
|
|
164
|
+
return !(this.stream && this.stream.getTracks && this.stream.getTracks().length > 0);
|
|
165
|
+
}
|
|
166
|
+
takePhoto() {
|
|
167
|
+
return new Promise(async (resolve) => {
|
|
168
|
+
const canvas = document.createElement('canvas');
|
|
169
|
+
canvas.width = this.videoElement.videoWidth;
|
|
170
|
+
canvas.height = this.videoElement.videoHeight;
|
|
171
|
+
resolve([await this.getFrame(canvas)]);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
getFrame(canvas) {
|
|
175
|
+
return new Promise(resolve => {
|
|
176
|
+
const context = canvas.getContext('2d');
|
|
177
|
+
context.drawImage(this.videoElement, 0, 0, canvas.width, canvas.height);
|
|
178
|
+
canvas.toBlob((frame) => {
|
|
179
|
+
if (frame.type === ImageFormat.JPEG && !this.device.isIos) {
|
|
180
|
+
try {
|
|
181
|
+
addExifInImg(frame, this.stream.getTracks()[0], this.videoSize).then(updatedFrame => resolve(updatedFrame));
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
resolve(frame);
|
|
185
|
+
this.callbackErrors(e, false);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
resolve(frame);
|
|
190
|
+
}
|
|
191
|
+
}, ImageFormat.PNG, 1);
|
|
192
|
+
let outCanvContext = this.canvasElement.getContext('2d');
|
|
193
|
+
outCanvContext.drawImage(this.videoElement, 0, 0, this.canvasElement.width, this.canvasElement.height);
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
async startIdDetection() {
|
|
197
|
+
if (this.streamPaused)
|
|
198
|
+
return;
|
|
199
|
+
this.idML5Detector.initDetector();
|
|
200
|
+
}
|
|
201
|
+
async startFaceDetection() {
|
|
202
|
+
if (this.streamPaused)
|
|
203
|
+
return;
|
|
204
|
+
this.faceML5Detector.initDetector();
|
|
205
|
+
}
|
|
206
|
+
requestFacePose() {
|
|
207
|
+
var pose = FacePosePick.randomEnum(FacePose);
|
|
208
|
+
// var pose = FacePose.TiltLeft;
|
|
209
|
+
this.callbackChangeTitle(pose);
|
|
210
|
+
return pose;
|
|
211
|
+
}
|
|
212
|
+
changeFacePose() {
|
|
213
|
+
this.callbackChangeTitle(null);
|
|
214
|
+
}
|
|
215
|
+
changeIDPose(pose) {
|
|
216
|
+
this.callbackChangeTitle(pose);
|
|
217
|
+
}
|
|
218
|
+
stopAnimation() {
|
|
219
|
+
this.callbackStopAnimation();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
window.addEventListener('resize', Stream.orientationChange, false);
|
|
223
|
+
window.addEventListener('orientationchange', Stream.orientationChange, false);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function videoRatio(videoElement) {
|
|
2
|
+
const hRatio = videoElement.clientWidth / videoElement.videoWidth;
|
|
3
|
+
const vRatio = videoElement.clientHeight / videoElement.videoHeight;
|
|
4
|
+
return Math.min(hRatio, vRatio);
|
|
5
|
+
}
|
|
6
|
+
export function getVideoRatio(videoElement) {
|
|
7
|
+
const hRatio = videoElement.clientWidth / videoElement.videoWidth;
|
|
8
|
+
const vRatio = videoElement.clientHeight / videoElement.videoHeight;
|
|
9
|
+
return Math.min(hRatio, vRatio);
|
|
10
|
+
}
|