@myazahq/kyc-sdk-react-native 2.6.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +128 -4
  2. package/android/build.gradle +30 -16
  3. package/android/consumer-rules.pro +22 -0
  4. package/android/src/main/AndroidManifest.xml +17 -6
  5. package/android/src/main/java/com/margelo/nitro/myazakyc/HybridMyazaFaceDetector.kt +27 -72
  6. package/android/src/main/java/com/margelo/nitro/myazakyc/HybridMyazaTextRecognizer.kt +14 -0
  7. package/android/src/main/java/com/margelo/nitro/myazakyc/MlKitModelReadiness.kt +154 -0
  8. package/app.plugin.js +57 -2
  9. package/ios/HybridMyazaTextRecognizer.swift +8 -0
  10. package/nitrogen/generated/android/c++/JHybridMyazaTextRecognizerSpec.cpp +21 -0
  11. package/nitrogen/generated/android/c++/JHybridMyazaTextRecognizerSpec.hpp +2 -0
  12. package/nitrogen/generated/android/kotlin/com/margelo/nitro/myazakyc/HybridMyazaTextRecognizerSpec.kt +8 -0
  13. package/nitrogen/generated/ios/c++/HybridMyazaTextRecognizerSpecSwift.hpp +16 -0
  14. package/nitrogen/generated/ios/swift/HybridMyazaTextRecognizerSpec.swift +2 -0
  15. package/nitrogen/generated/ios/swift/HybridMyazaTextRecognizerSpec_cxx.swift +31 -0
  16. package/nitrogen/generated/shared/c++/HybridMyazaTextRecognizerSpec.cpp +2 -0
  17. package/nitrogen/generated/shared/c++/HybridMyazaTextRecognizerSpec.hpp +2 -0
  18. package/package.json +17 -8
  19. package/src/MyazaKYC.tsx +4 -11
  20. package/src/assets/fonts/Karla_400Regular.ttf +0 -0
  21. package/src/assets/fonts/Karla_500Medium.ttf +0 -0
  22. package/src/assets/fonts/Karla_600SemiBold.ttf +0 -0
  23. package/src/assets/fonts/Karla_700Bold.ttf +0 -0
  24. package/src/assets/fonts/OFL-Karla.txt +93 -0
  25. package/src/assets/fonts/OFL-SpaceGrotesk.txt +93 -0
  26. package/src/assets/fonts/README.md +12 -0
  27. package/src/assets/fonts/SpaceGrotesk_500Medium.ttf +0 -0
  28. package/src/assets/fonts/SpaceGrotesk_600SemiBold.ttf +0 -0
  29. package/src/assets/fonts/SpaceGrotesk_700Bold.ttf +0 -0
  30. package/src/capture/useAutoCapture.ts +8 -1
  31. package/src/components/DocumentCropper.tsx +30 -24
  32. package/src/components/DocumentReview.tsx +11 -1
  33. package/src/components/DocumentReviewSide.tsx +6 -2
  34. package/src/components/DocumentReviewZoom.tsx +5 -1
  35. package/src/components/Icon.tsx +8 -7
  36. package/src/components/KycFlow.tsx +9 -2
  37. package/src/components/MyazaButton.tsx +9 -0
  38. package/src/components/RequiredDocumentPill.tsx +114 -0
  39. package/src/components/StepHeader.tsx +23 -3
  40. package/src/components/documentReviewCopy.ts +39 -0
  41. package/src/components/fonts.ts +14 -17
  42. package/src/components/stepHeaderMeta.tsx +6 -1
  43. package/src/config/documentCaptureMethods.ts +31 -0
  44. package/src/config/workflowMerge.ts +2 -0
  45. package/src/index.ts +5 -10
  46. package/src/lib/documentCaptureCheck.ts +136 -0
  47. package/src/lib/model-ready.ts +82 -0
  48. package/src/lib/prime-models.ts +50 -0
  49. package/src/lib/resubmit.ts +36 -7
  50. package/src/lib/selfie-sharpness.ts +211 -0
  51. package/src/liveness/avatarSource.ts +59 -0
  52. package/src/liveness/useModelReady.ts +9 -55
  53. package/src/mrz/extract.ts +71 -4
  54. package/src/mrz/textRecognizer.ts +36 -0
  55. package/src/mrz/useTextModelReady.ts +21 -0
  56. package/src/screens/DocumentCaptureStep.tsx +177 -93
  57. package/src/screens/LivenessAvatar.tsx +18 -13
  58. package/src/screens/LivenessStep.tsx +37 -0
  59. package/src/screens/MrzScanView.tsx +33 -0
  60. package/src/screens/document/CaptureCheckNotice.tsx +77 -0
  61. package/src/screens/document/UploadPhase.tsx +177 -0
  62. package/src/screens/document/useDocumentCamera.ts +109 -0
  63. package/src/screens/liveness/LivenessOutcome.tsx +4 -1
  64. package/src/screens/liveness/SelfiePreview.tsx +19 -4
  65. package/src/services/api-types.ts +28 -2
  66. package/src/services/api.ts +19 -3
  67. package/src/services/deviceMetadata.ts +1 -1
  68. package/src/services/mediaCompress.ts +23 -5
  69. package/src/specs/MyazaTextRecognizer.nitro.ts +29 -0
  70. package/src/store/kycStore.ts +8 -2
  71. package/src/types/config.ts +15 -0
  72. package/src/MyazaBiometricAuth.tsx +0 -119
  73. package/src/assets/liveness/Blink.gif +0 -0
  74. package/src/assets/liveness/Nod.gif +0 -0
  75. package/src/assets/liveness/Smile.gif +0 -0
  76. package/src/assets/liveness/Turn.gif +0 -0
  77. package/src/lib/biometric-auth.ts +0 -52
  78. package/src/screens/biometric/BiometricAuthFlow.tsx +0 -170
  79. package/src/services/api-biometric.ts +0 -37
  80. package/src/services/api-types-biometric.ts +0 -41
package/app.plugin.js CHANGED
@@ -27,8 +27,12 @@ const pkg = require('./package.json');
27
27
  // unconditionally would break code-signing for every consumer who does not read
28
28
  // chips and has not enabled it.
29
29
  //
30
- // Camera preview/capture itself comes from react-native-vision-camera; add its
31
- // config plugin too. This one is intentionally minimal and idempotent.
30
+ // Camera preview/capture itself comes from react-native-vision-camera, but v5
31
+ // ships NO config plugin (v4 did), so it must NOT be listed in the host app's
32
+ // `plugins`. Expo then loads the package's main entry as a plugin and prebuild
33
+ // dies on `Cannot find module '.../lib/VisionCamera'`. That is why the camera
34
+ // permission and usage string are declared HERE. This plugin is intentionally
35
+ // minimal and idempotent.
32
36
  // ---------------------------------------------------------------------------
33
37
 
34
38
  const CAMERA_USAGE =
@@ -170,6 +174,52 @@ function withAndroidPermissions(config, opts) {
170
174
  });
171
175
  }
172
176
 
177
+ /**
178
+ * Declares `android.hardware.nfc` as NOT required, on the host's manifest.
179
+ *
180
+ * This is not decoration, and it must never be separated from the NFC
181
+ * permission. Android INFERS `<uses-feature android:name="android.hardware.nfc"
182
+ * android:required="true">` from `android.permission.NFC` whenever the feature
183
+ * is not declared explicitly — and Play then hides the app from every device
184
+ * without an NFC radio. For a KYC SDK that is most of the catalogue in the
185
+ * markets we serve.
186
+ *
187
+ * So: the permission (androidPermissionsFor) and this declaration are written
188
+ * under the same `nfc: true` opt-in in withMyazaKyc, and nothing else writes
189
+ * either. plugin.test.ts pins that pairing with a source scan, because two
190
+ * separate functions are otherwise free to drift apart.
191
+ *
192
+ * Pure and exported so the pairing can be pinned by a test. The failure it
193
+ * guards has no runtime symptom in development — the app builds, installs and
194
+ * runs perfectly on the NFC-capable phone the developer is holding, and is
195
+ * simply absent from the store listing for everyone else.
196
+ *
197
+ * @param {Record<string, any>} manifest the `modResults.manifest` object
198
+ */
199
+ function ensureNfcFeatureOptional(manifest) {
200
+ const list = Array.isArray(manifest['uses-feature']) ? manifest['uses-feature'] : [];
201
+ const existing = list.find((f) => f && f.$ && f.$['android:name'] === 'android.hardware.nfc');
202
+ if (existing) {
203
+ // An explicit `required="true"` from the host or another library would
204
+ // reintroduce exactly the store-visibility problem above, so it is
205
+ // overwritten rather than respected.
206
+ existing.$['android:required'] = 'false';
207
+ } else {
208
+ list.push({
209
+ $: { 'android:name': 'android.hardware.nfc', 'android:required': 'false' },
210
+ });
211
+ }
212
+ manifest['uses-feature'] = list;
213
+ return manifest;
214
+ }
215
+
216
+ function withAndroidNfcFeature(config) {
217
+ return withAndroidManifest(config, (cfg) => {
218
+ ensureNfcFeatureOptional(cfg.modResults.manifest);
219
+ return cfg;
220
+ });
221
+ }
222
+
173
223
  /** iOS side of the always-on tier: the Always usage string plus the location
174
224
  * background mode, without which a geofence wake is refused. */
175
225
  function withIosBackgroundLocation(config, customMessage) {
@@ -211,6 +261,10 @@ function withMyazaKyc(config, props = {}) {
211
261
  config = withIosBackgroundLocation(config, props.locationPermission);
212
262
  }
213
263
  if (props.nfc === true) {
264
+ // Android: the permission comes from androidPermissionsFor above; this adds
265
+ // the uses-feature that must accompany it. Never write one without the
266
+ // other — see ensureNfcFeatureOptional.
267
+ config = withAndroidNfcFeature(config);
214
268
  config = withIosNfc(config, props.nfcPermission);
215
269
  }
216
270
  return config;
@@ -222,4 +276,5 @@ module.exports = createRunOncePlugin(withMyazaKyc, pkg.name, pkg.version);
222
276
  module.exports.applyNfcInfoPlist = applyNfcInfoPlist;
223
277
  module.exports.applyNfcEntitlements = applyNfcEntitlements;
224
278
  module.exports.androidPermissionsFor = androidPermissionsFor;
279
+ module.exports.ensureNfcFeatureOptional = ensureNfcFeatureOptional;
225
280
  module.exports.EMRTD_AID = EMRTD_AID;
@@ -27,6 +27,14 @@ import NitroModules
27
27
  // ---------------------------------------------------------------------------
28
28
 
29
29
  final class HybridMyazaTextRecognizer: HybridMyazaTextRecognizerSpec {
30
+ // Apple Vision ships with the OS — there is no model to fetch, no Play
31
+ // Services equivalent, and no window in which recognition is unavailable.
32
+ // These exist only because Android fetches ML Kit's models on demand; iOS
33
+ // answers "ready" unconditionally so the shared TS flow needs no platform
34
+ // branch.
35
+ func isModelReady() throws -> Bool { true }
36
+
37
+ func prepareModel() throws -> Promise<Bool> { Promise.resolved(withResult: true) }
30
38
 
31
39
  func recognizeText(frame: any HybridFrameSpec, bottomFraction: Double) throws -> TextResult {
32
40
  guard
@@ -76,5 +76,26 @@ namespace margelo::nitro::myazakyc {
76
76
  return __promise;
77
77
  }();
78
78
  }
79
+ bool JHybridMyazaTextRecognizerSpec::isModelReady() {
80
+ static const auto method = _javaPart->javaClassStatic()->getMethod<jboolean()>("isModelReady");
81
+ auto __result = method(_javaPart);
82
+ return static_cast<bool>(__result);
83
+ }
84
+ std::shared_ptr<Promise<bool>> JHybridMyazaTextRecognizerSpec::prepareModel() {
85
+ static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JPromise::javaobject>()>("prepareModel");
86
+ auto __result = method(_javaPart);
87
+ return [&]() {
88
+ auto __promise = Promise<bool>::create();
89
+ __result->cthis()->addOnResolvedListener([=](const jni::alias_ref<jni::JObject>& __boxedResult) {
90
+ auto __result = jni::static_ref_cast<jni::JBoolean>(__boxedResult);
91
+ __promise->resolve(static_cast<bool>(__result->value()));
92
+ });
93
+ __result->cthis()->addOnRejectedListener([=](const jni::alias_ref<jni::JThrowable>& __throwable) {
94
+ jni::JniException __jniError(__throwable);
95
+ __promise->reject(std::make_exception_ptr(__jniError));
96
+ });
97
+ return __promise;
98
+ }();
99
+ }
79
100
 
80
101
  } // namespace margelo::nitro::myazakyc
@@ -56,6 +56,8 @@ namespace margelo::nitro::myazakyc {
56
56
  // Methods
57
57
  TextResult recognizeText(const std::shared_ptr<margelo::nitro::camera::HybridFrameSpec>& frame, double bottomFraction) override;
58
58
  std::shared_ptr<Promise<TextResult>> recognizeTextInImage(const std::string& uri, double bottomFraction) override;
59
+ bool isModelReady() override;
60
+ std::shared_ptr<Promise<bool>> prepareModel() override;
59
61
 
60
62
  private:
61
63
  jni::global_ref<JHybridMyazaTextRecognizerSpec::JavaPart> _javaPart;
@@ -37,6 +37,14 @@ abstract class HybridMyazaTextRecognizerSpec: HybridObject() {
37
37
  @DoNotStrip
38
38
  @Keep
39
39
  abstract fun recognizeTextInImage(uri: String, bottomFraction: Double): Promise<TextResult>
40
+
41
+ @DoNotStrip
42
+ @Keep
43
+ abstract fun isModelReady(): Boolean
44
+
45
+ @DoNotStrip
46
+ @Keep
47
+ abstract fun prepareModel(): Promise<Boolean>
40
48
 
41
49
  // Default implementation of `HybridObject.toString()`
42
50
  override fun toString(): String {
@@ -90,6 +90,22 @@ namespace margelo::nitro::myazakyc {
90
90
  auto __value = std::move(__result.value());
91
91
  return __value;
92
92
  }
93
+ inline bool isModelReady() override {
94
+ auto __result = _swiftPart.isModelReady();
95
+ if (__result.hasError()) [[unlikely]] {
96
+ std::rethrow_exception(__result.error());
97
+ }
98
+ auto __value = std::move(__result.value());
99
+ return __value;
100
+ }
101
+ inline std::shared_ptr<Promise<bool>> prepareModel() override {
102
+ auto __result = _swiftPart.prepareModel();
103
+ if (__result.hasError()) [[unlikely]] {
104
+ std::rethrow_exception(__result.error());
105
+ }
106
+ auto __value = std::move(__result.value());
107
+ return __value;
108
+ }
93
109
 
94
110
  private:
95
111
  KycSdkReactNative::HybridMyazaTextRecognizerSpec_cxx _swiftPart;
@@ -16,6 +16,8 @@ public protocol HybridMyazaTextRecognizerSpec_protocol: HybridObject {
16
16
  // Methods
17
17
  func recognizeText(frame: (any HybridFrameSpec), bottomFraction: Double) throws -> TextResult
18
18
  func recognizeTextInImage(uri: String, bottomFraction: Double) throws -> Promise<TextResult>
19
+ func isModelReady() throws -> Bool
20
+ func prepareModel() throws -> Promise<Bool>
19
21
  }
20
22
 
21
23
  public extension HybridMyazaTextRecognizerSpec_protocol {
@@ -159,4 +159,35 @@ open class HybridMyazaTextRecognizerSpec_cxx {
159
159
  return bridge.create_Result_std__shared_ptr_Promise_TextResult___(__exceptionPtr)
160
160
  }
161
161
  }
162
+
163
+ @inline(__always)
164
+ public final func isModelReady() -> bridge.Result_bool_ {
165
+ do {
166
+ let __result = try self.__implementation.isModelReady()
167
+ let __resultCpp = __result
168
+ return bridge.create_Result_bool_(__resultCpp)
169
+ } catch (let __error) {
170
+ let __exceptionPtr = __error.toCpp()
171
+ return bridge.create_Result_bool_(__exceptionPtr)
172
+ }
173
+ }
174
+
175
+ @inline(__always)
176
+ public final func prepareModel() -> bridge.Result_std__shared_ptr_Promise_bool___ {
177
+ do {
178
+ let __result = try self.__implementation.prepareModel()
179
+ let __resultCpp = { () -> bridge.std__shared_ptr_Promise_bool__ in
180
+ let __promise = bridge.create_std__shared_ptr_Promise_bool__()
181
+ let __promiseHolder = bridge.wrap_std__shared_ptr_Promise_bool__(__promise)
182
+ __result
183
+ .then({ __result in __promiseHolder.resolve(__result) })
184
+ .catch({ __error in __promiseHolder.reject(__error.toCpp()) })
185
+ return __promise
186
+ }()
187
+ return bridge.create_Result_std__shared_ptr_Promise_bool___(__resultCpp)
188
+ } catch (let __error) {
189
+ let __exceptionPtr = __error.toCpp()
190
+ return bridge.create_Result_std__shared_ptr_Promise_bool___(__exceptionPtr)
191
+ }
192
+ }
162
193
  }
@@ -16,6 +16,8 @@ namespace margelo::nitro::myazakyc {
16
16
  registerHybrids(this, [](Prototype& prototype) {
17
17
  prototype.registerHybridMethod("recognizeText", &HybridMyazaTextRecognizerSpec::recognizeText);
18
18
  prototype.registerHybridMethod("recognizeTextInImage", &HybridMyazaTextRecognizerSpec::recognizeTextInImage);
19
+ prototype.registerHybridMethod("isModelReady", &HybridMyazaTextRecognizerSpec::isModelReady);
20
+ prototype.registerHybridMethod("prepareModel", &HybridMyazaTextRecognizerSpec::prepareModel);
19
21
  });
20
22
  }
21
23
 
@@ -57,6 +57,8 @@ namespace margelo::nitro::myazakyc {
57
57
  // Methods
58
58
  virtual TextResult recognizeText(const std::shared_ptr<margelo::nitro::camera::HybridFrameSpec>& frame, double bottomFraction) = 0;
59
59
  virtual std::shared_ptr<Promise<TextResult>> recognizeTextInImage(const std::string& uri, double bottomFraction) = 0;
60
+ virtual bool isModelReady() = 0;
61
+ virtual std::shared_ptr<Promise<bool>> prepareModel() = 0;
60
62
 
61
63
  protected:
62
64
  // Hybrid Setup
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myazahq/kyc-sdk-react-native",
3
- "version": "2.6.0",
3
+ "version": "3.0.0",
4
4
  "description": "Myaza KYC SDK for React Native (Expo) — ID verification, liveness detection, and document capture",
5
5
  "author": "Flitstack Technologies Inc.",
6
6
  "repository": {
@@ -49,6 +49,10 @@
49
49
  "license": "MIT",
50
50
  "peerDependencies": {
51
51
  "expo": ">=56",
52
+ "expo-application": ">=56",
53
+ "expo-device": ">=56",
54
+ "expo-document-picker": ">=56",
55
+ "expo-localization": ">=56",
52
56
  "expo-task-manager": ">=14",
53
57
  "react-native-webview": ">=13",
54
58
  "react": ">=19",
@@ -61,6 +65,18 @@
61
65
  "react-native-worklets": ">=0.8"
62
66
  },
63
67
  "peerDependenciesMeta": {
68
+ "expo-application": {
69
+ "optional": true
70
+ },
71
+ "expo-device": {
72
+ "optional": true
73
+ },
74
+ "expo-document-picker": {
75
+ "optional": true
76
+ },
77
+ "expo-localization": {
78
+ "optional": true
79
+ },
64
80
  "expo-task-manager": {
65
81
  "optional": true
66
82
  },
@@ -69,21 +85,14 @@
69
85
  }
70
86
  },
71
87
  "dependencies": {
72
- "@expo-google-fonts/karla": "^0.4.2",
73
- "@expo-google-fonts/space-grotesk": "^0.4.1",
74
- "@expo/vector-icons": "^14.0.4",
75
88
  "country-flag-icons": "^1.6.17",
76
- "expo-application": "~56.0.3",
77
89
  "libphonenumber-js": "^1.13.8",
78
90
  "expo-crypto": "~56.0.4",
79
91
  "expo-clipboard": "~56.0.0",
80
- "expo-device": "~56.0.4",
81
- "expo-document-picker": "~56.0.4",
82
92
  "expo-font": "~56.0.5",
83
93
  "expo-glass-effect": "~56.0.4",
84
94
  "expo-image-manipulator": "~56.0.17",
85
95
  "expo-image-picker": "~56.0.16",
86
- "expo-localization": "~56.0.6",
87
96
  "expo-location": "~56.0.24",
88
97
  "expo-speech": "~56.0.3",
89
98
  "lucide-react-native": "^1.17.0",
package/src/MyazaKYC.tsx CHANGED
@@ -15,8 +15,8 @@ import type { KYCStep, MyazaKYCConfig, SupportedCountry } from './types/config';
15
15
  import { KycRuntimeProvider, MyazaThemeProvider } from './components/runtime';
16
16
  import { WorkflowGate } from './components/WorkflowGate';
17
17
  import { useWorkflowMount } from './components/useWorkflowMount';
18
+ import { usePrimeModels } from './lib/prime-models';
18
19
  import { safeReportError } from './services/errors';
19
- import { primeFaceModel } from './liveness/visionCameraFaceDetector';
20
20
  import { KycFlow, type BackResult } from './components/KycFlow';
21
21
  import { MyazaButton } from './components/MyazaButton';
22
22
 
@@ -99,16 +99,7 @@ function MyazaKYCTrigger({
99
99
  const settled = state.status !== 'resolving';
100
100
  const open = wantOpen && settled;
101
101
 
102
- // Start fetching the face model the moment the user opens the flow, so the
103
- // download overlaps consent and ID-type selection rather than stalling in
104
- // front of the camera. Mirrors the web SDK's primeFaceMesh() on mount; the
105
- // liveness step still gates on isFaceModelReady(), so this is best-effort.
106
- const primedRef = useRef(false);
107
- useEffect(() => {
108
- if (!wantOpen || primedRef.current) return;
109
- primedRef.current = true;
110
- primeFaceModel();
111
- }, [wantOpen]);
102
+ usePrimeModels(wantOpen, config.apiKey, config.devUrl);
112
103
 
113
104
  // Reported only once the user has actually tried to start. Prefetching must
114
105
  // not fire a consumer's error handler for a flow they never opened.
@@ -229,6 +220,8 @@ export function useMyazaKYC<C extends SupportedCountry = SupportedCountry>(
229
220
  configRef.current = config;
230
221
  const backRef = useRef<(() => BackResult) | null>(null);
231
222
 
223
+ usePrimeModels(wantOpen, config.apiKey, config.devUrl);
224
+
232
225
  // `refresh` is defined further down (it needs `wrappedConfig`), so it is
233
226
  // reached through a ref rather than reordering the component around it.
234
227
  const refreshRef = useRef<() => void>(() => undefined);
@@ -0,0 +1,93 @@
1
+ Copyright 2019 The Karla Project Authors (https://github.com/googlefonts/karla)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ https://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
1
+ Copyright 2020 The Space Grotesk Project Authors (https://github.com/floriankarsten/space-grotesk)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,12 @@
1
+ # Bundled typefaces
2
+
3
+ The seven faces the SDK draws with, and nothing else: Karla 400/500/600/700
4
+ (body) and Space Grotesk 500/600/700 (headings). Both families are Google
5
+ Fonts under the SIL Open Font License 1.1; the licence for each sits beside
6
+ the files (`OFL-Karla.txt`, `OFL-SpaceGrotesk.txt`).
7
+
8
+ They are vendored rather than imported from the `@expo-google-fonts` packages
9
+ because Metro bundles every `require` in a package index whether or not the
10
+ export is used, so those two packages put all 19 of their font files (1.85 MB)
11
+ into every integrator's app for the seven faces the SDK uses. Add a weight here
12
+ only when `config/font-resolve.ts` resolves to it.
@@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
2
  import { useFrameOutput } from 'react-native-vision-camera';
3
3
  import { runOnJS } from 'react-native-worklets';
4
4
 
5
- import { hasTextRecognizer, recognizeAllLines } from '../mrz/textRecognizer';
5
+ import { hasTextRecognizer, primeTextModel, recognizeAllLines } from '../mrz/textRecognizer';
6
6
  import { extractMrz } from '../mrz/extract';
7
7
  import type { MrzScan } from '../mrz/parse';
8
8
  import { DocumentTextGate } from './documentTextGate';
@@ -97,6 +97,13 @@ export function useAutoCapture({
97
97
  // body is the one place that is both.
98
98
  hasTextRecognizer();
99
99
  hasRectDetector();
100
+ // Android fetches the text model through Play Services, so start it here too.
101
+ // The flow primes at open and this is normally a no-op, but the document step
102
+ // can be reached directly in a resumed session. Auto-capture deliberately does
103
+ // NOT gate on readiness: it is an accelerator, the manual shutter is live
104
+ // throughout, so a model that never arrives costs convenience rather than
105
+ // leaving the user stuck.
106
+ primeTextModel();
100
107
 
101
108
  const gate = useMemo(() => new DocumentTextGate(), []);
102
109
  const [guidance, setGuidance] = useState<DocumentGuidance>(INITIAL);