@infilectorg/infiviz-shots-react-sdk 1.0.52 → 1.0.53
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.
- package/android/build.gradle +1 -1
- package/ios/InfivizShotSDK.xcframework/Info.plist +5 -5
- package/ios/InfivizShotSDK.xcframework/ios-arm64/InfivizShotSDK.framework/Assets.car +0 -0
- package/ios/InfivizShotSDK.xcframework/ios-arm64/InfivizShotSDK.framework/InfivizShotSDK +0 -0
- package/ios/InfivizShotSDK.xcframework/ios-arm64/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/arm64-apple-ios.abi.json +77 -77
- package/ios/InfivizShotSDK.xcframework/ios-arm64/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/arm64-apple-ios.swiftmodule +0 -0
- package/ios/InfivizShotSDK.xcframework/ios-arm64/InfivizShotSDK.framework/shotsSDK.storyboardc/xUL-ol-gRQ-view-6A8-mO-Rhi.nib +0 -0
- package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/InfivizShotSDK +0 -0
- package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +77 -77
- package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/arm64-apple-ios-simulator.swiftmodule +0 -0
- package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/x86_64-apple-ios-simulator.abi.json +77 -77
- package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/Modules/InfivizShotSDK.swiftmodule/x86_64-apple-ios-simulator.swiftmodule +0 -0
- package/ios/InfivizShotSDK.xcframework/ios-arm64_x86_64-simulator/InfivizShotSDK.framework/shotsSDK.storyboardc/xUL-ol-gRQ-view-6A8-mO-Rhi.nib +0 -0
- package/ios/InfivizShotsReactSdk.swift +564 -590
- package/lib/module/NativeInfivizShotsReactSdk.js +2 -0
- package/lib/module/NativeInfivizShotsReactSdk.js.map +1 -1
- package/lib/module/index.js +4 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/package.json +1 -0
- package/lib/module/types/Environment.js +2 -0
- package/lib/module/types/Environment.js.map +1 -1
- package/lib/module/types/ImageMetaData.js +2 -0
- package/lib/module/types/ImageMetaData.js.map +1 -1
- package/lib/module/types/InfiSession.js +2 -0
- package/lib/module/types/InfiSession.js.map +1 -1
- package/lib/module/types/LabelScore.js +1 -1
- package/lib/module/types/LabelScore.js.map +1 -1
- package/lib/module/types/SessionStatus.js +1 -1
- package/lib/module/types/SessionStatus.js.map +1 -1
- package/lib/module/types/SessionSyncStateEnum.js +2 -0
- package/lib/module/types/SessionSyncStateEnum.js.map +1 -1
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeInfivizShotsReactSdk.d.ts +23 -0
- package/lib/typescript/src/NativeInfivizShotsReactSdk.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +24 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types/Environment.d.ts +5 -0
- package/lib/typescript/src/types/Environment.d.ts.map +1 -0
- package/lib/typescript/src/types/ImageMetaData.d.ts +13 -0
- package/lib/typescript/src/types/ImageMetaData.d.ts.map +1 -0
- package/lib/typescript/src/types/InfiSession.d.ts +18 -0
- package/lib/typescript/src/types/InfiSession.d.ts.map +1 -0
- package/lib/typescript/src/types/LabelScore.d.ts +5 -0
- package/lib/typescript/src/types/LabelScore.d.ts.map +1 -0
- package/lib/typescript/src/types/SessionStatus.d.ts +5 -0
- package/lib/typescript/src/types/SessionStatus.d.ts.map +1 -0
- package/lib/typescript/src/types/SessionSyncStateEnum.d.ts +8 -0
- package/lib/typescript/src/types/SessionSyncStateEnum.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -12,339 +12,313 @@ import React
|
|
|
12
12
|
|
|
13
13
|
@objc(InfivizShotsReactSdk)
|
|
14
14
|
class InfivizShotsReactSdk: RCTEventEmitter {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
NotificationCenter.default.addObserver(self,
|
|
42
|
-
selector: #selector(handleActionsGeneratedEvent(_:)),
|
|
43
|
-
name: NSNotification.Name("ActionsGeneratedEvent"),
|
|
44
|
-
object: nil)
|
|
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
|
+
|
|
45
41
|
NotificationCenter.default.addObserver(self,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
-
|
|
116
|
+
ids = arr
|
|
117
117
|
} else if let arr = temporarySessionIDs as? [NSString] {
|
|
118
|
-
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
}
|
|
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)
|
|
143
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
|
+
}
|
|
143
|
+
}
|
|
144
144
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// MARK: - Get Session Result
|
|
148
|
+
|
|
149
149
|
@objc
|
|
150
150
|
func getSessionStatus(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
_ temporarySessionID: NSString,
|
|
152
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
153
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
154
154
|
) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
)
|
|
172
|
-
}
|
|
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
|
-
print(value)
|
|
198
|
-
// Return the dictionary directly instead of JSON string
|
|
199
|
-
resolve(cleanDict)
|
|
200
|
-
case .failure(let error):
|
|
201
|
-
reject("RESULT_FAILED", "Failed to get result: \(error)", nil)
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// MARK: - Convert Any 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 {
|
|
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
|
-
// MARK: - Recursively Clean Dictionary
|
|
224
|
-
private func cleanDictionary(_ dict: [String: Any]) -> [String: Any] {
|
|
225
|
-
var cleaned: [String: Any] = [:]
|
|
226
|
-
for (key, value) in dict {
|
|
227
|
-
cleaned[key] = unwrapOptional(value)
|
|
228
|
-
}
|
|
229
|
-
return cleaned
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// MARK: - Unwrap Optionals and Flatten SDK Values
|
|
233
|
-
private func unwrapOptional(_ value: Any) -> Any {
|
|
234
|
-
// 1. Handle Optional
|
|
235
|
-
let mirror = Mirror(reflecting: value)
|
|
236
|
-
if mirror.displayStyle == .optional {
|
|
237
|
-
if let unwrapped = mirror.children.first?.value {
|
|
238
|
-
return unwrapOptional(unwrapped)
|
|
239
|
-
} else {
|
|
240
|
-
return NSNull()
|
|
241
|
-
}
|
|
242
|
-
}
|
|
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]
|
|
243
160
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
case .string(let str): return str
|
|
248
|
-
case .bool(let b): return b
|
|
249
|
-
case .int(let i): return i
|
|
250
|
-
case .double(let d): return d
|
|
251
|
-
case .dictionary(let dict):
|
|
252
|
-
var cleaned: [String: Any] = [:]
|
|
253
|
-
for (k, v) in dict {
|
|
254
|
-
cleaned[k] = unwrapOptional(v)
|
|
255
|
-
}
|
|
256
|
-
return cleaned
|
|
257
|
-
case .array(let arr):
|
|
258
|
-
return arr.map { unwrapOptional($0) }
|
|
259
|
-
case .null:
|
|
260
|
-
return NSNull()
|
|
261
|
-
@unknown default:
|
|
262
|
-
return NSNull()
|
|
161
|
+
if let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []) {
|
|
162
|
+
let jsonString = String(data: jsonData, encoding: .utf8)
|
|
163
|
+
resolve(jsonString)
|
|
263
164
|
}
|
|
264
|
-
}
|
|
265
165
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
166
|
+
case .failure(let error):
|
|
167
|
+
reject(
|
|
168
|
+
"RESULT_FAILED",
|
|
169
|
+
"Failed to get result for \(temporarySessionID): \(error.localizedDescription)",
|
|
170
|
+
nil
|
|
171
|
+
)
|
|
269
172
|
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
270
175
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
+
}
|
|
279
188
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
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
|
+
}
|
|
285
281
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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
|
+
}
|
|
292
294
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
+
}
|
|
303
307
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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
|
+
}
|
|
307
320
|
|
|
308
|
-
|
|
309
|
-
@objc
|
|
310
|
-
func logout(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
311
|
-
InfivizShotsSDK.shared.callLogoutAPI { result in
|
|
312
|
-
switch result {
|
|
313
|
-
case .success(let success):
|
|
314
|
-
resolve(success)
|
|
315
|
-
case .failure(let error):
|
|
316
|
-
reject("LOGOUT_FAILED", "Logout error: \(error)", nil)
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
// MARK: - Reprocessing Enable Time
|
|
322
|
-
@objc
|
|
323
|
-
func getReprocessingButtonEnableTime(_ sessionID: NSString, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
324
|
-
InfivizShotsSDK.shared.getReprocessingButtonEnableTime(sessionID: sessionID as String) { result in
|
|
325
|
-
switch result {
|
|
326
|
-
case .success(let time):
|
|
327
|
-
resolve(time)
|
|
328
|
-
case .failure(let error):
|
|
329
|
-
reject("REPROCESS_TIME_ERROR", "Error fetching reprocessing time: \(error)", nil)
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// MARK: - Start Reprocessing Workflow
|
|
335
|
-
@objc
|
|
336
|
-
func startReprocessingWorkflow(_ sessionID: NSString, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
337
|
-
InfivizShotsSDK.shared.startReprocessingWorkflow(sessionID: sessionID as String) { result in
|
|
338
|
-
switch result {
|
|
339
|
-
case .success(let time):
|
|
340
|
-
resolve(time)
|
|
341
|
-
case .failure(let error):
|
|
342
|
-
reject("REPROCESS_WORKFLOW_ERROR", "Reprocessing workflow error: \(error)", nil)
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// MARK: - Start Camera
|
|
321
|
+
// MARK: - Start Camera
|
|
348
322
|
@objc(startCamera:storeTitle:storeId:photoType:category:maxPhoto:maxPhotoOneGo:metaData:resolver:rejecter:)
|
|
349
323
|
func startCamera(_ taskName: NSString,
|
|
350
324
|
storeTitle: NSString,
|
|
@@ -356,229 +330,229 @@ class InfivizShotsReactSdk: RCTEventEmitter {
|
|
|
356
330
|
metaData: NSDictionary,
|
|
357
331
|
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
358
332
|
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
)
|
|
377
|
-
|
|
378
|
-
// 2️⃣ Instantiate the SDK activity
|
|
379
|
-
let activity = InfilectSDKCameraActivityForResult(cameraContext: context)
|
|
380
|
-
|
|
381
|
-
// 3️⃣ Call its existing `start(completion:)` which will handle validation,
|
|
382
|
-
activity.start { result in
|
|
383
|
-
switch result {
|
|
384
|
-
case .success(let sessionID):
|
|
385
|
-
resolve(sessionID)
|
|
386
|
-
case .failure(let apiError):
|
|
387
|
-
reject("CAMERA_ERROR", apiError.localizedDescription, nil)
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
@objc
|
|
394
|
-
func initialize(_ appID: NSString,
|
|
395
|
-
authSecret: NSString,
|
|
396
|
-
accountKey: NSString,
|
|
397
|
-
userID: NSString,
|
|
398
|
-
clientID: NSString,
|
|
399
|
-
apiToken: NSString,
|
|
400
|
-
env: NSString,
|
|
401
|
-
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
402
|
-
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
403
|
-
|
|
404
|
-
let model = InfivizUserLoginContext(
|
|
405
|
-
appID: appID as String,
|
|
406
|
-
authSecret: authSecret as String,
|
|
407
|
-
accountKey: accountKey as String,
|
|
408
|
-
userID: userID as String,
|
|
409
|
-
clientID: clientID as String,
|
|
410
|
-
apiToken: apiToken as String
|
|
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
|
|
411
350
|
)
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
@objc
|
|
427
|
-
func fetchSessionID(_ taskCategory: NSString,
|
|
428
|
-
storeID: NSString,
|
|
429
|
-
taskPhotoType: NSString,
|
|
430
|
-
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
431
|
-
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
432
|
-
|
|
433
|
-
InfivizShotsSDK.shared.fetchSessionID(
|
|
434
|
-
taskCategory: taskCategory as String,
|
|
435
|
-
storeID: storeID as String,
|
|
436
|
-
taskPhotoType: taskPhotoType as String
|
|
437
|
-
) { sessionID, error in
|
|
438
|
-
if let id = sessionID {
|
|
439
|
-
resolve(id)
|
|
440
|
-
} else {
|
|
441
|
-
reject("SESSION_NOT_FOUND", "Session not found", nil)
|
|
442
|
-
}
|
|
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
|
+
}
|
|
443
363
|
}
|
|
364
|
+
}
|
|
444
365
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
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,
|
|
449
375
|
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
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:)
|
|
505
479
|
func resumeCamera(
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
480
|
+
_ temporarySessionID: NSString,
|
|
481
|
+
metaData: NSDictionary?,
|
|
482
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
483
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
510
484
|
) {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
@objc
|
|
554
|
-
func deletePhoto(
|
|
555
|
-
_ imageURI: NSString,
|
|
556
|
-
temporarySessionId: NSString,
|
|
557
|
-
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
558
|
-
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
559
|
-
) {
|
|
560
|
-
let context = CameraContext(
|
|
561
|
-
taskName: "",
|
|
562
|
-
storeTitle: "",
|
|
563
|
-
storeId: "",
|
|
564
|
-
photoType: "",
|
|
565
|
-
|
|
566
|
-
category: "",
|
|
567
|
-
maxPhoto: 0,
|
|
568
|
-
maxPhotoOneGo: 0,
|
|
569
|
-
navigationController: nil
|
|
570
|
-
)
|
|
571
|
-
let controller = InfilectSDKCameraActivityForResult(cameraContext: context)
|
|
572
|
-
controller.deleteImage(imageID: imageURI as String, sessionID: temporarySessionId as String) { result in
|
|
573
|
-
switch result {
|
|
574
|
-
case .success(let successMessage):
|
|
575
|
-
resolve(successMessage)
|
|
576
|
-
case .failure(let error):
|
|
577
|
-
reject("DELETE_IMAGE_ERROR", "Failed to delete image: \(error.localizedDescription)", error)
|
|
578
|
-
}
|
|
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
|
+
)
|
|
579
523
|
}
|
|
524
|
+
}
|
|
580
525
|
}
|
|
581
|
-
|
|
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
|
+
|
|
582
556
|
@objc(retakeImage:imageURL:metaData:resolver:rejecter:)
|
|
583
557
|
func retakeImage(
|
|
584
558
|
_ temporarySessionId: NSString,
|
|
@@ -619,70 +593,70 @@ class InfivizShotsReactSdk: RCTEventEmitter {
|
|
|
619
593
|
}
|
|
620
594
|
}
|
|
621
595
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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)
|
|
670
653
|
}
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
@objc
|
|
674
|
-
private func handleActionsGeneratedEvent(_ notification: Notification) {
|
|
675
|
-
guard hasListeners else { return }
|
|
676
654
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
let payload = notification.userInfo ?? [:]
|
|
686
|
-
sendEvent(withName: "SessionRealTimeResultEvent", body: payload)
|
|
687
|
-
}
|
|
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)
|
|
661
|
+
}
|
|
688
662
|
}
|