@infilectorg/infiviz-shots-react-sdk 1.2.1 → 1.2.3

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 (49) hide show
  1. package/ios/InfivizShotSDK.xcframework/Info.plist +5 -5
  2. package/ios/InfivizShotSDK.xcframework/ios-arm64/InfivizShotSDK.framework/Assets.car +0 -0
  3. package/ios/InfivizShotSDK.xcframework/ios-arm64/InfivizShotSDK.framework/InfivizShotSDK +0 -0
  4. package/ios/InfivizShotSDK.xcframework/ios-arm64/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/arm64-apple-ios.abi.json +60 -60
  5. package/ios/InfivizShotSDK.xcframework/ios-arm64/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/arm64-apple-ios.swiftmodule +0 -0
  6. package/ios/InfivizShotSDK.xcframework/ios-arm64/InfivizShotSDK.framework/shotsSDK.storyboardc/xUL-ol-gRQ-view-6A8-mO-Rhi.nib +0 -0
  7. package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/InfivizShotSDK +0 -0
  8. package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +60 -60
  9. package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/arm64-apple-ios-simulator.swiftmodule +0 -0
  10. package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/x86_64-apple-ios-simulator.abi.json +60 -60
  11. package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/x86_64-apple-ios-simulator.swiftmodule +0 -0
  12. package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/shotsSDK.storyboardc/xUL-ol-gRQ-view-6A8-mO-Rhi.nib +0 -0
  13. package/ios/InfivizShotsReactSdk.swift +593 -570
  14. package/lib/module/NativeInfivizShotsReactSdk.js +0 -2
  15. package/lib/module/NativeInfivizShotsReactSdk.js.map +1 -1
  16. package/lib/module/index.js +2 -4
  17. package/lib/module/index.js.map +1 -1
  18. package/lib/module/types/Environment.js +0 -2
  19. package/lib/module/types/Environment.js.map +1 -1
  20. package/lib/module/types/ImageMetaData.js +0 -2
  21. package/lib/module/types/ImageMetaData.js.map +1 -1
  22. package/lib/module/types/InfiSession.js +0 -2
  23. package/lib/module/types/InfiSession.js.map +1 -1
  24. package/lib/module/types/LabelScore.js +1 -1
  25. package/lib/module/types/LabelScore.js.map +1 -1
  26. package/lib/module/types/SessionStatus.js +1 -1
  27. package/lib/module/types/SessionStatus.js.map +1 -1
  28. package/lib/module/types/SessionSyncStateEnum.js +0 -2
  29. package/lib/module/types/SessionSyncStateEnum.js.map +1 -1
  30. package/package.json +1 -1
  31. package/react-native-infiviz-shots.podspec +1 -1
  32. package/lib/module/package.json +0 -1
  33. package/lib/typescript/package.json +0 -1
  34. package/lib/typescript/src/NativeInfivizShotsReactSdk.d.ts +0 -23
  35. package/lib/typescript/src/NativeInfivizShotsReactSdk.d.ts.map +0 -1
  36. package/lib/typescript/src/index.d.ts +0 -24
  37. package/lib/typescript/src/index.d.ts.map +0 -1
  38. package/lib/typescript/src/types/Environment.d.ts +0 -5
  39. package/lib/typescript/src/types/Environment.d.ts.map +0 -1
  40. package/lib/typescript/src/types/ImageMetaData.d.ts +0 -13
  41. package/lib/typescript/src/types/ImageMetaData.d.ts.map +0 -1
  42. package/lib/typescript/src/types/InfiSession.d.ts +0 -18
  43. package/lib/typescript/src/types/InfiSession.d.ts.map +0 -1
  44. package/lib/typescript/src/types/LabelScore.d.ts +0 -5
  45. package/lib/typescript/src/types/LabelScore.d.ts.map +0 -1
  46. package/lib/typescript/src/types/SessionStatus.d.ts +0 -5
  47. package/lib/typescript/src/types/SessionStatus.d.ts.map +0 -1
  48. package/lib/typescript/src/types/SessionSyncStateEnum.d.ts +0 -8
  49. package/lib/typescript/src/types/SessionSyncStateEnum.d.ts.map +0 -1
@@ -12,313 +12,336 @@ import React
12
12
 
13
13
  @objc(InfivizShotsReactSdk)
14
14
  class InfivizShotsReactSdk: RCTEventEmitter {
15
- @objc
16
- override static func moduleName() -> String! {
17
- return "InfivizShotsReactSdk"
18
- }
19
-
20
- @objc
21
- override static func requiresMainQueueSetup() -> Bool {
22
- return false
23
- }
24
-
25
- // MARK: – RCTEventEmitter Boilerplate
26
-
27
- private var hasListeners = false
28
-
29
- // 3. List of events that JS can subscribe to:
30
- override func supportedEvents() -> [String]! {
31
- return [
32
- "SyncEvent",
33
- "ActionsGeneratedEvent",
34
- "SessionRealTimeResultEvent"]
35
- }
36
-
37
- // 4. Only send events if JS has at least one listener:
38
- override func startObserving() {
39
- hasListeners = true
40
-
15
+ @objc
16
+ override static func moduleName() -> String! {
17
+ return "InfivizShotsReactSdk"
18
+ }
19
+
20
+ @objc
21
+ override static func requiresMainQueueSetup() -> Bool {
22
+ return false
23
+ }
24
+
25
+ // MARK: – RCTEventEmitter Boilerplate
26
+
27
+ private var hasListeners = false
28
+
29
+ // 3. List of events that JS can subscribe to:
30
+ override func supportedEvents() -> [String]! {
31
+ return [
32
+ "SyncEvent",
33
+ "ActionsGeneratedEvent",
34
+ "SessionRealTimeResultEvent"]
35
+ }
36
+
37
+ // 4. Only send events if JS has at least one listener:
38
+ override func startObserving() {
39
+ hasListeners = true
40
+
41
41
  NotificationCenter.default.addObserver(self,
42
- selector: #selector(handleActionsGeneratedEvent(_:)),
43
- name: NSNotification.Name("ActionsGeneratedEvent"),
44
- object: nil)
45
- NotificationCenter.default.addObserver(self,
46
- selector: #selector(handleSessionRealTimeResultEvent(_:)),
47
- name: NSNotification.Name("SessionRealTimeResultEvent"),
48
- object: nil)
49
-
50
- }
51
-
52
- override func stopObserving() {
53
- hasListeners = false
54
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name("ActionsGeneratedEvent"), object: nil)
55
- NotificationCenter.default.removeObserver(self, name: NSNotification.Name("SessionRealTimeResultEvent"), object: nil)
56
- }
57
-
58
- // 5. If you have no constants to export, just return empty:
59
- override func constantsToExport() -> [AnyHashable: Any]! {
60
- return [:]
61
- }
62
-
63
-
64
- var activity: InfivizShotsActivity?
65
-
66
- // MARK: –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
67
- // MARK: – Helper Methods (not directly exposed to JS)
68
-
69
-
70
- // MARK: - Universal Session ID
71
- @objc
72
- func fetchUniversalSessionId(_ tempID: NSString, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
73
- InfivizShotsSDK.shared.fetchUniversalSessionId(temporarySessionID: tempID as String, completion: { sessionID, error in
74
- if let id = sessionID {
75
- resolve(id)
76
- } else {
77
- reject("FETCH_SESSION_ID_ERROR", "Session not found", nil)
78
- }
79
- })
80
- }
81
-
82
- @objc
83
- func syncSession(_ sessionId: NSString) {
84
- // Kick off the upload. No resolver/rejecter—just emit events once it’s done.
85
- InfivizShotsSDK.shared.uploadSession(temporarySessionID: sessionId as String) { result in
86
- switch result {
87
- case .success(let response):
88
- if self.hasListeners {
89
- let payload: [String: Any] = [
90
- "status": "200",
91
- "universalSessionID": response,
92
- "temporarySessionID": sessionId as String
93
- ]
94
- self.sendEvent(withName: "SyncEvent", body: payload)
95
- }
96
- case .failure(let error):
97
- if self.hasListeners {
98
- let payload: [String: Any] = [
99
- "status": "400",
100
- "message": error.localizedDescription,
101
- "temporarySessionID": sessionId as String
102
- ]
103
- self.sendEvent(withName: "SyncEvent", body: payload)
104
- }
105
- }
106
- }
107
- }
108
-
109
- // MARK: - Sync Multiple Sessions
110
- /// Bridge to InfivizShotsSDK.shared.syncSessions(temporarySessionIDs:completionHandler:)
111
-
112
- @objc
113
- func uploadSession(temporarySessionIDs: NSArray) {
42
+ selector: #selector(handleActionsGeneratedEvent(_:)),
43
+ name: NSNotification.Name("ActionsGeneratedEvent"),
44
+ object: nil)
45
+ NotificationCenter.default.addObserver(self,
46
+ selector: #selector(handleSessionRealTimeResultEvent(_:)),
47
+ name: NSNotification.Name("SessionRealTimeResultEvent"),
48
+ object: nil)
49
+
50
+ }
51
+
52
+ override func stopObserving() {
53
+ hasListeners = false
54
+ NotificationCenter.default.removeObserver(self, name: NSNotification.Name("ActionsGeneratedEvent"), object: nil)
55
+ NotificationCenter.default.removeObserver(self, name: NSNotification.Name("SessionRealTimeResultEvent"), object: nil)
56
+ }
57
+
58
+ // 5. If you have no constants to export, just return empty:
59
+ override func constantsToExport() -> [AnyHashable: Any]! {
60
+ return [:]
61
+ }
62
+
63
+
64
+ var activity: InfivizShotsActivity?
65
+
66
+ // MARK: –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
67
+ // MARK: – Helper Methods (not directly exposed to JS)
68
+
69
+
70
+ // MARK: - Universal Session ID
71
+ @objc
72
+ func fetchUniversalSessionId(_ tempID: NSString, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
73
+ InfivizShotsSDK.shared.fetchUniversalSessionId(temporarySessionID: tempID as String, completion: { sessionID, error in
74
+ if let id = sessionID {
75
+ resolve(id)
76
+ } else {
77
+ reject("FETCH_SESSION_ID_ERROR", "Session not found", nil)
78
+ }
79
+ })
80
+ }
81
+
82
+ @objc
83
+ func syncSession(_ sessionId: NSString) {
84
+ // Kick off the upload. No resolver/rejecter—just emit events once it’s done.
85
+ InfivizShotsSDK.shared.uploadSession(temporarySessionID: sessionId as String) { result in
86
+ switch result {
87
+ case .success(let response):
88
+ if self.hasListeners {
89
+ let payload: [String: Any] = [
90
+ "status": "200",
91
+ "universalSessionID": response,
92
+ "temporarySessionID": sessionId as String
93
+ ]
94
+ self.sendEvent(withName: "SyncEvent", body: payload)
95
+ }
96
+ case .failure(let error):
97
+ if self.hasListeners {
98
+ let payload: [String: Any] = [
99
+ "status": "400",
100
+ "message": error.localizedDescription,
101
+ "temporarySessionID": sessionId as String
102
+ ]
103
+ self.sendEvent(withName: "SyncEvent", body: payload)
104
+ }
105
+ }
106
+ }
107
+ }
108
+
109
+ // MARK: - Sync Multiple Sessions
110
+ /// Bridge to InfivizShotsSDK.shared.syncSessions(temporarySessionIDs:completionHandler:)
111
+
112
+ @objc
113
+ func uploadSession(temporarySessionIDs: NSArray) {
114
114
  var ids: [String] = []
115
115
  if let arr = temporarySessionIDs as? [String] {
116
- ids = arr
116
+ ids = arr
117
117
  } else if let arr = temporarySessionIDs as? [NSString] {
118
- ids = arr.map { $0 as String }
118
+ ids = arr.map { $0 as String }
119
119
  }
120
-
120
+
121
121
  guard !ids.isEmpty else { return }
122
-
122
+
123
123
  InfivizShotsSDK.shared.syncSessions(temporarySessionIDs: ids) { sessionId, result in
124
- switch result {
125
- case .success(let message):
126
- if self.hasListeners {
127
- let payload: [String: Any] = [
128
- "status": "200",
129
- "universalSessionID": message,
130
- "temporarySessionID": sessionId
131
- ]
132
- self.sendEvent(withName: "SyncEvent", body: payload)
133
- }
134
- case .failure(let error):
135
- if self.hasListeners {
136
- let payload: [String: Any] = [
137
- "status": "400",
138
- "universalSessionID": error,
139
- "temporarySessionID": sessionId
140
- ]
141
- self.sendEvent(withName: "SyncEvent", body: payload)
124
+ switch result {
125
+ case .success(let message):
126
+ if self.hasListeners {
127
+ let payload: [String: Any] = [
128
+ "status": "200",
129
+ "universalSessionID": message,
130
+ "temporarySessionID": sessionId
131
+ ]
132
+ self.sendEvent(withName: "SyncEvent", body: payload)
133
+ }
134
+ case .failure(let error):
135
+ if self.hasListeners {
136
+ let payload: [String: Any] = [
137
+ "status": "400",
138
+ "universalSessionID": error,
139
+ "temporarySessionID": sessionId
140
+ ]
141
+ self.sendEvent(withName: "SyncEvent", body: payload)
142
+ }
142
143
  }
143
- }
144
144
  }
145
- }
146
-
147
- // MARK: - Get Session Result
148
-
145
+ }
146
+
147
+ // MARK: - Get Session Result
148
+
149
149
  @objc
150
150
  func getSessionStatus(
151
- _ temporarySessionID: NSString,
152
- resolver resolve: @escaping RCTPromiseResolveBlock,
153
- rejecter reject: @escaping RCTPromiseRejectBlock
151
+ _ temporarySessionID: NSString,
152
+ resolver resolve: @escaping RCTPromiseResolveBlock,
153
+ rejecter reject: @escaping RCTPromiseRejectBlock
154
154
  ) {
155
- InfivizShotsSDK.shared.checkState(sessionID: temporarySessionID as String) { result in
156
- switch result {
157
- case .success(let response):
158
- let json = ["sessionId": temporarySessionID,
159
- "status": response]
160
-
161
- if let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []) {
162
- let jsonString = String(data: jsonData, encoding: .utf8)
163
- resolve(jsonString)
155
+ InfivizShotsSDK.shared.checkState(sessionID: temporarySessionID as String) { result in
156
+ switch result {
157
+ case .success(let response):
158
+ let json = ["sessionId": temporarySessionID,
159
+ "status": response]
160
+
161
+ if let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []) {
162
+ let jsonString = String(data: jsonData, encoding: .utf8)
163
+ resolve(jsonString)
164
+ }
165
+
166
+ case .failure(let error):
167
+ reject(
168
+ "RESULT_FAILED",
169
+ "Failed to get result for \(temporarySessionID): \(error.localizedDescription)",
170
+ nil
171
+ )
164
172
  }
165
-
166
- case .failure(let error):
167
- reject(
168
- "RESULT_FAILED",
169
- "Failed to get result for \(temporarySessionID): \(error.localizedDescription)",
170
- nil
171
- )
172
173
  }
173
- }
174
+ }
175
+
176
+ // MARK: - Sync All Data
177
+ @objc
178
+ func syncAllData(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
179
+ InfivizShotsSDK.shared.syncAllData { result in
180
+ switch result {
181
+ case .success(let message):
182
+ resolve(message)
183
+ case .failure(let error):
184
+ reject("SYNC_FAILED", "Sync failed: \(error)", nil)
185
+ }
186
+ }
187
+ }
188
+
189
+ // MARK: - Fetch Session Details
190
+ @objc
191
+ func fetchSessionDetails(_ temporarySessionID: NSString, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
192
+ InfivizShotsSDK.shared.fetchSessionDetails(temporarySessionID: temporarySessionID as String) { result in
193
+ switch result {
194
+ case .success(let value):
195
+ // Convert any value to a clean dictionary that handles Optionals properly
196
+ let cleanDict = self.convertToCleanDictionary(value)
197
+ // Return the dictionary directly instead of JSON string
198
+ resolve(cleanDict)
199
+ case .failure(let error):
200
+ reject("RESULT_FAILED", "Failed to get result: \(error)", nil)
201
+ }
202
+ }
203
+ }
204
+
205
+ // Helper method to convert any value to a clean dictionary that handles Optionals
206
+ // MARK: - Convert Any Value to Clean Dictionary
207
+ private func convertToCleanDictionary(_ value: Any) -> [String: Any] {
208
+ if let dict = value as? [String: Any] {
209
+ return cleanDictionary(dict)
210
+ } else if let dict = value as? [AnyHashable: Any] {
211
+ var result: [String: Any] = [:]
212
+ for (k, v) in dict {
213
+ result[String(describing: k)] = unwrapOptional(v)
214
+ }
215
+ return result
216
+ } else {
217
+ // Try to convert to dictionary using Mirror reflection
218
+ let mirror = Mirror(reflecting: value)
219
+ var result: [String: Any] = [:]
220
+ for child in mirror.children {
221
+ if let label = child.label {
222
+ result[label] = unwrapOptional(child.value)
223
+ }
224
+ }
225
+ return result
226
+ }
227
+ }
228
+
229
+ // MARK: - Recursively Clean Dictionary
230
+ private func cleanDictionary(_ dict: [String: Any]) -> [String: Any] {
231
+ var cleaned: [String: Any] = [:]
232
+ for (key, value) in dict {
233
+ cleaned[key] = unwrapOptional(value)
234
+ }
235
+ return cleaned
236
+ }
237
+
238
+ // MARK: - Unwrap Optionals and Clean Nested Structures
239
+ private func unwrapOptional(_ value: Any) -> Any {
240
+ let mirror = Mirror(reflecting: value)
241
+
242
+ // 1. Handle Optional
243
+ let typeName = String(describing: type(of: value))
244
+ if typeName.hasPrefix("Optional<") {
245
+ if let unwrapped = mirror.children.first?.value {
246
+ return unwrapOptional(unwrapped)
247
+ } else {
248
+ return NSNull()
249
+ }
250
+ }
251
+
252
+ // 2. Strings cleanup
253
+ if let str = value as? String {
254
+ return str.replacingOccurrences(of: "Optional\\(|\\)",
255
+ with: "",
256
+ options: .regularExpression)
257
+ }
258
+
259
+ // 3. Arrays
260
+ if let array = value as? [Any] {
261
+ return array.map { unwrapOptional($0) }
262
+ }
263
+
264
+ // 4. Dictionaries
265
+ if let dict = value as? [String: Any] {
266
+ // 👇 Detect special case: metadata dictionaries
267
+ if dict.keys.count == 1, let firstKey = dict.keys.first {
268
+ if ["string", "bool", "int", "double", "float"].contains(firstKey.lowercased()) {
269
+ return unwrapOptional(dict[firstKey]!)
270
+ }
271
+ }
272
+ return cleanDictionary(dict)
273
+ } else if let dict = value as? [AnyHashable: Any] {
274
+ var result: [String: Any] = [:]
275
+ for (k, v) in dict {
276
+ result[String(describing: k)] = unwrapOptional(v)
277
+ }
278
+ return result
279
+ }
280
+
281
+ // 5. Dates
282
+ if let date = value as? Date {
283
+ let formatter = DateFormatter()
284
+ formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
285
+ return formatter.string(from: date)
286
+ }
287
+
288
+ // 6. Custom objects
289
+ let objectMirror = Mirror(reflecting: value)
290
+ if !objectMirror.children.isEmpty {
291
+ var result: [String: Any] = [:]
292
+ for child in objectMirror.children {
293
+ if let label = child.label {
294
+ result[label] = unwrapOptional(child.value)
295
+ }
296
+ }
297
+ return result
298
+ }
299
+
300
+ // 7. Primitives
301
+ return value
174
302
  }
175
303
 
176
- // MARK: - Sync All Data
177
- @objc
178
- func syncAllData(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
179
- InfivizShotsSDK.shared.syncAllData { result in
180
- switch result {
181
- case .success(let message):
182
- resolve(message)
183
- case .failure(let error):
184
- reject("SYNC_FAILED", "Sync failed: \(error)", nil)
185
- }
186
- }
187
- }
188
-
189
- // MARK: - Fetch Session Details
190
- @objc
191
- func fetchSessionDetails(_ temporarySessionID: NSString, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
192
- InfivizShotsSDK.shared.fetchSessionDetails(temporarySessionID: temporarySessionID as String) { result in
193
- switch result {
194
- case .success(let value):
195
- // Convert any value to a clean dictionary that handles Optionals properly
196
- let cleanDict = self.convertToCleanDictionary(value)
197
- // Return the dictionary directly instead of JSON string
198
- resolve(cleanDict)
199
- case .failure(let error):
200
- reject("RESULT_FAILED", "Failed to get result: \(error)", nil)
201
- }
202
- }
203
- }
204
-
205
- // Helper method to convert any value to a clean dictionary that handles Optionals
206
- private func convertToCleanDictionary(_ value: Any) -> [String: Any] {
207
- if let dict = value as? [String: Any] {
208
- return cleanDictionary(dict)
209
- } else {
210
- // Try to convert to dictionary using Mirror reflection
211
- let mirror = Mirror(reflecting: value)
212
- var result: [String: Any] = [:]
213
-
214
- for child in mirror.children {
215
- if let label = child.label {
216
- result[label] = unwrapOptional(child.value)
217
- }
218
- }
219
- return result
220
- }
221
- }
222
-
223
- // Recursively clean a dictionary to handle Optionals
224
- private func cleanDictionary(_ dict: [String: Any]) -> [String: Any] {
225
- var cleaned: [String: Any] = [:]
226
-
227
- for (key, value) in dict {
228
- cleaned[key] = unwrapOptional(value)
229
- }
230
-
231
- return cleaned
232
- }
233
-
234
- // Unwrap Optional values and clean nested structures
235
- private func unwrapOptional(_ value: Any) -> Any {
236
- let mirror = Mirror(reflecting: value)
237
-
238
- // Check if it's an Optional by checking the type name
239
- let typeName = String(describing: type(of: value))
240
- if typeName.hasPrefix("Optional<") {
241
- if let unwrapped = mirror.children.first?.value {
242
- return unwrapOptional(unwrapped)
243
- } else {
244
- return NSNull() // nil value
245
- }
246
- }
247
-
248
- // Handle arrays
249
- if let array = value as? [Any] {
250
- return array.map { unwrapOptional($0) }
251
- }
252
-
253
- // Handle dictionaries
254
- if let dict = value as? [String: Any] {
255
- return cleanDictionary(dict)
256
- }
257
-
258
- // Handle Date objects
259
- if let date = value as? Date {
260
- let formatter = DateFormatter()
261
- formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
262
- return formatter.string(from: date)
263
- }
264
-
265
- // Handle custom objects (like ImageMetaData) using Mirror reflection
266
- // This ensures that objects with optional properties are properly serialized
267
- let objectMirror = Mirror(reflecting: value)
268
- if !objectMirror.children.isEmpty {
269
- var result: [String: Any] = [:]
270
- for child in objectMirror.children {
271
- if let label = child.label {
272
- result[label] = unwrapOptional(child.value)
273
- }
274
- }
275
- return result
276
- }
277
-
278
- // Return the value as-is if it's a basic type
279
- return value
280
- }
281
-
282
- // MARK: - Logout
283
- @objc
284
- func logout(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
285
- InfivizShotsSDK.shared.callLogoutAPI { result in
286
- switch result {
287
- case .success(let success):
288
- resolve(success)
289
- case .failure(let error):
290
- reject("LOGOUT_FAILED", "Logout error: \(error)", nil)
291
- }
292
- }
293
- }
294
-
295
- // MARK: - Reprocessing Enable Time
296
- @objc
297
- func getReprocessingButtonEnableTime(_ sessionID: NSString, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
298
- InfivizShotsSDK.shared.getReprocessingButtonEnableTime(sessionID: sessionID as String) { result in
299
- switch result {
300
- case .success(let time):
301
- resolve(time)
302
- case .failure(let error):
303
- reject("REPROCESS_TIME_ERROR", "Error fetching reprocessing time: \(error)", nil)
304
- }
305
- }
306
- }
307
-
308
- // MARK: - Start Reprocessing Workflow
309
- @objc
310
- func startReprocessingWorkflow(_ sessionID: NSString, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
311
- InfivizShotsSDK.shared.startReprocessingWorkflow(sessionID: sessionID as String) { result in
312
- switch result {
313
- case .success(let time):
314
- resolve(time)
315
- case .failure(let error):
316
- reject("REPROCESS_WORKFLOW_ERROR", "Reprocessing workflow error: \(error)", nil)
317
- }
318
- }
319
- }
320
-
321
- // MARK: - Start Camera
304
+
305
+ // MARK: - Logout
306
+ @objc
307
+ func logout(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
308
+ InfivizShotsSDK.shared.callLogoutAPI { result in
309
+ switch result {
310
+ case .success(let success):
311
+ resolve(success)
312
+ case .failure(let error):
313
+ reject("LOGOUT_FAILED", "Logout error: \(error)", nil)
314
+ }
315
+ }
316
+ }
317
+
318
+ // MARK: - Reprocessing Enable Time
319
+ @objc
320
+ func getReprocessingButtonEnableTime(_ sessionID: NSString, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
321
+ InfivizShotsSDK.shared.getReprocessingButtonEnableTime(sessionID: sessionID as String) { result in
322
+ switch result {
323
+ case .success(let time):
324
+ resolve(time)
325
+ case .failure(let error):
326
+ reject("REPROCESS_TIME_ERROR", "Error fetching reprocessing time: \(error)", nil)
327
+ }
328
+ }
329
+ }
330
+
331
+ // MARK: - Start Reprocessing Workflow
332
+ @objc
333
+ func startReprocessingWorkflow(_ sessionID: NSString, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
334
+ InfivizShotsSDK.shared.startReprocessingWorkflow(sessionID: sessionID as String) { result in
335
+ switch result {
336
+ case .success(let time):
337
+ resolve(time)
338
+ case .failure(let error):
339
+ reject("REPROCESS_WORKFLOW_ERROR", "Reprocessing workflow error: \(error)", nil)
340
+ }
341
+ }
342
+ }
343
+
344
+ // MARK: - Start Camera
322
345
  @objc(startCamera:storeTitle:storeId:photoType:category:maxPhoto:maxPhotoOneGo:metaData:resolver:rejecter:)
323
346
  func startCamera(_ taskName: NSString,
324
347
  storeTitle: NSString,
@@ -330,229 +353,229 @@ class InfivizShotsReactSdk: RCTEventEmitter {
330
353
  metaData: NSDictionary,
331
354
  resolver resolve: @escaping RCTPromiseResolveBlock,
332
355
  rejecter reject: @escaping RCTPromiseRejectBlock) {
333
-
334
- DispatchQueue.main.async {
335
- // 1️⃣ Build the CameraContext just like before
336
- let metadataDict: [String: Any]? = metaData as? [String: Any]
337
- let context = CameraContext(
338
- taskName: taskName as String,
339
- storeTitle: storeTitle as String,
340
- storeId: storeId as String,
341
- photoType: photoType as String,
342
- category: category as String,
343
- maxPhoto: maxPhoto.intValue,
344
- maxPhotoOneGo: maxPhotoOneGo.intValue,
345
- tempSessionId: nil,
346
- imageURI: nil,
347
- navigationController: nil,
348
- retake: false,
349
- metaData: metadataDict
356
+
357
+ DispatchQueue.main.async {
358
+ // 1️⃣ Build the CameraContext just like before
359
+ let metadataDict: [String: Any]? = metaData as? [String: Any]
360
+ let context = CameraContext(
361
+ taskName: taskName as String,
362
+ storeTitle: storeTitle as String,
363
+ storeId: storeId as String,
364
+ photoType: photoType as String,
365
+ category: category as String,
366
+ maxPhoto: maxPhoto.intValue,
367
+ maxPhotoOneGo: maxPhotoOneGo.intValue,
368
+ tempSessionId: nil,
369
+ imageURI: nil,
370
+ navigationController: nil,
371
+ retake: false,
372
+ metaData: metadataDict
373
+ )
374
+
375
+ // 2️⃣ Instantiate the SDK activity
376
+ let activity = InfilectSDKCameraActivityForResult(cameraContext: context)
377
+
378
+ // 3️⃣ Call its existing `start(completion:)` which will handle validation,
379
+ activity.start { result in
380
+ switch result {
381
+ case .success(let sessionID):
382
+ resolve(sessionID)
383
+ case .failure(let apiError):
384
+ reject("CAMERA_ERROR", apiError.localizedDescription, nil)
385
+ }
386
+ }
387
+ }
388
+ }
389
+
390
+ @objc
391
+ func initialize(_ appID: NSString,
392
+ authSecret: NSString,
393
+ accountKey: NSString,
394
+ userID: NSString,
395
+ clientID: NSString,
396
+ apiToken: NSString,
397
+ env: NSString,
398
+ resolver resolve: @escaping RCTPromiseResolveBlock,
399
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
400
+
401
+ let model = InfivizUserLoginContext(
402
+ appID: appID as String,
403
+ authSecret: authSecret as String,
404
+ accountKey: accountKey as String,
405
+ userID: userID as String,
406
+ clientID: clientID as String,
407
+ apiToken: apiToken as String
350
408
  )
351
-
352
- // 2️⃣ Instantiate the SDK activity
353
- let activity = InfilectSDKCameraActivityForResult(cameraContext: context)
354
-
355
- // 3️⃣ Call its existing `start(completion:)` which will handle validation,
356
- activity.start { result in
357
- switch result {
358
- case .success(let sessionID):
359
- resolve(sessionID)
360
- case .failure(let apiError):
361
- reject("CAMERA_ERROR", apiError.localizedDescription, nil)
362
- }
409
+
410
+ let environment = APIEnvironment(rawValue: env as String) ?? .production
411
+ InfivizShotsSDK.shared.initializeEnvironent(environment)
412
+ activity = InfivizShotsActivity(model: model)
413
+ activity?.initialize { result in
414
+ switch result {
415
+ case .success(let success):
416
+ resolve(success)
417
+ case .failure(let error):
418
+ reject("LOGIN_FAILED", error.localizedDescription, nil)
419
+ }
363
420
  }
364
- }
365
421
  }
366
-
367
- @objc
368
- func initialize(_ appID: NSString,
369
- authSecret: NSString,
370
- accountKey: NSString,
371
- userID: NSString,
372
- clientID: NSString,
373
- apiToken: NSString,
374
- env: NSString,
422
+
423
+ @objc
424
+ func fetchSessionID(_ taskCategory: NSString,
425
+ storeID: NSString,
426
+ taskPhotoType: NSString,
427
+ resolver resolve: @escaping RCTPromiseResolveBlock,
428
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
429
+
430
+ InfivizShotsSDK.shared.fetchSessionID(
431
+ taskCategory: taskCategory as String,
432
+ storeID: storeID as String,
433
+ taskPhotoType: taskPhotoType as String
434
+ ) { sessionID, error in
435
+ if let id = sessionID {
436
+ resolve(id)
437
+ } else {
438
+ reject("SESSION_NOT_FOUND", "Session not found", nil)
439
+ }
440
+ }
441
+ }
442
+
443
+ // MARK: - View IR Results via bridge
444
+ @objc(viewIRResults:resolver:rejecter:)
445
+ func viewIRResults(_ sessionID: NSString,
375
446
  resolver resolve: @escaping RCTPromiseResolveBlock,
376
- rejecter reject: @escaping RCTPromiseRejectBlock) {
377
-
378
- let model = InfivizUserLoginContext(
379
- appID: appID as String,
380
- authSecret: authSecret as String,
381
- accountKey: accountKey as String,
382
- userID: userID as String,
383
- clientID: clientID as String,
384
- apiToken: apiToken as String
385
- )
386
-
387
- let environment = APIEnvironment(rawValue: env as String) ?? .production
388
- InfivizShotsSDK.shared.initializeEnvironent(environment)
389
- activity = InfivizShotsActivity(model: model)
390
- activity?.initialize { result in
391
- switch result {
392
- case .success(let success):
393
- resolve(success)
394
- case .failure(let error):
395
- reject("LOGIN_FAILED", error.localizedDescription, nil)
396
- }
397
- }
398
- }
399
-
400
- @objc
401
- func fetchSessionID(_ taskCategory: NSString,
402
- storeID: NSString,
403
- taskPhotoType: NSString,
404
- resolver resolve: @escaping RCTPromiseResolveBlock,
405
- rejecter reject: @escaping RCTPromiseRejectBlock) {
406
-
407
- InfivizShotsSDK.shared.fetchSessionID(
408
- taskCategory: taskCategory as String,
409
- storeID: storeID as String,
410
- taskPhotoType: taskPhotoType as String
411
- ) { sessionID, error in
412
- if let id = sessionID {
413
- resolve(id)
414
- } else {
415
- reject("SESSION_NOT_FOUND", "Session not found", nil)
416
- }
417
- }
418
- }
419
-
420
- // MARK: - View IR Results via bridge
421
- @objc(viewIRResults:resolver:rejecter:)
422
- func viewIRResults(_ sessionID: NSString,
423
- resolver resolve: @escaping RCTPromiseResolveBlock,
424
- rejecter reject: @escaping RCTPromiseRejectBlock) {
425
- DispatchQueue.main.async {
426
- guard let navigationController = UIApplication.shared.connectedScenes
427
- .compactMap({ $0 as? UIWindowScene })
428
- .flatMap({ $0.windows })
429
- .first(where: { $0.isKeyWindow })?
430
- .rootViewController?.navigationController else {
431
- reject("NAV_ERROR", "No navigation controller available", nil)
432
- return
433
- }
434
- let realTimeView = InfivizRealTimeView(sessionID: sessionID as String,
435
- navigationController: navigationController)
436
- realTimeView.viewIRResults(sessionID: sessionID as String) { result in
437
- switch result {
438
- case .success(let value): resolve(value)
439
- case .failure(let error): reject("VIEW_IR_FAILED", error.localizedDescription, nil)
440
- }
441
- }
442
- }
443
- }
444
-
445
- // MARK: - Start Actions Workflow via bridge
446
- @objc(startActionsWorkFlow:sessionId:latitude:longitude:dateTimeStamp:resolver:rejecter:)
447
- func startActionsWorkFlow(_ storeId: NSString,
448
- sessionId: NSString,
449
- latitude: NSString,
450
- longitude: NSString,
451
- dateTimeStamp: NSString,
452
- resolver resolve: @escaping RCTPromiseResolveBlock,
453
- rejecter reject: @escaping RCTPromiseRejectBlock) {
454
- DispatchQueue.main.async {
455
- guard let navigationController = UIApplication.shared.connectedScenes
456
- .compactMap({ $0 as? UIWindowScene })
457
- .flatMap({ $0.windows })
458
- .first(where: { $0.isKeyWindow })?
459
- .rootViewController?.navigationController else {
460
- reject("NAV_ERROR", "No navigation controller available", nil)
461
- return
462
- }
463
- let realTimeView = InfivizRealTimeView(sessionID: sessionId as String,
464
- navigationController: navigationController)
465
- realTimeView.startActionsWorkFlow(storeId: storeId as String,
466
- sessionId: sessionId as String,
467
- latitude: latitude as String,
468
- longitude: longitude as String,
469
- dateTimeStamp: dateTimeStamp as String) { result in
470
- switch result {
471
- case .success(let value): resolve(value)
472
- case .failure(let error): reject("ACTIONS_WORKFLOW_FAILED", error.localizedDescription, nil)
473
- }
474
- }
475
- }
476
- }
477
-
478
- @objc(resumeCamera:metaData:resolver:rejecter:)
447
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
448
+ DispatchQueue.main.async {
449
+ guard let navigationController = UIApplication.shared.connectedScenes
450
+ .compactMap({ $0 as? UIWindowScene })
451
+ .flatMap({ $0.windows })
452
+ .first(where: { $0.isKeyWindow })?
453
+ .rootViewController?.navigationController else {
454
+ reject("NAV_ERROR", "No navigation controller available", nil)
455
+ return
456
+ }
457
+ let realTimeView = InfivizRealTimeView(sessionID: sessionID as String,
458
+ navigationController: navigationController)
459
+ realTimeView.viewIRResults(sessionID: sessionID as String) { result in
460
+ switch result {
461
+ case .success(let value): resolve(value)
462
+ case .failure(let error): reject("VIEW_IR_FAILED", error.localizedDescription, nil)
463
+ }
464
+ }
465
+ }
466
+ }
467
+
468
+ // MARK: - Start Actions Workflow via bridge
469
+ @objc(startActionsWorkFlow:sessionId:latitude:longitude:dateTimeStamp:resolver:rejecter:)
470
+ func startActionsWorkFlow(_ storeId: NSString,
471
+ sessionId: NSString,
472
+ latitude: NSString,
473
+ longitude: NSString,
474
+ dateTimeStamp: NSString,
475
+ resolver resolve: @escaping RCTPromiseResolveBlock,
476
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
477
+ DispatchQueue.main.async {
478
+ guard let navigationController = UIApplication.shared.connectedScenes
479
+ .compactMap({ $0 as? UIWindowScene })
480
+ .flatMap({ $0.windows })
481
+ .first(where: { $0.isKeyWindow })?
482
+ .rootViewController?.navigationController else {
483
+ reject("NAV_ERROR", "No navigation controller available", nil)
484
+ return
485
+ }
486
+ let realTimeView = InfivizRealTimeView(sessionID: sessionId as String,
487
+ navigationController: navigationController)
488
+ realTimeView.startActionsWorkFlow(storeId: storeId as String,
489
+ sessionId: sessionId as String,
490
+ latitude: latitude as String,
491
+ longitude: longitude as String,
492
+ dateTimeStamp: dateTimeStamp as String) { result in
493
+ switch result {
494
+ case .success(let value): resolve(value)
495
+ case .failure(let error): reject("ACTIONS_WORKFLOW_FAILED", error.localizedDescription, nil)
496
+ }
497
+ }
498
+ }
499
+ }
500
+
501
+ @objc(resumeCamera:metaData:resolver:rejecter:)
479
502
  func resumeCamera(
480
- _ temporarySessionID: NSString,
481
- metaData: NSDictionary?,
482
- resolver resolve: @escaping RCTPromiseResolveBlock,
483
- rejecter reject: @escaping RCTPromiseRejectBlock
503
+ _ temporarySessionID: NSString,
504
+ metaData: NSDictionary?,
505
+ resolver resolve: @escaping RCTPromiseResolveBlock,
506
+ rejecter reject: @escaping RCTPromiseRejectBlock
484
507
  ) {
485
- // Build whatever CameraContext your SDK needs. In your original UI code,
486
- // you were reading from text fields (e.g. shelfTextField.text, traderTextField.text, etc.).
487
- // In a module method you typically won't have those outlets available, so you'll
488
- // need to pass any required "taskName", "storeTitle" etc. from JS into this call
489
- // or hard‐code defaults here. For now, I'll show a minimal example:
490
-
491
- let context = CameraContext(
492
- taskName: "", // ← pass in from JS if you really need it
493
- storeTitle: "",
494
- storeId: "",
495
- photoType: "",
496
- category: "",
497
- maxPhoto: 0,
498
- maxPhotoOneGo: 0,
499
- navigationController: nil // ← no UIKit nav controller in RN module
500
- )
501
-
502
- // Instantiate your SDK's camera controller just like before:
503
- let controller = InfilectSDKCameraActivityForResult(cameraContext: context)
504
-
505
- // Convert NSDictionary to [String: Any]
506
- let metadataDict: [String: Any]? = metaData as? [String: Any]
507
-
508
- // Call the updated `resumeCamera(sessionID:metaData:completion:)` API with metadata
509
- controller.resumeCamera(sessionID: temporarySessionID as String, metaData: metadataDict) { result in
510
- switch result {
511
- case .success(let successString):
512
- // fulfill the JS promise with the returned string
513
- resolve(successString)
514
-
515
- case .failure(let sdkError):
516
- // reject the JS promise
517
- let nsError = sdkError as NSError
518
- reject(
519
- "ResumeCameraError",
520
- "Failed to resume camera: \(nsError.localizedDescription)",
521
- nsError
522
- )
508
+ // Build whatever CameraContext your SDK needs. In your original UI code,
509
+ // you were reading from text fields (e.g. shelfTextField.text, traderTextField.text, etc.).
510
+ // In a module method you typically won't have those outlets available, so you'll
511
+ // need to pass any required "taskName", "storeTitle" etc. from JS into this call
512
+ // or hard‐code defaults here. For now, I'll show a minimal example:
513
+
514
+ let context = CameraContext(
515
+ taskName: "", // ← pass in from JS if you really need it
516
+ storeTitle: "",
517
+ storeId: "",
518
+ photoType: "",
519
+ category: "",
520
+ maxPhoto: 0,
521
+ maxPhotoOneGo: 0,
522
+ navigationController: nil // ← no UIKit nav controller in RN module
523
+ )
524
+
525
+ // Instantiate your SDK's camera controller just like before:
526
+ let controller = InfilectSDKCameraActivityForResult(cameraContext: context)
527
+
528
+ // Convert NSDictionary to [String: Any]
529
+ let metadataDict: [String: Any]? = metaData as? [String: Any]
530
+
531
+ // Call the updated `resumeCamera(sessionID:metaData:completion:)` API with metadata
532
+ controller.resumeCamera(sessionID: temporarySessionID as String, metaData: metadataDict) { result in
533
+ switch result {
534
+ case .success(let successString):
535
+ // fulfill the JS promise with the returned string
536
+ resolve(successString)
537
+
538
+ case .failure(let sdkError):
539
+ // reject the JS promise
540
+ let nsError = sdkError as NSError
541
+ reject(
542
+ "ResumeCameraError",
543
+ "Failed to resume camera: \(nsError.localizedDescription)",
544
+ nsError
545
+ )
546
+ }
523
547
  }
524
- }
525
548
  }
526
-
527
- @objc
528
- func deletePhoto(
529
- _ imageURI: NSString,
530
- temporarySessionId: NSString,
531
- resolver resolve: @escaping RCTPromiseResolveBlock,
532
- rejecter reject: @escaping RCTPromiseRejectBlock
533
- ) {
534
- let context = CameraContext(
535
- taskName: "",
536
- storeTitle: "",
537
- storeId: "",
538
- photoType: "",
539
-
540
- category: "",
541
- maxPhoto: 0,
542
- maxPhotoOneGo: 0,
543
- navigationController: nil
544
- )
545
- let controller = InfilectSDKCameraActivityForResult(cameraContext: context)
546
- controller.deleteImage(imageID: imageURI as String, sessionID: temporarySessionId as String) { result in
547
- switch result {
548
- case .success(let successMessage):
549
- resolve(successMessage)
550
- case .failure(let error):
551
- reject("DELETE_IMAGE_ERROR", "Failed to delete image: \(error.localizedDescription)", error)
552
- }
553
- }
554
- }
555
-
549
+
550
+ @objc
551
+ func deletePhoto(
552
+ _ imageURI: NSString,
553
+ temporarySessionId: NSString,
554
+ resolver resolve: @escaping RCTPromiseResolveBlock,
555
+ rejecter reject: @escaping RCTPromiseRejectBlock
556
+ ) {
557
+ let context = CameraContext(
558
+ taskName: "",
559
+ storeTitle: "",
560
+ storeId: "",
561
+ photoType: "",
562
+
563
+ category: "",
564
+ maxPhoto: 0,
565
+ maxPhotoOneGo: 0,
566
+ navigationController: nil
567
+ )
568
+ let controller = InfilectSDKCameraActivityForResult(cameraContext: context)
569
+ controller.deleteImage(imageID: imageURI as String, sessionID: temporarySessionId as String) { result in
570
+ switch result {
571
+ case .success(let successMessage):
572
+ resolve(successMessage)
573
+ case .failure(let error):
574
+ reject("DELETE_IMAGE_ERROR", "Failed to delete image: \(error.localizedDescription)", error)
575
+ }
576
+ }
577
+ }
578
+
556
579
  @objc(retakeImage:imageURL:metaData:resolver:rejecter:)
557
580
  func retakeImage(
558
581
  _ temporarySessionId: NSString,
@@ -593,70 +616,70 @@ class InfivizShotsReactSdk: RCTEventEmitter {
593
616
  }
594
617
  }
595
618
  }
596
-
597
- // MARK: – React Native Promise Exposures for OutputAPI
598
- /// Expose `getIRResult(sessionID:completion:)` to JavaScript as:
599
- /// InfiBridge.getIRResult("session-123").then(...).catch(...)
600
- @objc
601
- func getIrResult(
602
- _ sessionId: NSString,
603
- resolver resolve: @escaping RCTPromiseResolveBlock,
604
- rejecter reject: @escaping RCTPromiseRejectBlock
605
- ) {
606
- print("Inside GetIrResult sessionId -> \(sessionId)")
607
- // Call the Swift helper (which calls outputAPI.getIRResult)
608
- InfivizShotsSDK.shared.getIrResult(sessionID: sessionId as String) { (dataAny, error) in
609
- if let err = error {
610
- // If the SDK returned an error, reject the JS promise
611
- print("err", err)
612
- reject(
613
- "IR_RESULT_ERROR", // error code (custom identifier)
614
- err as? String, // error message
615
- nil // optional NSError (can be nil)
616
- )
617
- } else if let output = dataAny {
618
- // If the SDK returned data (Any), pass it back to JS.
619
- resolve(output)
620
- } else {
621
- // Neither data nor error? Just resolve with `nil`.
622
- resolve(nil)
623
- }
624
- }
625
- }
626
-
627
- /// Expose `getActionsResult(sessionID:completion:)` to JavaScript as:
628
- /// InfiBridge.getActionsResult("session-123").then(...).catch(...)
629
- @objc
630
- func getActionsResult(
631
- _ sessionId: NSString,
632
- resolver resolve: @escaping RCTPromiseResolveBlock,
633
- rejecter reject: @escaping RCTPromiseRejectBlock
634
- ) {
635
- // Call the Swift helper (which calls outputAPI.getActionsResult)
636
- InfivizShotsSDK.shared.getActionsResult(sessionID: sessionId as String) { (dataAny, error) in
637
- if let err = error {
638
- reject("ACTIONS_FAILED", err as? String, nil)
639
- } else if let output = dataAny {
640
- resolve(output)
641
- } else {
642
- resolve(nil)
643
- }
644
- }
645
- }
646
-
647
- @objc
648
- private func handleActionsGeneratedEvent(_ notification: Notification) {
649
- guard hasListeners else { return }
650
-
651
- let payload = notification.userInfo ?? [:]
652
- sendEvent(withName: "ActionsGeneratedEvent", body: payload)
619
+
620
+ // MARK: – React Native Promise Exposures for OutputAPI
621
+ /// Expose `getIRResult(sessionID:completion:)` to JavaScript as:
622
+ /// InfiBridge.getIRResult("session-123").then(...).catch(...)
623
+ @objc
624
+ func getIrResult(
625
+ _ sessionId: NSString,
626
+ resolver resolve: @escaping RCTPromiseResolveBlock,
627
+ rejecter reject: @escaping RCTPromiseRejectBlock
628
+ ) {
629
+ print("Inside GetIrResult sessionId -> \(sessionId)")
630
+ // Call the Swift helper (which calls outputAPI.getIRResult)
631
+ InfivizShotsSDK.shared.getIrResult(sessionID: sessionId as String) { (dataAny, error) in
632
+ if let err = error {
633
+ // If the SDK returned an error, reject the JS promise
634
+ print("err", err)
635
+ reject(
636
+ "IR_RESULT_ERROR", // error code (custom identifier)
637
+ err as? String, // error message
638
+ nil // optional NSError (can be nil)
639
+ )
640
+ } else if let output = dataAny {
641
+ // If the SDK returned data (Any), pass it back to JS.
642
+ resolve(output)
643
+ } else {
644
+ // Neither data nor error? Just resolve with `nil`.
645
+ resolve(nil)
646
+ }
653
647
  }
654
-
655
- @objc
656
- private func handleSessionRealTimeResultEvent(_ notification: Notification) {
657
- guard hasListeners else { return }
658
-
659
- let payload = notification.userInfo ?? [:]
660
- sendEvent(withName: "SessionRealTimeResultEvent", body: payload)
648
+ }
649
+
650
+ /// Expose `getActionsResult(sessionID:completion:)` to JavaScript as:
651
+ /// InfiBridge.getActionsResult("session-123").then(...).catch(...)
652
+ @objc
653
+ func getActionsResult(
654
+ _ sessionId: NSString,
655
+ resolver resolve: @escaping RCTPromiseResolveBlock,
656
+ rejecter reject: @escaping RCTPromiseRejectBlock
657
+ ) {
658
+ // Call the Swift helper (which calls outputAPI.getActionsResult)
659
+ InfivizShotsSDK.shared.getActionsResult(sessionID: sessionId as String) { (dataAny, error) in
660
+ if let err = error {
661
+ reject("ACTIONS_FAILED", err as? String, nil)
662
+ } else if let output = dataAny {
663
+ resolve(output)
664
+ } else {
665
+ resolve(nil)
666
+ }
661
667
  }
668
+ }
669
+
670
+ @objc
671
+ private func handleActionsGeneratedEvent(_ notification: Notification) {
672
+ guard hasListeners else { return }
673
+
674
+ let payload = notification.userInfo ?? [:]
675
+ sendEvent(withName: "ActionsGeneratedEvent", body: payload)
676
+ }
677
+
678
+ @objc
679
+ private func handleSessionRealTimeResultEvent(_ notification: Notification) {
680
+ guard hasListeners else { return }
681
+
682
+ let payload = notification.userInfo ?? [:]
683
+ sendEvent(withName: "SessionRealTimeResultEvent", body: payload)
684
+ }
662
685
  }