react-native-unit-components 3.5.1 → 3.5.2

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.
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.isVeryfiAvailable = exports.configureAndShowVeryfiCamera = void 0;
7
7
  var _reactNative = require("react-native");
8
+ var _veryfiService = require("./veryfiService.utils");
8
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
10
  let VeryfiLens = null;
10
11
  try {
@@ -20,8 +21,12 @@ exports.isVeryfiAvailable = isVeryfiAvailable;
20
21
  const CHECK_SETTINGS = {
21
22
  documentTypes: ['check'],
22
23
  checksBackIsOn: true,
24
+ checksBackIsRequired: true,
23
25
  blurDetectionIsOn: true,
24
26
  autoDocDetectionAndCropIsOn: true,
27
+ // Without this, a no-document capture is kept in the package and the user
28
+ // lands on the submit screen with an image that can only fail.
29
+ allowSubmitUndetectedDocsIsOn: false,
25
30
  dataExtractionEngine: true,
26
31
  returnStitchedPDF: true,
27
32
  originalImageMaxSizeInMB: 1.4
@@ -34,6 +39,10 @@ const buildEndorsement = bankName => {
34
39
  // Bank-agnostic fallback when the bank name is absent, so the copy never reads "...deposit at ".
35
40
  return `Please make sure to sign the back and write “For mobile deposit ${bank ? `at ${bank}` : 'only'}”`;
36
41
  };
42
+
43
+ // How long to hold delivery waiting for Veryfi's parsed result before falling
44
+ // back to positional labeling.
45
+ const VERDICT_WAIT_MS = 10000;
37
46
  const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError) => {
38
47
  if (!VeryfiLens) {
39
48
  onError('Veryfi SDK is not available');
@@ -42,13 +51,45 @@ const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError)
42
51
  const emitter = new _reactNative.NativeEventEmitter(VeryfiLens.NativeModule);
43
52
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
44
53
  const subscriptions = [];
45
- let delivered = false;
54
+ let capturing = false;
55
+ let dispatched = false;
56
+ let convertedImages = null;
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
+ let verdictPages = null;
59
+ let fallbackTimer = null;
46
60
  const cleanup = () => {
47
61
  subscriptions.forEach(sub => sub.remove());
62
+ if (fallbackTimer != null) {
63
+ clearTimeout(fallbackTimer);
64
+ fallbackTimer = null;
65
+ }
66
+ };
67
+ const dispatchToWeb = images => {
68
+ if (dispatched) return;
69
+ dispatched = true;
70
+ cleanup();
71
+ onImages(images);
72
+ };
73
+
74
+ // Delivery is held briefly so Veryfi's parsed result — the authoritative
75
+ // source for which image is the front — can label the pair before the web
76
+ // renders it. The positional fallback covers slow or failed uploads;
77
+ // position is unreliable across Veryfi versions (the order reversed in
78
+ // Android lens 2.4.0.0), which is exactly why the verdict is preferred.
79
+ const dispatchWhenReady = () => {
80
+ if (dispatched || !convertedImages) return;
81
+ if (verdictPages) {
82
+ const labeled = (0, _veryfiService.labelSidesFromPages)(convertedImages, verdictPages);
83
+ dispatchToWeb(labeled ?? convertedImages);
84
+ return;
85
+ }
86
+ if (fallbackTimer == null) {
87
+ fallbackTimer = setTimeout(() => dispatchToWeb(convertedImages), VERDICT_WAIT_MS);
88
+ }
48
89
  };
49
- const deliverImages = imagePaths => {
50
- if (delivered) return;
51
- delivered = true;
90
+ const convertImages = imagePaths => {
91
+ if (capturing) return;
92
+ capturing = true;
52
93
  let converted = 0;
53
94
  const images = [];
54
95
  imagePaths.forEach((filePath, index) => {
@@ -57,10 +98,11 @@ const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError)
57
98
  () => {
58
99
  converted++;
59
100
  if (converted === imagePaths.length) {
60
- cleanup();
61
101
  if (images.length > 0) {
62
- onImages(images);
102
+ convertedImages = images;
103
+ dispatchWhenReady();
63
104
  } else {
105
+ cleanup();
64
106
  onError('Failed to convert check images');
65
107
  }
66
108
  }
@@ -73,8 +115,8 @@ const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError)
73
115
  });
74
116
  converted++;
75
117
  if (converted === imagePaths.length) {
76
- cleanup();
77
- onImages(images);
118
+ convertedImages = images;
119
+ dispatchWhenReady();
78
120
  }
79
121
  });
80
122
  });
@@ -87,14 +129,28 @@ const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError)
87
129
  if (event.status === 'inprogress' && event.msg === 'img_stitched_pdf_path') {
88
130
  const paths = event.img_original_paths || [];
89
131
  if (paths.length > 0) {
90
- deliverImages(paths);
132
+ convertImages(paths);
91
133
  }
92
134
  }
93
135
  }));
136
+ subscriptions.push(
137
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
138
+ emitter.addListener(VeryfiLens.Events.onVeryfiLensSuccess, event => {
139
+ verdictPages = event?.data?.meta?.pages ?? null;
140
+ dispatchWhenReady();
141
+ }));
94
142
 
95
- // No onClose listener — if the user cancels, we simply don't dispatch
96
- // unitVeryfiResponse, and the web SDK's polling handles the timeout.
97
-
143
+ // User cancelled (X button) without submitting: the web side never resets its
144
+ // loading state on its own, so deliver an empty response to move it off the
145
+ // stuck Continue. Grace period covers a close event racing the stitched event.
146
+ subscriptions.push(emitter.addListener(VeryfiLens.Events.onVeryfiLensClose, () => {
147
+ setTimeout(() => {
148
+ if (capturing || dispatched) return;
149
+ dispatched = true;
150
+ cleanup();
151
+ onImages([]);
152
+ }, 1500);
153
+ }));
98
154
  subscriptions.push(
99
155
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
100
156
  emitter.addListener(VeryfiLens.Events.onVeryfiLensError, event => {
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","VeryfiLens","default","isVeryfiAvailable","exports","CHECK_SETTINGS","documentTypes","checksBackIsOn","blurDetectionIsOn","autoDocDetectionAndCropIsOn","dataExtractionEngine","returnStitchedPDF","originalImageMaxSizeInMB","BACK_CAPTURE_MODAL_KEY","buildEndorsement","bankName","bank","trim","configureAndShowVeryfiCamera","credentials","onImages","onError","emitter","NativeEventEmitter","NativeModule","subscriptions","delivered","cleanup","forEach","sub","remove","deliverImages","imagePaths","converted","images","filePath","index","getFileBase64","length","base64Data","push","base64Img","isFront","addListener","Events","onVeryfiLensUpdate","event","status","msg","paths","img_original_paths","onVeryfiLensError","veryfiCredentials","clientId","userName","apiKey","url","endorsement","settings","customLensStrings","en","configureWithCredentials","showCamera"],"sourceRoot":"../../../src","sources":["services/veryfiService.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_veryfiService","VeryfiLens","default","isVeryfiAvailable","exports","CHECK_SETTINGS","documentTypes","checksBackIsOn","checksBackIsRequired","blurDetectionIsOn","autoDocDetectionAndCropIsOn","allowSubmitUndetectedDocsIsOn","dataExtractionEngine","returnStitchedPDF","originalImageMaxSizeInMB","BACK_CAPTURE_MODAL_KEY","buildEndorsement","bankName","bank","trim","VERDICT_WAIT_MS","configureAndShowVeryfiCamera","credentials","onImages","onError","emitter","NativeEventEmitter","NativeModule","subscriptions","capturing","dispatched","convertedImages","verdictPages","fallbackTimer","cleanup","forEach","sub","remove","clearTimeout","dispatchToWeb","images","dispatchWhenReady","labeled","labelSidesFromPages","setTimeout","convertImages","imagePaths","converted","filePath","index","getFileBase64","length","base64Data","push","base64Img","isFront","addListener","Events","onVeryfiLensUpdate","event","status","msg","paths","img_original_paths","onVeryfiLensSuccess","data","meta","pages","onVeryfiLensClose","onVeryfiLensError","veryfiCredentials","clientId","userName","apiKey","url","endorsement","settings","customLensStrings","en","configureWithCredentials","showCamera"],"sourceRoot":"../../../src","sources":["services/veryfiService.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.readJpegDimensions = exports.labelSidesFromPages = void 0;
7
+ const JPEG_SOF_MARKERS = [0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf];
8
+ const readJpegDimensions = base64 => {
9
+ try {
10
+ // SOF sits near the file start; a 4-aligned prefix keeps atob happy and cheap.
11
+ const prefix = base64.length > 786432 ? base64.slice(0, 786432) : base64;
12
+ const bytes = atob(prefix);
13
+ if (bytes.charCodeAt(0) !== 0xff || bytes.charCodeAt(1) !== 0xd8) return null;
14
+ let i = 2;
15
+ while (i + 9 < bytes.length) {
16
+ if (bytes.charCodeAt(i) !== 0xff) {
17
+ i++;
18
+ continue;
19
+ }
20
+ const marker = bytes.charCodeAt(i + 1);
21
+ if (marker === 0xff) {
22
+ i++;
23
+ continue;
24
+ }
25
+ if (marker === 0x01 || marker >= 0xd0 && marker <= 0xd9) {
26
+ i += 2;
27
+ continue;
28
+ }
29
+ if (JPEG_SOF_MARKERS.includes(marker)) {
30
+ return {
31
+ height: bytes.charCodeAt(i + 5) * 256 + bytes.charCodeAt(i + 6),
32
+ width: bytes.charCodeAt(i + 7) * 256 + bytes.charCodeAt(i + 8)
33
+ };
34
+ }
35
+ i += 2 + bytes.charCodeAt(i + 2) * 256 + bytes.charCodeAt(i + 3);
36
+ }
37
+ return null;
38
+ } catch {
39
+ return null;
40
+ }
41
+ };
42
+
43
+ // Veryfi's parsed result is the authority on which image is the front
44
+ // (their meta.pages[].is_front); page order does not correspond to the
45
+ // delivery array's order, so pages are matched to our images by exact
46
+ // pixel dimensions. Returns null whenever the verdict is not unambiguous.
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
+ exports.readJpegDimensions = readJpegDimensions;
49
+ const labelSidesFromPages = (images, pages) => {
50
+ if (!Array.isArray(pages) || pages.length !== 2 || images.length !== 2) return null;
51
+ const fronts = pages.filter(p => p && p.is_front === true);
52
+ const backs = pages.filter(p => p && p.is_front === false);
53
+ const frontPage = fronts[0];
54
+ const backPage = backs[0];
55
+ if (fronts.length !== 1 || backs.length !== 1 || !frontPage || !backPage) return null;
56
+ if (typeof frontPage.width !== 'number' || typeof frontPage.height !== 'number') return null;
57
+ const dims = [];
58
+ for (const img of images) {
59
+ const d = readJpegDimensions(img.base64Img);
60
+ if (!d) return null;
61
+ dims.push(d);
62
+ }
63
+
64
+ // Veryfi may auto-rotate pages in the parsed result, so dimensions are
65
+ // compared as an unordered pair.
66
+ const sameDims = (d, w, h) => d.width === w && d.height === h || d.width === h && d.height === w;
67
+ const matchesFront = dims.map(d => sameDims(d, frontPage.width, frontPage.height));
68
+ if (matchesFront.filter(Boolean).length !== 1) return null;
69
+ const frontIdx = matchesFront.indexOf(true);
70
+ const backIdx = 1 - frontIdx;
71
+ const frontImage = images[frontIdx];
72
+ const backImage = images[backIdx];
73
+ const backDims = dims[backIdx];
74
+ if (!frontImage || !backImage || !backDims) return null;
75
+ if (typeof backPage.width === 'number' && typeof backPage.height === 'number') {
76
+ if (!sameDims(backDims, backPage.width, backPage.height)) return null;
77
+ }
78
+ return [{
79
+ base64Img: frontImage.base64Img,
80
+ isFront: true
81
+ }, {
82
+ base64Img: backImage.base64Img,
83
+ isFront: false
84
+ }];
85
+ };
86
+ exports.labelSidesFromPages = labelSidesFromPages;
87
+ //# sourceMappingURL=veryfiService.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["JPEG_SOF_MARKERS","readJpegDimensions","base64","prefix","length","slice","bytes","atob","charCodeAt","i","marker","includes","height","width","exports","labelSidesFromPages","images","pages","Array","isArray","fronts","filter","p","is_front","backs","frontPage","backPage","dims","img","d","base64Img","push","sameDims","w","h","matchesFront","map","Boolean","frontIdx","indexOf","backIdx","frontImage","backImage","backDims","isFront"],"sourceRoot":"../../../src","sources":["services/veryfiService.utils.ts"],"mappings":"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","ignoreList":[]}
@@ -21,7 +21,7 @@ var _UNFontFileHelper = require("../nativeModulesHelpers/UNFontFileHelper/UNFont
21
21
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
22
22
  class UnitComponentsSDK {
23
23
  static securitySettings = _UnitComponentsSdk2.UNComponentsSDKConstants.securitySettings;
24
- static sdkVersion = '3.5.1';
24
+ static sdkVersion = '3.5.2';
25
25
  static iosFontBase64Map = {};
26
26
  static init = async (env, theme, language, fonts, webVersioningStrategy = _UnitComponentsSdk2.UNComponentsSDKConstants.webSDKRecommendedStrategy, securitySettings = _UnitComponentsSdk2.UNComponentsSDKConstants.securitySettings) => {
27
27
  try {
@@ -1,4 +1,5 @@
1
1
  import { NativeEventEmitter } from 'react-native';
2
+ import { labelSidesFromPages } from './veryfiService.utils';
2
3
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
3
4
  let VeryfiLens = null;
4
5
  try {
@@ -13,8 +14,12 @@ export const isVeryfiAvailable = () => {
13
14
  const CHECK_SETTINGS = {
14
15
  documentTypes: ['check'],
15
16
  checksBackIsOn: true,
17
+ checksBackIsRequired: true,
16
18
  blurDetectionIsOn: true,
17
19
  autoDocDetectionAndCropIsOn: true,
20
+ // Without this, a no-document capture is kept in the package and the user
21
+ // lands on the submit screen with an image that can only fail.
22
+ allowSubmitUndetectedDocsIsOn: false,
18
23
  dataExtractionEngine: true,
19
24
  returnStitchedPDF: true,
20
25
  originalImageMaxSizeInMB: 1.4
@@ -27,6 +32,10 @@ const buildEndorsement = bankName => {
27
32
  // Bank-agnostic fallback when the bank name is absent, so the copy never reads "...deposit at ".
28
33
  return `Please make sure to sign the back and write “For mobile deposit ${bank ? `at ${bank}` : 'only'}”`;
29
34
  };
35
+
36
+ // How long to hold delivery waiting for Veryfi's parsed result before falling
37
+ // back to positional labeling.
38
+ const VERDICT_WAIT_MS = 10000;
30
39
  export const configureAndShowVeryfiCamera = (credentials, bankName, onImages, onError) => {
31
40
  if (!VeryfiLens) {
32
41
  onError('Veryfi SDK is not available');
@@ -35,13 +44,45 @@ export const configureAndShowVeryfiCamera = (credentials, bankName, onImages, on
35
44
  const emitter = new NativeEventEmitter(VeryfiLens.NativeModule);
36
45
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
46
  const subscriptions = [];
38
- let delivered = false;
47
+ let capturing = false;
48
+ let dispatched = false;
49
+ let convertedImages = null;
50
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
51
+ let verdictPages = null;
52
+ let fallbackTimer = null;
39
53
  const cleanup = () => {
40
54
  subscriptions.forEach(sub => sub.remove());
55
+ if (fallbackTimer != null) {
56
+ clearTimeout(fallbackTimer);
57
+ fallbackTimer = null;
58
+ }
59
+ };
60
+ const dispatchToWeb = images => {
61
+ if (dispatched) return;
62
+ dispatched = true;
63
+ cleanup();
64
+ onImages(images);
65
+ };
66
+
67
+ // Delivery is held briefly so Veryfi's parsed result — the authoritative
68
+ // source for which image is the front — can label the pair before the web
69
+ // renders it. The positional fallback covers slow or failed uploads;
70
+ // position is unreliable across Veryfi versions (the order reversed in
71
+ // Android lens 2.4.0.0), which is exactly why the verdict is preferred.
72
+ const dispatchWhenReady = () => {
73
+ if (dispatched || !convertedImages) return;
74
+ if (verdictPages) {
75
+ const labeled = labelSidesFromPages(convertedImages, verdictPages);
76
+ dispatchToWeb(labeled ?? convertedImages);
77
+ return;
78
+ }
79
+ if (fallbackTimer == null) {
80
+ fallbackTimer = setTimeout(() => dispatchToWeb(convertedImages), VERDICT_WAIT_MS);
81
+ }
41
82
  };
42
- const deliverImages = imagePaths => {
43
- if (delivered) return;
44
- delivered = true;
83
+ const convertImages = imagePaths => {
84
+ if (capturing) return;
85
+ capturing = true;
45
86
  let converted = 0;
46
87
  const images = [];
47
88
  imagePaths.forEach((filePath, index) => {
@@ -50,10 +91,11 @@ export const configureAndShowVeryfiCamera = (credentials, bankName, onImages, on
50
91
  () => {
51
92
  converted++;
52
93
  if (converted === imagePaths.length) {
53
- cleanup();
54
94
  if (images.length > 0) {
55
- onImages(images);
95
+ convertedImages = images;
96
+ dispatchWhenReady();
56
97
  } else {
98
+ cleanup();
57
99
  onError('Failed to convert check images');
58
100
  }
59
101
  }
@@ -66,8 +108,8 @@ export const configureAndShowVeryfiCamera = (credentials, bankName, onImages, on
66
108
  });
67
109
  converted++;
68
110
  if (converted === imagePaths.length) {
69
- cleanup();
70
- onImages(images);
111
+ convertedImages = images;
112
+ dispatchWhenReady();
71
113
  }
72
114
  });
73
115
  });
@@ -80,14 +122,28 @@ export const configureAndShowVeryfiCamera = (credentials, bankName, onImages, on
80
122
  if (event.status === 'inprogress' && event.msg === 'img_stitched_pdf_path') {
81
123
  const paths = event.img_original_paths || [];
82
124
  if (paths.length > 0) {
83
- deliverImages(paths);
125
+ convertImages(paths);
84
126
  }
85
127
  }
86
128
  }));
129
+ subscriptions.push(
130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
+ emitter.addListener(VeryfiLens.Events.onVeryfiLensSuccess, event => {
132
+ verdictPages = event?.data?.meta?.pages ?? null;
133
+ dispatchWhenReady();
134
+ }));
87
135
 
88
- // No onClose listener — if the user cancels, we simply don't dispatch
89
- // unitVeryfiResponse, and the web SDK's polling handles the timeout.
90
-
136
+ // User cancelled (X button) without submitting: the web side never resets its
137
+ // loading state on its own, so deliver an empty response to move it off the
138
+ // stuck Continue. Grace period covers a close event racing the stitched event.
139
+ subscriptions.push(emitter.addListener(VeryfiLens.Events.onVeryfiLensClose, () => {
140
+ setTimeout(() => {
141
+ if (capturing || dispatched) return;
142
+ dispatched = true;
143
+ cleanup();
144
+ onImages([]);
145
+ }, 1500);
146
+ }));
91
147
  subscriptions.push(
92
148
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
149
  emitter.addListener(VeryfiLens.Events.onVeryfiLensError, event => {
@@ -1 +1 @@
1
- {"version":3,"names":["NativeEventEmitter","VeryfiLens","require","default","isVeryfiAvailable","CHECK_SETTINGS","documentTypes","checksBackIsOn","blurDetectionIsOn","autoDocDetectionAndCropIsOn","dataExtractionEngine","returnStitchedPDF","originalImageMaxSizeInMB","BACK_CAPTURE_MODAL_KEY","buildEndorsement","bankName","bank","trim","configureAndShowVeryfiCamera","credentials","onImages","onError","emitter","NativeModule","subscriptions","delivered","cleanup","forEach","sub","remove","deliverImages","imagePaths","converted","images","filePath","index","getFileBase64","length","base64Data","push","base64Img","isFront","addListener","Events","onVeryfiLensUpdate","event","status","msg","paths","img_original_paths","onVeryfiLensError","veryfiCredentials","clientId","userName","apiKey","url","endorsement","settings","customLensStrings","en","configureWithCredentials","showCamera"],"sourceRoot":"../../../src","sources":["services/veryfiService.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["NativeEventEmitter","labelSidesFromPages","VeryfiLens","require","default","isVeryfiAvailable","CHECK_SETTINGS","documentTypes","checksBackIsOn","checksBackIsRequired","blurDetectionIsOn","autoDocDetectionAndCropIsOn","allowSubmitUndetectedDocsIsOn","dataExtractionEngine","returnStitchedPDF","originalImageMaxSizeInMB","BACK_CAPTURE_MODAL_KEY","buildEndorsement","bankName","bank","trim","VERDICT_WAIT_MS","configureAndShowVeryfiCamera","credentials","onImages","onError","emitter","NativeModule","subscriptions","capturing","dispatched","convertedImages","verdictPages","fallbackTimer","cleanup","forEach","sub","remove","clearTimeout","dispatchToWeb","images","dispatchWhenReady","labeled","setTimeout","convertImages","imagePaths","converted","filePath","index","getFileBase64","length","base64Data","push","base64Img","isFront","addListener","Events","onVeryfiLensUpdate","event","status","msg","paths","img_original_paths","onVeryfiLensSuccess","data","meta","pages","onVeryfiLensClose","onVeryfiLensError","veryfiCredentials","clientId","userName","apiKey","url","endorsement","settings","customLensStrings","en","configureWithCredentials","showCamera"],"sourceRoot":"../../../src","sources":["services/veryfiService.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,79 @@
1
+ const JPEG_SOF_MARKERS = [0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf];
2
+ export const readJpegDimensions = base64 => {
3
+ try {
4
+ // SOF sits near the file start; a 4-aligned prefix keeps atob happy and cheap.
5
+ const prefix = base64.length > 786432 ? base64.slice(0, 786432) : base64;
6
+ const bytes = atob(prefix);
7
+ if (bytes.charCodeAt(0) !== 0xff || bytes.charCodeAt(1) !== 0xd8) return null;
8
+ let i = 2;
9
+ while (i + 9 < bytes.length) {
10
+ if (bytes.charCodeAt(i) !== 0xff) {
11
+ i++;
12
+ continue;
13
+ }
14
+ const marker = bytes.charCodeAt(i + 1);
15
+ if (marker === 0xff) {
16
+ i++;
17
+ continue;
18
+ }
19
+ if (marker === 0x01 || marker >= 0xd0 && marker <= 0xd9) {
20
+ i += 2;
21
+ continue;
22
+ }
23
+ if (JPEG_SOF_MARKERS.includes(marker)) {
24
+ return {
25
+ height: bytes.charCodeAt(i + 5) * 256 + bytes.charCodeAt(i + 6),
26
+ width: bytes.charCodeAt(i + 7) * 256 + bytes.charCodeAt(i + 8)
27
+ };
28
+ }
29
+ i += 2 + bytes.charCodeAt(i + 2) * 256 + bytes.charCodeAt(i + 3);
30
+ }
31
+ return null;
32
+ } catch {
33
+ return null;
34
+ }
35
+ };
36
+
37
+ // Veryfi's parsed result is the authority on which image is the front
38
+ // (their meta.pages[].is_front); page order does not correspond to the
39
+ // delivery array's order, so pages are matched to our images by exact
40
+ // pixel dimensions. Returns null whenever the verdict is not unambiguous.
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ export const labelSidesFromPages = (images, pages) => {
43
+ if (!Array.isArray(pages) || pages.length !== 2 || images.length !== 2) return null;
44
+ const fronts = pages.filter(p => p && p.is_front === true);
45
+ const backs = pages.filter(p => p && p.is_front === false);
46
+ const frontPage = fronts[0];
47
+ const backPage = backs[0];
48
+ if (fronts.length !== 1 || backs.length !== 1 || !frontPage || !backPage) return null;
49
+ if (typeof frontPage.width !== 'number' || typeof frontPage.height !== 'number') return null;
50
+ const dims = [];
51
+ for (const img of images) {
52
+ const d = readJpegDimensions(img.base64Img);
53
+ if (!d) return null;
54
+ dims.push(d);
55
+ }
56
+
57
+ // Veryfi may auto-rotate pages in the parsed result, so dimensions are
58
+ // compared as an unordered pair.
59
+ const sameDims = (d, w, h) => d.width === w && d.height === h || d.width === h && d.height === w;
60
+ const matchesFront = dims.map(d => sameDims(d, frontPage.width, frontPage.height));
61
+ if (matchesFront.filter(Boolean).length !== 1) return null;
62
+ const frontIdx = matchesFront.indexOf(true);
63
+ const backIdx = 1 - frontIdx;
64
+ const frontImage = images[frontIdx];
65
+ const backImage = images[backIdx];
66
+ const backDims = dims[backIdx];
67
+ if (!frontImage || !backImage || !backDims) return null;
68
+ if (typeof backPage.width === 'number' && typeof backPage.height === 'number') {
69
+ if (!sameDims(backDims, backPage.width, backPage.height)) return null;
70
+ }
71
+ return [{
72
+ base64Img: frontImage.base64Img,
73
+ isFront: true
74
+ }, {
75
+ base64Img: backImage.base64Img,
76
+ isFront: false
77
+ }];
78
+ };
79
+ //# sourceMappingURL=veryfiService.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["JPEG_SOF_MARKERS","readJpegDimensions","base64","prefix","length","slice","bytes","atob","charCodeAt","i","marker","includes","height","width","labelSidesFromPages","images","pages","Array","isArray","fronts","filter","p","is_front","backs","frontPage","backPage","dims","img","d","base64Img","push","sameDims","w","h","matchesFront","map","Boolean","frontIdx","indexOf","backIdx","frontImage","backImage","backDims","isFront"],"sourceRoot":"../../../src","sources":["services/veryfiService.utils.ts"],"mappings":"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","ignoreList":[]}
@@ -14,7 +14,7 @@ import UNSnapshotProtectionHelper from '../nativeModulesHelpers/UNSanpshotProtec
14
14
  import { loadIosFontBase64 } from '../nativeModulesHelpers/UNFontFileHelper/UNFontFileHelper';
15
15
  export class UnitComponentsSDK {
16
16
  static securitySettings = UNComponentsSDKConstants.securitySettings;
17
- static sdkVersion = '3.5.1';
17
+ static sdkVersion = '3.5.2';
18
18
  static iosFontBase64Map = {};
19
19
  static init = async (env, theme, language, fonts, webVersioningStrategy = UNComponentsSDKConstants.webSDKRecommendedStrategy, securitySettings = UNComponentsSDKConstants.securitySettings) => {
20
20
  try {
@@ -1,8 +1,6 @@
1
1
  import type { UNVeryfiCredentials } from '../types/shared/veryfi.types';
2
+ import type { UNVeryfiImage } from './veryfiService.utils';
3
+ export type { UNVeryfiImage } from './veryfiService.utils';
2
4
  export declare const isVeryfiAvailable: () => boolean;
3
- export interface UNVeryfiImage {
4
- base64Img: string;
5
- isFront: boolean;
6
- }
7
5
  export declare const configureAndShowVeryfiCamera: (credentials: UNVeryfiCredentials, bankName: string | undefined, onImages: (images: UNVeryfiImage[]) => void, onError: (error: string) => void) => void;
8
6
  //# sourceMappingURL=veryfiService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"veryfiService.d.ts","sourceRoot":"","sources":["../../../../src/services/veryfiService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAWxE,eAAO,MAAM,iBAAiB,QAAO,OAEpC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAqBD,eAAO,MAAM,4BAA4B,gBAC1B,mBAAmB,YACtB,MAAM,GAAG,SAAS,qBACT,aAAa,EAAE,KAAK,IAAI,mBAC1B,MAAM,KAAK,IAAI,KAC/B,IAiGF,CAAC"}
1
+ {"version":3,"file":"veryfiService.d.ts","sourceRoot":"","sources":["../../../../src/services/veryfiService.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAW3D,eAAO,MAAM,iBAAiB,QAAO,OAEpC,CAAC;AA6BF,eAAO,MAAM,4BAA4B,gBAC1B,mBAAmB,YACtB,MAAM,GAAG,SAAS,qBACT,aAAa,EAAE,KAAK,IAAI,mBAC1B,MAAM,KAAK,IAAI,KAC/B,IAsJF,CAAC"}
@@ -0,0 +1,10 @@
1
+ export interface UNVeryfiImage {
2
+ base64Img: string;
3
+ isFront: boolean;
4
+ }
5
+ export declare const readJpegDimensions: (base64: string) => {
6
+ width: number;
7
+ height: number;
8
+ } | null;
9
+ export declare const labelSidesFromPages: (images: UNVeryfiImage[], pages: any) => UNVeryfiImage[] | null;
10
+ //# sourceMappingURL=veryfiService.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"veryfiService.utils.d.ts","sourceRoot":"","sources":["../../../../src/services/veryfiService.utils.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAID,eAAO,MAAM,kBAAkB,WAAY,MAAM,KAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAiCvF,CAAC;AAOF,eAAO,MAAM,mBAAmB,WAAY,aAAa,EAAE,SAAS,GAAG,KAAG,aAAa,EAAE,GAAG,IAuC3F,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-unit-components",
3
- "version": "3.5.1",
3
+ "version": "3.5.2",
4
4
  "description": "Unit React Native components",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -1,5 +1,9 @@
1
1
  import { NativeEventEmitter } from 'react-native';
2
2
  import type { UNVeryfiCredentials } from '../types/shared/veryfi.types';
3
+ import { labelSidesFromPages } from './veryfiService.utils';
4
+ import type { UNVeryfiImage } from './veryfiService.utils';
5
+
6
+ export type { UNVeryfiImage } from './veryfiService.utils';
3
7
 
4
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
9
  let VeryfiLens: any = null;
@@ -14,16 +18,15 @@ export const isVeryfiAvailable = (): boolean => {
14
18
  return VeryfiLens != null;
15
19
  };
16
20
 
17
- export interface UNVeryfiImage {
18
- base64Img: string;
19
- isFront: boolean;
20
- }
21
-
22
21
  const CHECK_SETTINGS = {
23
22
  documentTypes: ['check'],
24
23
  checksBackIsOn: true,
24
+ checksBackIsRequired: true,
25
25
  blurDetectionIsOn: true,
26
26
  autoDocDetectionAndCropIsOn: true,
27
+ // Without this, a no-document capture is kept in the package and the user
28
+ // lands on the submit screen with an image that can only fail.
29
+ allowSubmitUndetectedDocsIsOn: false,
27
30
  dataExtractionEngine: true,
28
31
  returnStitchedPDF: true,
29
32
  originalImageMaxSizeInMB: 1.4,
@@ -38,6 +41,10 @@ const buildEndorsement = (bankName?: string): string => {
38
41
  return `Please make sure to sign the back and write “For mobile deposit ${bank ? `at ${bank}` : 'only'}”`;
39
42
  };
40
43
 
44
+ // How long to hold delivery waiting for Veryfi's parsed result before falling
45
+ // back to positional labeling.
46
+ const VERDICT_WAIT_MS = 10000;
47
+
41
48
  export const configureAndShowVeryfiCamera = (
42
49
  credentials: UNVeryfiCredentials,
43
50
  bankName: string | undefined,
@@ -52,15 +59,48 @@ export const configureAndShowVeryfiCamera = (
52
59
  const emitter = new NativeEventEmitter(VeryfiLens.NativeModule);
53
60
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
61
  const subscriptions: any[] = [];
55
- let delivered = false;
62
+ let capturing = false;
63
+ let dispatched = false;
64
+ let convertedImages: UNVeryfiImage[] | null = null;
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ let verdictPages: any = null;
67
+ let fallbackTimer: ReturnType<typeof setTimeout> | null = null;
56
68
 
57
69
  const cleanup = () => {
58
70
  subscriptions.forEach((sub) => sub.remove());
71
+ if (fallbackTimer != null) {
72
+ clearTimeout(fallbackTimer);
73
+ fallbackTimer = null;
74
+ }
75
+ };
76
+
77
+ const dispatchToWeb = (images: UNVeryfiImage[]) => {
78
+ if (dispatched) return;
79
+ dispatched = true;
80
+ cleanup();
81
+ onImages(images);
82
+ };
83
+
84
+ // Delivery is held briefly so Veryfi's parsed result — the authoritative
85
+ // source for which image is the front — can label the pair before the web
86
+ // renders it. The positional fallback covers slow or failed uploads;
87
+ // position is unreliable across Veryfi versions (the order reversed in
88
+ // Android lens 2.4.0.0), which is exactly why the verdict is preferred.
89
+ const dispatchWhenReady = () => {
90
+ if (dispatched || !convertedImages) return;
91
+ if (verdictPages) {
92
+ const labeled = labelSidesFromPages(convertedImages, verdictPages);
93
+ dispatchToWeb(labeled ?? convertedImages);
94
+ return;
95
+ }
96
+ if (fallbackTimer == null) {
97
+ fallbackTimer = setTimeout(() => dispatchToWeb(convertedImages as UNVeryfiImage[]), VERDICT_WAIT_MS);
98
+ }
59
99
  };
60
100
 
61
- const deliverImages = (imagePaths: string[]) => {
62
- if (delivered) return;
63
- delivered = true;
101
+ const convertImages = (imagePaths: string[]) => {
102
+ if (capturing) return;
103
+ capturing = true;
64
104
 
65
105
  let converted = 0;
66
106
  const images: UNVeryfiImage[] = [];
@@ -72,10 +112,11 @@ export const configureAndShowVeryfiCamera = (
72
112
  () => {
73
113
  converted++;
74
114
  if (converted === imagePaths.length) {
75
- cleanup();
76
115
  if (images.length > 0) {
77
- onImages(images);
116
+ convertedImages = images;
117
+ dispatchWhenReady();
78
118
  } else {
119
+ cleanup();
79
120
  onError('Failed to convert check images');
80
121
  }
81
122
  }
@@ -88,8 +129,8 @@ export const configureAndShowVeryfiCamera = (
88
129
  });
89
130
  converted++;
90
131
  if (converted === imagePaths.length) {
91
- cleanup();
92
- onImages(images);
132
+ convertedImages = images;
133
+ dispatchWhenReady();
93
134
  }
94
135
  }
95
136
  );
@@ -103,14 +144,33 @@ export const configureAndShowVeryfiCamera = (
103
144
  if (event.status === 'inprogress' && event.msg === 'img_stitched_pdf_path') {
104
145
  const paths = event.img_original_paths || [];
105
146
  if (paths.length > 0) {
106
- deliverImages(paths);
147
+ convertImages(paths);
107
148
  }
108
149
  }
109
150
  })
110
151
  );
111
152
 
112
- // No onClose listener — if the user cancels, we simply don't dispatch
113
- // unitVeryfiResponse, and the web SDK's polling handles the timeout.
153
+ subscriptions.push(
154
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
155
+ emitter.addListener(VeryfiLens.Events.onVeryfiLensSuccess, (event: any) => {
156
+ verdictPages = event?.data?.meta?.pages ?? null;
157
+ dispatchWhenReady();
158
+ })
159
+ );
160
+
161
+ // User cancelled (X button) without submitting: the web side never resets its
162
+ // loading state on its own, so deliver an empty response to move it off the
163
+ // stuck Continue. Grace period covers a close event racing the stitched event.
164
+ subscriptions.push(
165
+ emitter.addListener(VeryfiLens.Events.onVeryfiLensClose, () => {
166
+ setTimeout(() => {
167
+ if (capturing || dispatched) return;
168
+ dispatched = true;
169
+ cleanup();
170
+ onImages([]);
171
+ }, 1500);
172
+ })
173
+ );
114
174
 
115
175
  subscriptions.push(
116
176
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -0,0 +1,87 @@
1
+ export interface UNVeryfiImage {
2
+ base64Img: string;
3
+ isFront: boolean;
4
+ }
5
+
6
+ const JPEG_SOF_MARKERS = [0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf];
7
+
8
+ export const readJpegDimensions = (base64: string): { width: number; height: number } | null => {
9
+ try {
10
+ // SOF sits near the file start; a 4-aligned prefix keeps atob happy and cheap.
11
+ const prefix = base64.length > 786432 ? base64.slice(0, 786432) : base64;
12
+ const bytes = atob(prefix);
13
+ if (bytes.charCodeAt(0) !== 0xff || bytes.charCodeAt(1) !== 0xd8) return null;
14
+ let i = 2;
15
+ while (i + 9 < bytes.length) {
16
+ if (bytes.charCodeAt(i) !== 0xff) {
17
+ i++;
18
+ continue;
19
+ }
20
+ const marker = bytes.charCodeAt(i + 1);
21
+ if (marker === 0xff) {
22
+ i++;
23
+ continue;
24
+ }
25
+ if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd9)) {
26
+ i += 2;
27
+ continue;
28
+ }
29
+ if (JPEG_SOF_MARKERS.includes(marker)) {
30
+ return {
31
+ height: bytes.charCodeAt(i + 5) * 256 + bytes.charCodeAt(i + 6),
32
+ width: bytes.charCodeAt(i + 7) * 256 + bytes.charCodeAt(i + 8),
33
+ };
34
+ }
35
+ i += 2 + bytes.charCodeAt(i + 2) * 256 + bytes.charCodeAt(i + 3);
36
+ }
37
+ return null;
38
+ } catch {
39
+ return null;
40
+ }
41
+ };
42
+
43
+ // Veryfi's parsed result is the authority on which image is the front
44
+ // (their meta.pages[].is_front); page order does not correspond to the
45
+ // delivery array's order, so pages are matched to our images by exact
46
+ // pixel dimensions. Returns null whenever the verdict is not unambiguous.
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
+ export const labelSidesFromPages = (images: UNVeryfiImage[], pages: any): UNVeryfiImage[] | null => {
49
+ if (!Array.isArray(pages) || pages.length !== 2 || images.length !== 2) return null;
50
+
51
+ const fronts = pages.filter((p) => p && p.is_front === true);
52
+ const backs = pages.filter((p) => p && p.is_front === false);
53
+ const frontPage = fronts[0];
54
+ const backPage = backs[0];
55
+ if (fronts.length !== 1 || backs.length !== 1 || !frontPage || !backPage) return null;
56
+ if (typeof frontPage.width !== 'number' || typeof frontPage.height !== 'number') return null;
57
+
58
+ const dims: { width: number; height: number }[] = [];
59
+ for (const img of images) {
60
+ const d = readJpegDimensions(img.base64Img);
61
+ if (!d) return null;
62
+ dims.push(d);
63
+ }
64
+
65
+ // Veryfi may auto-rotate pages in the parsed result, so dimensions are
66
+ // compared as an unordered pair.
67
+ const sameDims = (d: { width: number; height: number }, w: number, h: number) =>
68
+ (d.width === w && d.height === h) || (d.width === h && d.height === w);
69
+
70
+ const matchesFront = dims.map((d) => sameDims(d, frontPage.width, frontPage.height));
71
+ if (matchesFront.filter(Boolean).length !== 1) return null;
72
+
73
+ const frontIdx = matchesFront.indexOf(true);
74
+ const backIdx = 1 - frontIdx;
75
+ const frontImage = images[frontIdx];
76
+ const backImage = images[backIdx];
77
+ const backDims = dims[backIdx];
78
+ if (!frontImage || !backImage || !backDims) return null;
79
+ if (typeof backPage.width === 'number' && typeof backPage.height === 'number') {
80
+ if (!sameDims(backDims, backPage.width, backPage.height)) return null;
81
+ }
82
+
83
+ return [
84
+ { base64Img: frontImage.base64Img, isFront: true },
85
+ { base64Img: backImage.base64Img, isFront: false },
86
+ ];
87
+ };
@@ -27,7 +27,7 @@ export class UnitComponentsSDK {
27
27
  protected static fonts?: UNFonts;
28
28
  protected static signedNonce?: string;
29
29
  protected static pushProvisionModule?: typeof NativeModules;
30
- protected static sdkVersion = '3.5.1';
30
+ protected static sdkVersion = '3.5.2';
31
31
  static iosFontBase64Map: Record<string, string> = {};
32
32
 
33
33
  public static init = async (