dojah-kyc-sdk-react-expo 0.1.6 → 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,47 +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
- if !String(describing: vc).contains("DojahWidget") {
36
- let vStatus = DojahWidgetSDK.getVerificationResultStatus()
37
- let status = vStatus.isEmpty ? "closed" : vStatus
38
- self.mPromise?.resolve(status)
39
- self.prevController = nil
40
- } else if String(describing: vc).contains("DojahWidget.DJDisclaimer")
41
- && self.prevController != nil {
42
- self.navCtrl?.popToRootViewController(animated: false)
43
- } else if !String(describing: vc).contains("DojahWidget.SDKInitViewController") {
44
- 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
45
139
  }
46
140
  }
47
141
  }
@@ -53,42 +147,118 @@ public class DojahKycSdkReactExpoModule: Module {
53
147
  AsyncFunction("launch") { (widgetId: String, referenceId: String?, email: String?, extraData: ExtraDataRecord?, promise: Promise) in
54
148
  self.mPromise = promise
55
149
 
56
- DispatchQueue.main.async {
57
- // Get the current key window
58
- guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else {
59
- self.mPromise?.reject("002", "No key window found")
60
- return
61
- }
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 }
62
157
 
63
- // If we already have a navigation controller, use it
64
- if let existingNav = self.navCtrl {
65
- self.initializeDojahSDK(with: existingNav, widgetId: widgetId, referenceId: referenceId, email: email, extraData: extraData)
66
- return
67
- }
158
+ // Reset state for new launch
159
+ self.prevController = nil
160
+ self.isDojahActive = false
161
+ self.hasSeenSDKInit = false
68
162
 
69
- // If root is already a navigation controller
70
- if let rootNav = window.rootViewController as? UINavigationController {
71
- self.navCtrl = rootNav
72
- self.initializeDojahSDK(with: rootNav, widgetId: widgetId, referenceId: referenceId, email: email, extraData: extraData)
73
- return
74
- }
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
75
173
 
76
- // If root is not a navigation controller, create a new one
77
- if let rootVC = window.rootViewController {
78
- // Create a new navigation controller with the root VC
79
- let navController = UINavigationController()
80
- navController.viewControllers = [rootVC]
81
- window.rootViewController = navController
82
- self.navCtrl = navController
83
- self.initializeDojahSDK(with: navController, widgetId: widgetId, referenceId: referenceId, email: email, extraData: extraData)
84
- return
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)")
181
+
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
+ }
189
+ return
190
+ }
191
+
192
+ // Mark as active when we see Dojah screens
193
+ self.isDojahActive = true
194
+
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)
199
+ return
200
+ }
201
+
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
+ }
85
218
  }
86
219
 
87
- // If we still don't have a navigation controller
88
- self.mPromise?.reject("002", "Failed to setup navigation controller")
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
227
+ DojahWidgetSDK.initialize(
228
+ widgetID: widgetId,
229
+ referenceID: referenceId,
230
+ emailAddress: email,
231
+ extraUserData: extraData?.toExtraUserData(),
232
+ source: "ios_react_native_expo",
233
+ navController: dojahNavController
234
+ )
235
+ print("🎯 Dojah SDK initialized")
236
+ }
237
+ }
89
238
  }
90
239
  }
91
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
+
92
262
  View(DojahKycSdkReactExpoView.self) {
93
263
  Prop("url") { (view: DojahKycSdkReactExpoView, url: URL) in
94
264
  if view.webView.url != url {
@@ -98,28 +268,11 @@ public class DojahKycSdkReactExpoModule: Module {
98
268
  Events("onLoad")
99
269
  }
100
270
  }
101
-
102
- private func initializeDojahSDK(with navController: UINavigationController,
103
- widgetId: String,
104
- referenceId: String?,
105
- email: String?,
106
- extraData: ExtraDataRecord?) {
107
- navController.delegate = self.navDelegate
108
- do {
109
- DojahWidgetSDK.initialize(
110
- widgetID: widgetId,
111
- referenceID: referenceId,
112
- emailAddress: email,
113
- extraUserData: extraData?.toExtraUserData(),
114
- navController: navController
115
- )
116
- } catch {
117
- self.mPromise?.reject("001", "failed to initialize")
118
- }
119
- }
120
271
  }
121
272
 
122
273
 
274
+ // ============= KEEP ALL THESE STRUCTS =============
275
+
123
276
  struct ExtraDataRecord : Record {
124
277
  @Field
125
278
  var userData: UserRecord? = nil
@@ -153,10 +306,8 @@ struct ExtraDataRecord : Record {
153
306
  metadata: metadata
154
307
  )
155
308
  }
156
-
157
309
  }
158
310
 
159
-
160
311
  struct UserRecord : Record {
161
312
  @Field
162
313
  var firstName: String? = nil
@@ -259,5 +410,4 @@ struct BusinessDataRecord : Record {
259
410
  cac: cac
260
411
  )
261
412
  }
262
- }
263
-
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.6",
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");