dojah-kyc-sdk-react-expo 0.1.5 → 0.1.7

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.
@@ -51,5 +51,6 @@ repositories {
51
51
 
52
52
  dependencies {
53
53
  // implementation 'com.github.dojah-inc:sdk-kotlin:v0.0.1-dev'
54
- implementation 'com.github.dojah-inc:sdk-kotlin:v0.0.4-dev'
54
+ // implementation 'com.github.dojah-inc:sdk-kotlin:v0.0.4-dev'
55
+ implementation 'com.github.dojah-inc:sdk-kotlin:v0.2.0'
55
56
  }
@@ -53,7 +53,7 @@ class DojahKycSdkReactExpoModule : Module() {
53
53
  widgetId,
54
54
  referenceId,
55
55
  email,
56
- extraData = extraData?.toExtraUserData()?: ExtraUserData(),
56
+ extraData = extraData?.toExtraUserData() ?: ExtraUserData()
57
57
  )
58
58
  Log.d("DojahKycSdk", "data passed -> ${extraData?.toExtraUserData()}")
59
59
  } catch (e: Exception) {
@@ -1,5 +1,5 @@
1
- import { NativeModule } from 'expo';
2
- import { DojahKycSdkReactExpoModuleEvents } from './DojahKycSdkReactExpo.types';
1
+ import { NativeModule } from "expo";
2
+ import { DojahKycSdkReactExpoModuleEvents } from "./DojahKycSdkReactExpo.types";
3
3
  declare class DojahKycSdk extends NativeModule<DojahKycSdkReactExpoModuleEvents> {
4
4
  launch(widgetId: string, referenceId?: string | null, email?: string | null, extraData?: Record<string, any> | null): Promise<string>;
5
5
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DojahKycSdkReactExpoModule.d.ts","sourceRoot":"","sources":["../src/DojahKycSdkReactExpoModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,MAAM,CAAC;AAEzD,OAAO,EAAE,gCAAgC,EAAE,MAAM,8BAA8B,CAAC;AAEhF,OAAO,OAAO,WAAY,SAAQ,YAAY,CAAC,gCAAgC,CAAC;IAC9E,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,EAClD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GACrC,OAAO,CAAC,MAAM,CAAC;CACnB;;AAGD,wBAA+D"}
1
+ {"version":3,"file":"DojahKycSdkReactExpoModule.d.ts","sourceRoot":"","sources":["../src/DojahKycSdkReactExpoModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,MAAM,CAAC;AAEzD,OAAO,EAAE,gCAAgC,EAAE,MAAM,8BAA8B,CAAC;AAEhF,OAAO,OAAO,WAAY,SAAQ,YAAY,CAAC,gCAAgC,CAAC;IAC9E,MAAM,CACJ,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,EAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,EACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GACrC,OAAO,CAAC,MAAM,CAAC;CACnB;;AAGD,wBAA+D"}
@@ -1,4 +1,4 @@
1
- import { requireNativeModule } from 'expo';
1
+ import { requireNativeModule } from "expo";
2
2
  // This call loads the native module object from the JSI.
3
- export default requireNativeModule('DojahKycSdk');
3
+ export default requireNativeModule("DojahKycSdk");
4
4
  //# sourceMappingURL=DojahKycSdkReactExpoModule.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DojahKycSdkReactExpoModule.js","sourceRoot":"","sources":["../src/DojahKycSdkReactExpoModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAWzD,yDAAyD;AACzD,eAAe,mBAAmB,CAAc,aAAa,CAAC,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from 'expo';\n\nimport { DojahKycSdkReactExpoModuleEvents } from './DojahKycSdkReactExpo.types';\n\ndeclare class DojahKycSdk extends NativeModule<DojahKycSdkReactExpoModuleEvents> {\n launch(widgetId: string, referenceId?: string | null,\n email?: string | null,\n extraData?: Record<string, any> | null\n ): Promise<string>;\n}\n\n// This call loads the native module object from the JSI.\nexport default requireNativeModule<DojahKycSdk>('DojahKycSdk');\n"]}
1
+ {"version":3,"file":"DojahKycSdkReactExpoModule.js","sourceRoot":"","sources":["../src/DojahKycSdkReactExpoModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAazD,yDAAyD;AACzD,eAAe,mBAAmB,CAAc,aAAa,CAAC,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from \"expo\";\n\nimport { DojahKycSdkReactExpoModuleEvents } from \"./DojahKycSdkReactExpo.types\";\n\ndeclare class DojahKycSdk extends NativeModule<DojahKycSdkReactExpoModuleEvents> {\n launch(\n widgetId: string,\n referenceId?: string | null,\n email?: string | null,\n extraData?: Record<string, any> | null\n ): Promise<string>;\n}\n\n// This call loads the native module object from the JSI.\nexport default requireNativeModule<DojahKycSdk>(\"DojahKycSdk\");\n"]}
@@ -1,49 +1,141 @@
1
1
  import ExpoModulesCore
2
2
  import DojahWidget
3
+ import UIKit
4
+
5
+ // Custom NavigationController that prevents duplicate presentations
6
+ class SafeDojahNavigationController: UINavigationController {
7
+ private var isPresenting = false
8
+
9
+ override func present(_ viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Void)? = nil) {
10
+ // Check if we're already presenting something
11
+ if isPresenting {
12
+ print("⚠️ Already presenting, preventing duplicate: \(String(describing: type(of: viewControllerToPresent)))")
13
+ completion?()
14
+ return
15
+ }
16
+
17
+ // Check if this view controller is already in the navigation stack
18
+ if viewControllers.contains(where: {
19
+ type(of: $0) == type(of: viewControllerToPresent)
20
+ }) {
21
+ print("⚠️ ViewController already in navigation stack: \(String(describing: type(of: viewControllerToPresent)))")
22
+ completion?()
23
+ return
24
+ }
25
+
26
+ // Check if we're already presenting something
27
+ if presentedViewController != nil {
28
+ print("⚠️ NavigationController already has a presentedViewController")
29
+ completion?()
30
+ return
31
+ }
32
+
33
+ // Mark as presenting
34
+ isPresenting = true
35
+
36
+ // Call super to actually present
37
+ super.present(viewControllerToPresent, animated: animated) { [weak self] in
38
+ self?.isPresenting = false
39
+ completion?()
40
+ }
41
+ }
42
+
43
+ override func dismiss(animated: Bool, completion: (() -> Void)? = nil) {
44
+ isPresenting = false
45
+ super.dismiss(animated: animated, completion: completion)
46
+ }
47
+ }
3
48
 
4
49
  class DojahNavigationControllerDelegate: NSObject, UINavigationControllerDelegate {
5
50
  var onDidShow: (UIViewController) -> Void = { _ in }
51
+
6
52
  func navigationController(_ navigationController: UINavigationController,
7
53
  didShow viewController: UIViewController,
8
54
  animated: Bool) {
9
- print("Did show: \(viewController)")
55
+ print("📱 Did show: \(viewController)")
10
56
  onDidShow(viewController)
11
57
  }
12
-
13
- func navigationController(_ navigationController: UINavigationController,
14
- willShow viewController: UIViewController,
15
- animated: Bool) {
16
- print("Will show: \(viewController)")
17
- }
18
58
 
19
59
  func setOnDidShow(_ onDidShow: @escaping (UIViewController) -> Void) {
20
60
  self.onDidShow = onDidShow
21
61
  }
22
62
  }
23
63
 
64
+ class DojahPresentationControllerDelegate: NSObject, UIAdaptivePresentationControllerDelegate {
65
+ var onDidDismiss: () -> Void = { }
66
+
67
+ func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
68
+ print("🛑 Modal was dismissed manually")
69
+ onDidDismiss()
70
+ }
71
+
72
+ func setOnDidDismiss(_ onDidDismiss: @escaping () -> Void) {
73
+ self.onDidDismiss = onDidDismiss
74
+ }
75
+ }
76
+
24
77
  public class DojahKycSdkReactExpoModule: Module {
25
78
 
26
- var mPromise: Promise?
79
+ var mPromise: Promise? = nil
27
80
  let navDelegate = DojahNavigationControllerDelegate()
28
- var navCtrl: UINavigationController?
29
- var prevController: UIViewController?
30
-
81
+ let presentationDelegate = DojahPresentationControllerDelegate()
82
+
83
+ // Track Dojah state
84
+ private var isDojahActive = false
85
+ private var dojahNavController: SafeDojahNavigationController?
86
+ private var prevController: UIViewController? // Track previous controller for DJDisclaimer handling
87
+ private var hasSeenSDKInit = false // Track if we've seen SDKInitViewController before
88
+
31
89
  required public init(appContext: AppContext) {
32
90
  super.init(appContext: appContext)
33
- navDelegate.setOnDidShow { vc in
34
- print("onDidShow: \(vc)")
35
- //return result from DojahWidget once verification
36
- //is done,failed or cancel
37
- if !String(describing: vc).contains("DojahWidget") {
38
- let vStatus = DojahWidgetSDK.getVerificationResultStatus()
39
- let status = vStatus.isEmpty ? "closed" : vStatus
40
- self.mPromise?.resolve(status)
41
- self.prevController = nil
42
- } else if String(describing: vc).contains("DojahWidget.DJDisclaimer")
43
- && self.prevController != nil {
44
- self.navCtrl?.popToRootViewController(animated: false)
45
- } else if !String(describing: vc).contains("DojahWidget.SDKInitViewController") {
46
- self.prevController = vc
91
+
92
+ // Set up presentation delegate callback
93
+ presentationDelegate.setOnDidDismiss { [weak self] in
94
+ guard let self = self else { return }
95
+ print("🛑 Modal was dismissed manually")
96
+ self.resolveSdkResult()
97
+ self.dojahNavController = nil
98
+ }
99
+ }
100
+
101
+ private func resolveSdkResult() {
102
+ let vStatus = DojahWidgetSDK.getVerificationResultStatus()
103
+ let status = vStatus.isEmpty ? "closed" : vStatus
104
+
105
+ print("📊 Resolving SDK result: \(status)")
106
+
107
+ // Resolve promise first
108
+ self.mPromise?.resolve(status)
109
+ self.mPromise = nil
110
+
111
+ // Clear state
112
+ self.prevController = nil
113
+
114
+ // Dismiss the navigation controller
115
+ self.dismissDojahController()
116
+
117
+ // Reset flag
118
+ self.isDojahActive = false
119
+ }
120
+
121
+ private func getTopViewController() -> UIViewController? {
122
+ guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
123
+ let rootViewController = windowScene.windows.first?.rootViewController else {
124
+ return nil
125
+ }
126
+
127
+ var topViewController = rootViewController
128
+ while let presentedViewController = topViewController.presentedViewController {
129
+ topViewController = presentedViewController
130
+ }
131
+
132
+ return topViewController
133
+ }
134
+
135
+ private func dismissDojahController() {
136
+ DispatchQueue.main.async { [weak self] in
137
+ self?.dojahNavController?.dismiss(animated: true) {
138
+ self?.dojahNavController = nil
47
139
  }
48
140
  }
49
141
  }
@@ -55,62 +147,118 @@ public class DojahKycSdkReactExpoModule: Module {
55
147
  AsyncFunction("launch") { (widgetId: String, referenceId: String?, email: String?, extraData: ExtraDataRecord?, promise: Promise) in
56
148
  self.mPromise = promise
57
149
 
58
- // Get the navigation controller when needed, not during initialization
59
- if self.navCtrl == nil {
60
- DispatchQueue.main.async {
61
- if let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) {
62
- if let rootNav = window.rootViewController as? UINavigationController {
63
- self.navCtrl = rootNav
64
- } else if let rootVC = window.rootViewController {
65
- // If rootViewController isn't a nav controller, create one
66
- let navController = UINavigationController(rootViewController: rootVC)
67
- window.rootViewController = navController
68
- self.navCtrl = navController
69
- }
70
- }
150
+ guard let rootVC = self.getTopViewController() else {
151
+ promise.reject("002", "Failed to get top view controller")
152
+ return
153
+ }
154
+
155
+ DispatchQueue.main.async { [weak self] in
156
+ guard let self = self else { return }
157
+
158
+ // Reset state for new launch
159
+ self.prevController = nil
160
+ self.isDojahActive = false
161
+ self.hasSeenSDKInit = false
162
+
163
+ // Create safe navigation controller for Dojah (prevents duplicate presentations)
164
+ let dojahNavController = SafeDojahNavigationController()
165
+ dojahNavController.modalPresentationStyle = .fullScreen
166
+ self.dojahNavController = dojahNavController
167
+
168
+ // Set delegate BEFORE presenting (important!)
169
+ dojahNavController.delegate = self.navDelegate
170
+
171
+ // Detect modal dismissal (for cancel)
172
+ dojahNavController.presentationController?.delegate = self.presentationDelegate
173
+
174
+ // Track Dojah flow - simplified like original but with Flutter closing logic
175
+ self.navDelegate.setOnDidShow { [weak self] vc in
176
+ guard let self = self else { return }
177
+
178
+ // Use String(describing: vc) like the original code
179
+ let vcName = String(describing: vc)
180
+ print("🔄 onDidShow: \(vcName)")
71
181
 
72
- guard let navController = self.navCtrl else {
73
- self.mPromise?.reject("002", "failed to initialize, can't find navController")
182
+ // Match original + Flutter logic:
183
+ // 1. If not DojahWidget, resolve (but only if we were in Dojah)
184
+ if !vcName.contains("DojahWidget") {
185
+ if self.isDojahActive {
186
+ print("🚪 Not DojahWidget - resolving")
187
+ self.resolveSdkResult()
188
+ }
74
189
  return
75
190
  }
76
191
 
77
- navController.delegate = self.navDelegate
192
+ // Mark as active when we see Dojah screens
193
+ self.isDojahActive = true
78
194
 
79
- do {
80
- DojahWidgetSDK.initialize(
81
- widgetID: widgetId,
82
- referenceID: referenceId,
83
- emailAddress: email,
84
- extraUserData: extraData?.toExtraUserData(),
85
- navController: navController
86
- )
87
- } catch {
88
- self.mPromise?.reject("001", "failed to initialize")
89
- }
90
- }
91
- } else {
92
- // If navCtrl already exists
93
- DispatchQueue.main.async {
94
- guard let navController = self.navCtrl else {
95
- self.mPromise?.reject("002", "failed to initialize, can't find navController")
195
+ // 2. If DJDisclaimer with prevController, pop to root (like original)
196
+ if vcName.contains("DojahWidget.DJDisclaimer") && self.prevController != nil {
197
+ print("📱 DJDisclaimer with prevController - popping to root")
198
+ self.dojahNavController?.popToRootViewController(animated: false)
96
199
  return
97
200
  }
98
201
 
99
- do {
202
+ // 3. If not SDKInitViewController, track as prevController (like original)
203
+ if !vcName.contains("DojahWidget.SDKInitViewController") {
204
+ self.prevController = vc
205
+ print("✅ Tracking prevController: \(vcName)")
206
+ } else {
207
+ // 4. SDKInitViewController - resolve (matches Flutter's "else" case)
208
+ // Resolve if we've seen it before OR if we've progressed
209
+ if self.hasSeenSDKInit || self.prevController != nil {
210
+ print("📱 SDKInitViewController - resolving")
211
+ self.resolveSdkResult()
212
+ } else {
213
+ // First time seeing SDKInitViewController - allow to continue
214
+ print("📱 SDKInitViewController on initial launch - allowing to continue")
215
+ self.hasSeenSDKInit = true
216
+ }
217
+ }
218
+ }
219
+
220
+ // Present modally and wait for completion to ensure view hierarchy is ready
221
+ rootVC.present(dojahNavController, animated: true) {
222
+ // Add a small delay to ensure view hierarchy is fully laid out
223
+ // This helps with camera session initialization timing
224
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
225
+ // Initialize SDK after presentation completes and view is laid out
226
+ // This ensures the view hierarchy is fully set up before camera access
100
227
  DojahWidgetSDK.initialize(
101
228
  widgetID: widgetId,
102
229
  referenceID: referenceId,
103
230
  emailAddress: email,
104
231
  extraUserData: extraData?.toExtraUserData(),
105
- navController: navController
232
+ source: "ios_react_native_expo",
233
+ navController: dojahNavController
106
234
  )
107
- } catch {
108
- self.mPromise?.reject("001", "failed to initialize")
235
+ print("🎯 Dojah SDK initialized")
109
236
  }
110
237
  }
111
238
  }
112
239
  }
113
240
 
241
+ AsyncFunction("close") { [weak self] (promise: Promise) in
242
+ print("🛑 Manual close requested")
243
+
244
+ guard let self = self else {
245
+ promise.resolve("no_instance")
246
+ return
247
+ }
248
+
249
+ let vStatus = DojahWidgetSDK.getVerificationResultStatus()
250
+ let status = vStatus.isEmpty ? "cancelled" : vStatus
251
+
252
+ self.mPromise?.resolve(status)
253
+ self.mPromise = nil
254
+ self.prevController = nil
255
+
256
+ self.dismissDojahController()
257
+ self.isDojahActive = false
258
+
259
+ promise.resolve("closed")
260
+ }
261
+
114
262
  View(DojahKycSdkReactExpoView.self) {
115
263
  Prop("url") { (view: DojahKycSdkReactExpoView, url: URL) in
116
264
  if view.webView.url != url {
@@ -122,6 +270,9 @@ public class DojahKycSdkReactExpoModule: Module {
122
270
  }
123
271
  }
124
272
 
273
+
274
+ // ============= KEEP ALL THESE STRUCTS =============
275
+
125
276
  struct ExtraDataRecord : Record {
126
277
  @Field
127
278
  var userData: UserRecord? = nil
@@ -155,10 +306,8 @@ struct ExtraDataRecord : Record {
155
306
  metadata: metadata
156
307
  )
157
308
  }
158
-
159
309
  }
160
310
 
161
-
162
311
  struct UserRecord : Record {
163
312
  @Field
164
313
  var firstName: String? = nil
@@ -261,5 +410,4 @@ struct BusinessDataRecord : Record {
261
410
  cac: cac
262
411
  )
263
412
  }
264
- }
265
-
413
+ }
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Workspace
3
+ version = "1.0">
4
+ <FileRef
5
+ location = "self:">
6
+ </FileRef>
7
+ </Workspace>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>IDEDidComputeMac32BitWarning</key>
6
+ <true/>
7
+ </dict>
8
+ </plist>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dojah-kyc-sdk-react-expo",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Dojah Kyc",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -1,13 +1,15 @@
1
- import { NativeModule, requireNativeModule } from 'expo';
1
+ import { NativeModule, requireNativeModule } from "expo";
2
2
 
3
- import { DojahKycSdkReactExpoModuleEvents } from './DojahKycSdkReactExpo.types';
3
+ import { DojahKycSdkReactExpoModuleEvents } from "./DojahKycSdkReactExpo.types";
4
4
 
5
5
  declare class DojahKycSdk extends NativeModule<DojahKycSdkReactExpoModuleEvents> {
6
- launch(widgetId: string, referenceId?: string | null,
6
+ launch(
7
+ widgetId: string,
8
+ referenceId?: string | null,
7
9
  email?: string | null,
8
10
  extraData?: Record<string, any> | null
9
11
  ): Promise<string>;
10
12
  }
11
13
 
12
14
  // This call loads the native module object from the JSI.
13
- export default requireNativeModule<DojahKycSdk>('DojahKycSdk');
15
+ export default requireNativeModule<DojahKycSdk>("DojahKycSdk");