@infilectorg/infiviz-shots-react-sdk 1.0.47 → 1.0.49
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/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 +590 -564
- package/lib/module/NativeInfivizShotsReactSdk.js +0 -2
- package/lib/module/NativeInfivizShotsReactSdk.js.map +1 -1
- package/lib/module/index.js +2 -4
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/Environment.js +0 -2
- package/lib/module/types/Environment.js.map +1 -1
- package/lib/module/types/ImageMetaData.js +0 -2
- package/lib/module/types/ImageMetaData.js.map +1 -1
- package/lib/module/types/InfiSession.js +0 -2
- 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 +0 -2
- package/lib/module/types/SessionSyncStateEnum.js.map +1 -1
- package/package.json +1 -1
- package/lib/module/package.json +0 -1
- package/lib/typescript/package.json +0 -1
- package/lib/typescript/src/NativeInfivizShotsReactSdk.d.ts +0 -23
- package/lib/typescript/src/NativeInfivizShotsReactSdk.d.ts.map +0 -1
- package/lib/typescript/src/index.d.ts +0 -24
- package/lib/typescript/src/index.d.ts.map +0 -1
- package/lib/typescript/src/types/Environment.d.ts +0 -5
- package/lib/typescript/src/types/Environment.d.ts.map +0 -1
- package/lib/typescript/src/types/ImageMetaData.d.ts +0 -13
- package/lib/typescript/src/types/ImageMetaData.d.ts.map +0 -1
- package/lib/typescript/src/types/InfiSession.d.ts +0 -18
- package/lib/typescript/src/types/InfiSession.d.ts.map +0 -1
- package/lib/typescript/src/types/LabelScore.d.ts +0 -5
- package/lib/typescript/src/types/LabelScore.d.ts.map +0 -1
- package/lib/typescript/src/types/SessionStatus.d.ts +0 -5
- package/lib/typescript/src/types/SessionStatus.d.ts.map +0 -1
- package/lib/typescript/src/types/SessionSyncStateEnum.d.ts +0 -8
- package/lib/typescript/src/types/SessionSyncStateEnum.d.ts.map +0 -1
|
@@ -12,313 +12,339 @@ 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
|
-
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
}
|
|
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
|
+
}
|
|
165
222
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
)
|
|
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)
|
|
172
228
|
}
|
|
173
|
-
|
|
229
|
+
return cleaned
|
|
174
230
|
}
|
|
175
231
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
+
}
|
|
243
|
+
|
|
244
|
+
// 2. Handle JSONValue directly
|
|
245
|
+
if let jsonValue = value as? InfivizShotSDK.JSONValue {
|
|
246
|
+
switch jsonValue {
|
|
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()
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// 3. Arrays
|
|
267
|
+
if let array = value as? [Any] {
|
|
268
|
+
return array.map { unwrapOptional($0) }
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// 4. Dictionaries
|
|
272
|
+
if let dict = value as? [String: Any] {
|
|
273
|
+
var cleaned: [String: Any] = [:]
|
|
274
|
+
for (k, v) in dict {
|
|
275
|
+
cleaned[k] = unwrapOptional(v)
|
|
276
|
+
}
|
|
277
|
+
return cleaned
|
|
278
|
+
}
|
|
188
279
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
}
|
|
280
|
+
// 5. Enum like SessionSyncStateEnum
|
|
281
|
+
let typeName = String(describing: type(of: value))
|
|
282
|
+
if typeName.contains("InfivizShotSDK.SessionSyncStateEnum") {
|
|
283
|
+
return String(describing: value)
|
|
284
|
+
}
|
|
281
285
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
resolve(success)
|
|
289
|
-
case .failure(let error):
|
|
290
|
-
reject("LOGOUT_FAILED", "Logout error: \(error)", nil)
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
286
|
+
// 6. Date
|
|
287
|
+
if let date = value as? Date {
|
|
288
|
+
let formatter = DateFormatter()
|
|
289
|
+
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
|
|
290
|
+
return formatter.string(from: date)
|
|
291
|
+
}
|
|
294
292
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
306
|
-
}
|
|
293
|
+
// 7. Custom objects
|
|
294
|
+
if !mirror.children.isEmpty {
|
|
295
|
+
var result: [String: Any] = [:]
|
|
296
|
+
for child in mirror.children {
|
|
297
|
+
if let label = child.label {
|
|
298
|
+
result[label] = unwrapOptional(child.value)
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return result
|
|
302
|
+
}
|
|
307
303
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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
|
-
}
|
|
304
|
+
// 8. Primitive
|
|
305
|
+
return value
|
|
306
|
+
}
|
|
320
307
|
|
|
321
|
-
|
|
308
|
+
// MARK: - Logout
|
|
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
|
|
322
348
|
@objc(startCamera:storeTitle:storeId:photoType:category:maxPhoto:maxPhotoOneGo:metaData:resolver:rejecter:)
|
|
323
349
|
func startCamera(_ taskName: NSString,
|
|
324
350
|
storeTitle: NSString,
|
|
@@ -330,229 +356,229 @@ class InfivizShotsReactSdk: RCTEventEmitter {
|
|
|
330
356
|
metaData: NSDictionary,
|
|
331
357
|
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
332
358
|
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
359
|
+
|
|
360
|
+
DispatchQueue.main.async {
|
|
361
|
+
// 1️⃣ Build the CameraContext just like before
|
|
362
|
+
let metadataDict: [String: Any]? = metaData as? [String: Any]
|
|
363
|
+
let context = CameraContext(
|
|
364
|
+
taskName: taskName as String,
|
|
365
|
+
storeTitle: storeTitle as String,
|
|
366
|
+
storeId: storeId as String,
|
|
367
|
+
photoType: photoType as String,
|
|
368
|
+
category: category as String,
|
|
369
|
+
maxPhoto: maxPhoto.intValue,
|
|
370
|
+
maxPhotoOneGo: maxPhotoOneGo.intValue,
|
|
371
|
+
tempSessionId: nil,
|
|
372
|
+
imageURI: nil,
|
|
373
|
+
navigationController: nil,
|
|
374
|
+
retake: false,
|
|
375
|
+
metaData: metadataDict
|
|
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
|
|
350
411
|
)
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
}
|
|
412
|
+
|
|
413
|
+
let environment = APIEnvironment(rawValue: env as String) ?? .production
|
|
414
|
+
InfivizShotsSDK.shared.initializeEnvironent(environment)
|
|
415
|
+
activity = InfivizShotsActivity(model: model)
|
|
416
|
+
activity?.initialize { result in
|
|
417
|
+
switch result {
|
|
418
|
+
case .success(let success):
|
|
419
|
+
resolve(success)
|
|
420
|
+
case .failure(let error):
|
|
421
|
+
reject("LOGIN_FAILED", error.localizedDescription, nil)
|
|
422
|
+
}
|
|
363
423
|
}
|
|
364
|
-
}
|
|
365
424
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// MARK: - View IR Results via bridge
|
|
447
|
+
@objc(viewIRResults:resolver:rejecter:)
|
|
448
|
+
func viewIRResults(_ sessionID: NSString,
|
|
375
449
|
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
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:)
|
|
450
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
451
|
+
DispatchQueue.main.async {
|
|
452
|
+
guard let navigationController = UIApplication.shared.connectedScenes
|
|
453
|
+
.compactMap({ $0 as? UIWindowScene })
|
|
454
|
+
.flatMap({ $0.windows })
|
|
455
|
+
.first(where: { $0.isKeyWindow })?
|
|
456
|
+
.rootViewController?.navigationController else {
|
|
457
|
+
reject("NAV_ERROR", "No navigation controller available", nil)
|
|
458
|
+
return
|
|
459
|
+
}
|
|
460
|
+
let realTimeView = InfivizRealTimeView(sessionID: sessionID as String,
|
|
461
|
+
navigationController: navigationController)
|
|
462
|
+
realTimeView.viewIRResults(sessionID: sessionID as String) { result in
|
|
463
|
+
switch result {
|
|
464
|
+
case .success(let value): resolve(value)
|
|
465
|
+
case .failure(let error): reject("VIEW_IR_FAILED", error.localizedDescription, nil)
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// MARK: - Start Actions Workflow via bridge
|
|
472
|
+
@objc(startActionsWorkFlow:sessionId:latitude:longitude:dateTimeStamp:resolver:rejecter:)
|
|
473
|
+
func startActionsWorkFlow(_ storeId: NSString,
|
|
474
|
+
sessionId: NSString,
|
|
475
|
+
latitude: NSString,
|
|
476
|
+
longitude: NSString,
|
|
477
|
+
dateTimeStamp: NSString,
|
|
478
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
479
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
480
|
+
DispatchQueue.main.async {
|
|
481
|
+
guard let navigationController = UIApplication.shared.connectedScenes
|
|
482
|
+
.compactMap({ $0 as? UIWindowScene })
|
|
483
|
+
.flatMap({ $0.windows })
|
|
484
|
+
.first(where: { $0.isKeyWindow })?
|
|
485
|
+
.rootViewController?.navigationController else {
|
|
486
|
+
reject("NAV_ERROR", "No navigation controller available", nil)
|
|
487
|
+
return
|
|
488
|
+
}
|
|
489
|
+
let realTimeView = InfivizRealTimeView(sessionID: sessionId as String,
|
|
490
|
+
navigationController: navigationController)
|
|
491
|
+
realTimeView.startActionsWorkFlow(storeId: storeId as String,
|
|
492
|
+
sessionId: sessionId as String,
|
|
493
|
+
latitude: latitude as String,
|
|
494
|
+
longitude: longitude as String,
|
|
495
|
+
dateTimeStamp: dateTimeStamp as String) { result in
|
|
496
|
+
switch result {
|
|
497
|
+
case .success(let value): resolve(value)
|
|
498
|
+
case .failure(let error): reject("ACTIONS_WORKFLOW_FAILED", error.localizedDescription, nil)
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
@objc(resumeCamera:metaData:resolver:rejecter:)
|
|
479
505
|
func resumeCamera(
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
506
|
+
_ temporarySessionID: NSString,
|
|
507
|
+
metaData: NSDictionary?,
|
|
508
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
509
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
484
510
|
) {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
511
|
+
// Build whatever CameraContext your SDK needs. In your original UI code,
|
|
512
|
+
// you were reading from text fields (e.g. shelfTextField.text, traderTextField.text, etc.).
|
|
513
|
+
// In a module method you typically won't have those outlets available, so you'll
|
|
514
|
+
// need to pass any required "taskName", "storeTitle" etc. from JS into this call
|
|
515
|
+
// or hard‐code defaults here. For now, I'll show a minimal example:
|
|
516
|
+
|
|
517
|
+
let context = CameraContext(
|
|
518
|
+
taskName: "", // ← pass in from JS if you really need it
|
|
519
|
+
storeTitle: "",
|
|
520
|
+
storeId: "",
|
|
521
|
+
photoType: "",
|
|
522
|
+
category: "",
|
|
523
|
+
maxPhoto: 0,
|
|
524
|
+
maxPhotoOneGo: 0,
|
|
525
|
+
navigationController: nil // ← no UIKit nav controller in RN module
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
// Instantiate your SDK's camera controller just like before:
|
|
529
|
+
let controller = InfilectSDKCameraActivityForResult(cameraContext: context)
|
|
530
|
+
|
|
531
|
+
// Convert NSDictionary to [String: Any]
|
|
532
|
+
let metadataDict: [String: Any]? = metaData as? [String: Any]
|
|
533
|
+
|
|
534
|
+
// Call the updated `resumeCamera(sessionID:metaData:completion:)` API with metadata
|
|
535
|
+
controller.resumeCamera(sessionID: temporarySessionID as String, metaData: metadataDict) { result in
|
|
536
|
+
switch result {
|
|
537
|
+
case .success(let successString):
|
|
538
|
+
// fulfill the JS promise with the returned string
|
|
539
|
+
resolve(successString)
|
|
540
|
+
|
|
541
|
+
case .failure(let sdkError):
|
|
542
|
+
// reject the JS promise
|
|
543
|
+
let nsError = sdkError as NSError
|
|
544
|
+
reject(
|
|
545
|
+
"ResumeCameraError",
|
|
546
|
+
"Failed to resume camera: \(nsError.localizedDescription)",
|
|
547
|
+
nsError
|
|
548
|
+
)
|
|
549
|
+
}
|
|
523
550
|
}
|
|
524
|
-
}
|
|
525
551
|
}
|
|
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
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
556
582
|
@objc(retakeImage:imageURL:metaData:resolver:rejecter:)
|
|
557
583
|
func retakeImage(
|
|
558
584
|
_ temporarySessionId: NSString,
|
|
@@ -593,70 +619,70 @@ class InfivizShotsReactSdk: RCTEventEmitter {
|
|
|
593
619
|
}
|
|
594
620
|
}
|
|
595
621
|
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
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)
|
|
622
|
+
|
|
623
|
+
// MARK: – React Native Promise Exposures for OutputAPI
|
|
624
|
+
/// Expose `getIRResult(sessionID:completion:)` to JavaScript as:
|
|
625
|
+
/// InfiBridge.getIRResult("session-123").then(...).catch(...)
|
|
626
|
+
@objc
|
|
627
|
+
func getIrResult(
|
|
628
|
+
_ sessionId: NSString,
|
|
629
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
630
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
631
|
+
) {
|
|
632
|
+
print("Inside GetIrResult sessionId -> \(sessionId)")
|
|
633
|
+
// Call the Swift helper (which calls outputAPI.getIRResult)
|
|
634
|
+
InfivizShotsSDK.shared.getIrResult(sessionID: sessionId as String) { (dataAny, error) in
|
|
635
|
+
if let err = error {
|
|
636
|
+
// If the SDK returned an error, reject the JS promise
|
|
637
|
+
print("err", err)
|
|
638
|
+
reject(
|
|
639
|
+
"IR_RESULT_ERROR", // error code (custom identifier)
|
|
640
|
+
err as? String, // error message
|
|
641
|
+
nil // optional NSError (can be nil)
|
|
642
|
+
)
|
|
643
|
+
} else if let output = dataAny {
|
|
644
|
+
// If the SDK returned data (Any), pass it back to JS.
|
|
645
|
+
resolve(output)
|
|
646
|
+
} else {
|
|
647
|
+
// Neither data nor error? Just resolve with `nil`.
|
|
648
|
+
resolve(nil)
|
|
649
|
+
}
|
|
653
650
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/// Expose `getActionsResult(sessionID:completion:)` to JavaScript as:
|
|
654
|
+
/// InfiBridge.getActionsResult("session-123").then(...).catch(...)
|
|
655
|
+
@objc
|
|
656
|
+
func getActionsResult(
|
|
657
|
+
_ sessionId: NSString,
|
|
658
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
659
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
660
|
+
) {
|
|
661
|
+
// Call the Swift helper (which calls outputAPI.getActionsResult)
|
|
662
|
+
InfivizShotsSDK.shared.getActionsResult(sessionID: sessionId as String) { (dataAny, error) in
|
|
663
|
+
if let err = error {
|
|
664
|
+
reject("ACTIONS_FAILED", err as? String, nil)
|
|
665
|
+
} else if let output = dataAny {
|
|
666
|
+
resolve(output)
|
|
667
|
+
} else {
|
|
668
|
+
resolve(nil)
|
|
669
|
+
}
|
|
661
670
|
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
@objc
|
|
674
|
+
private func handleActionsGeneratedEvent(_ notification: Notification) {
|
|
675
|
+
guard hasListeners else { return }
|
|
676
|
+
|
|
677
|
+
let payload = notification.userInfo ?? [:]
|
|
678
|
+
sendEvent(withName: "ActionsGeneratedEvent", body: payload)
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
@objc
|
|
682
|
+
private func handleSessionRealTimeResultEvent(_ notification: Notification) {
|
|
683
|
+
guard hasListeners else { return }
|
|
684
|
+
|
|
685
|
+
let payload = notification.userInfo ?? [:]
|
|
686
|
+
sendEvent(withName: "SessionRealTimeResultEvent", body: payload)
|
|
687
|
+
}
|
|
662
688
|
}
|