@flybits/react-native-concierge 0.0.0 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +75 -0
- package/android/build.gradle +102 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/concierge/AuthModule.kt +104 -0
- package/android/src/main/java/com/concierge/ConciergePackage.kt +19 -0
- package/android/src/main/java/com/concierge/ConciergeViewManager.kt +280 -0
- package/android/src/main/java/com/concierge/FlybitsModule.kt +460 -0
- package/android/src/main/java/com/concierge/UtilityHelper.kt +57 -0
- package/ios/Concierge-Bridging-Header.h +1 -0
- package/ios/ConciergeViewManager.m +40 -0
- package/ios/ConciergeViewManager.swift +158 -0
- package/ios/FlybitsModuleSwift.swift +489 -0
- package/lib/commonjs/index.js +260 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/index.js +259 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +41 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/index.d.ts +41 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/package.json +189 -8
- package/react-native-concierge.podspec +48 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
|
|
2
|
+
import React
|
|
3
|
+
import FlybitsConcierge
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@objc(ConciergeViewManager)
|
|
7
|
+
class ConciergeViewManager: RCTViewManager {
|
|
8
|
+
|
|
9
|
+
override func view() -> (ConciergeView) {
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
return ConciergeView()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@objc override static func requiresMainQueueSetup() -> Bool {
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class ConciergeView : UIView {
|
|
22
|
+
|
|
23
|
+
var fb: UIViewController?
|
|
24
|
+
@objc var onConciergeChange: RCTBubblingEventBlock?
|
|
25
|
+
@objc var zoneReferenceIDs: Array<String>?
|
|
26
|
+
|
|
27
|
+
@objc var actionlink: Dictionary<String, Any>?
|
|
28
|
+
|
|
29
|
+
@objc var onActionEvent: RCTBubblingEventBlock?
|
|
30
|
+
@objc var onAnalyticsEvent: RCTBubblingEventBlock?
|
|
31
|
+
@objc var onContentArrived: RCTBubblingEventBlock?
|
|
32
|
+
|
|
33
|
+
deinit {
|
|
34
|
+
fb?.view.removeFromSuperview()
|
|
35
|
+
fb?.removeFromParent()
|
|
36
|
+
fb?.didMove(toParent: nil)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override func didMoveToSuperview() {
|
|
40
|
+
super.didMoveToSuperview()
|
|
41
|
+
|
|
42
|
+
var delegate: AnyConciergeEventsDelegate<ConciergeEventsDelegate>?
|
|
43
|
+
|
|
44
|
+
let cDelegate = ConciergeViewManagerConciergeDelegate()
|
|
45
|
+
delegate = Concierge.delegate(from: cDelegate)
|
|
46
|
+
|
|
47
|
+
var urlComponent = URLComponents()
|
|
48
|
+
|
|
49
|
+
if let actionlink = actionlink {
|
|
50
|
+
for (key, value) in actionlink {
|
|
51
|
+
switch key {
|
|
52
|
+
case "action": urlComponent.scheme = value as? String ?? "concierge://"
|
|
53
|
+
case "params":
|
|
54
|
+
guard let value = value as? Dictionary<String, Any> else { return }
|
|
55
|
+
|
|
56
|
+
var queryItems = [URLQueryItem]()
|
|
57
|
+
for (key, value) in value {
|
|
58
|
+
let queryItem = URLQueryItem(name: key, value: value as? String)
|
|
59
|
+
queryItems.append(queryItem)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
urlComponent.queryItems = queryItems
|
|
63
|
+
|
|
64
|
+
default:
|
|
65
|
+
break
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
var concierge: UIViewController!
|
|
71
|
+
|
|
72
|
+
if let url = urlComponent.url {
|
|
73
|
+
concierge = Concierge.handleActionableLink(url, with: [], requestEvents: delegate) ?? Concierge.viewController(.configured, params: [], options: [])
|
|
74
|
+
} else {
|
|
75
|
+
concierge = Concierge.viewController(.configured, params: [], options: [])
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
self.addSubview(concierge.view)
|
|
80
|
+
|
|
81
|
+
concierge.view.translatesAutoresizingMaskIntoConstraints = false
|
|
82
|
+
|
|
83
|
+
concierge.view.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
|
|
84
|
+
concierge.view.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor).isActive = true
|
|
85
|
+
concierge.view.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
|
|
86
|
+
concierge.view.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
|
|
87
|
+
|
|
88
|
+
self.fb = concierge
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
class ConciergeViewManagerConciergeDelegate: ConciergeEventsDelegate {
|
|
94
|
+
|
|
95
|
+
func conciergeWillDisplayContent(_ hasContent: Bool, identifier: String) {
|
|
96
|
+
let emitter = ConciergeViewManagerEvents.shared
|
|
97
|
+
if((emitter?.hasListeners) != nil) {
|
|
98
|
+
emitter?.sendEvent(withName: "Concierge-Event", body: ["body": ["type": "conciergeContentFetch", "hasContent": hasContent, "identifier": identifier]])
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
func event(_ actionlink: URL, identifier: String) {
|
|
103
|
+
guard let components = URLComponents(url: actionlink, resolvingAgainstBaseURL: false) else { return }
|
|
104
|
+
|
|
105
|
+
var scheme = "concierge"
|
|
106
|
+
if var tmp = components.scheme {
|
|
107
|
+
scheme = tmp.last == ":" ? String(tmp.remove(at: tmp.index(before: tmp.endIndex))) : tmp
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let emitter = ConciergeViewManagerEvents.shared
|
|
111
|
+
if((emitter?.hasListeners) != nil) {
|
|
112
|
+
emitter?.sendEvent(withName: "Concierge-Event", body: ["body": ["type": "conciergeAction", "actionableLink": ["action": scheme, "params":components.queryItems?.reduce([:], { partialResult, queryItem in
|
|
113
|
+
var newResult = partialResult
|
|
114
|
+
newResult[queryItem.name] = queryItem.value
|
|
115
|
+
return newResult
|
|
116
|
+
}) ?? [:] ], "identifier": identifier]])
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
func analyticsEvent(_ exportedAnalyticsEvent: ExportedAnalyticsEvent, identifier: String) {
|
|
121
|
+
let emitter = ConciergeViewManagerEvents.shared
|
|
122
|
+
if((emitter?.hasListeners) != nil) {
|
|
123
|
+
emitter?.sendEvent(withName: "Concierge-Event", body: ["body": ["type": "conciergeAnalytics", "analyticsType": exportedAnalyticsEvent.type, "contentData": exportedAnalyticsEvent.contentData ?? [:], "contentInfo": exportedAnalyticsEvent.contentInfo]])
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@objc(ConciergeView)
|
|
129
|
+
class ConciergeViewManagerEvents: RCTEventEmitter {
|
|
130
|
+
public static var shared: ConciergeViewManagerEvents?
|
|
131
|
+
var hasListeners: Bool = false
|
|
132
|
+
|
|
133
|
+
override init() {
|
|
134
|
+
super.init()
|
|
135
|
+
ConciergeViewManagerEvents.shared = self
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
deinit {
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@objc(supportedEvents)
|
|
142
|
+
override func supportedEvents() -> [String]! {
|
|
143
|
+
return [
|
|
144
|
+
"Concierge-Event"
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
@objc(startObserving)
|
|
148
|
+
override func startObserving() {
|
|
149
|
+
super.startObserving()
|
|
150
|
+
hasListeners = true
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@objc(stopObserving)
|
|
154
|
+
override func stopObserving() {
|
|
155
|
+
super.stopObserving()
|
|
156
|
+
hasListeners = false
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
import FlybitsConcierge
|
|
2
|
+
import FlybitsContextSDK
|
|
3
|
+
import FlybitsCoreConcierge
|
|
4
|
+
import FlybitsSDK
|
|
5
|
+
import React
|
|
6
|
+
|
|
7
|
+
struct ErrorDetails: Codable {
|
|
8
|
+
let code: Int
|
|
9
|
+
let description: String
|
|
10
|
+
let action: String
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
struct ResultItem: Codable {
|
|
14
|
+
let errorCode: Int
|
|
15
|
+
let details: ErrorDetails
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@objc(FlybitsModule)
|
|
19
|
+
class FlybitsModuleSwift: NSObject {
|
|
20
|
+
var pushNetwork: ConciergePushNetwork = .fcm
|
|
21
|
+
|
|
22
|
+
static let UndefinedError = -1
|
|
23
|
+
static let InvalidFormatError = -2
|
|
24
|
+
|
|
25
|
+
@objc(configureFlybits:resolved:rejected:)
|
|
26
|
+
func configureFlybits(configuration: [String: Any],
|
|
27
|
+
resolved: @escaping RCTPromiseResolveBlock,
|
|
28
|
+
rejected: @escaping RCTPromiseRejectBlock) {
|
|
29
|
+
|
|
30
|
+
DispatchQueue.main.sync {
|
|
31
|
+
|
|
32
|
+
var contextPlugins = [ContextManager.PluginItem]()
|
|
33
|
+
var locales = [Locale]()
|
|
34
|
+
|
|
35
|
+
guard
|
|
36
|
+
let projectId = configuration["projectId"] as? String,
|
|
37
|
+
let gateway = configuration["gateway"] as? String,
|
|
38
|
+
let configPushNetwork = configuration["pushNetwork"] as? String,
|
|
39
|
+
!projectId.isEmpty,
|
|
40
|
+
!gateway.isEmpty,
|
|
41
|
+
!configPushNetwork.isEmpty
|
|
42
|
+
else {
|
|
43
|
+
let error = NSError(domain: "com.flybits",
|
|
44
|
+
code: 1,
|
|
45
|
+
userInfo: ["description": "Not enough information provided to configure Concierge. Please, provide the project Identifier, the gateway, the push network."])
|
|
46
|
+
rejected(error.localizedDescription, "\(error.code)", error)
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
pushNetwork = ConciergePushNetwork.convertToObj(configPushNetwork.lowercased())
|
|
51
|
+
|
|
52
|
+
var config = FlybitsConciergeConfiguration.Builder()
|
|
53
|
+
.setProjectId(projectId)
|
|
54
|
+
.setGatewayUrl(gateway)
|
|
55
|
+
.setPushNetwork(pushNetwork)
|
|
56
|
+
.setWebService(configuration["webService"] as? String ?? "https://static-files-concierge.demo.flybits.com/latest")
|
|
57
|
+
|
|
58
|
+
if let webPoolSize = configuration["webPoolSize"] as? Int {
|
|
59
|
+
config = config.setWebviewPoolingSize(webPoolSize)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if let _ = configuration["locationPlugin"] {
|
|
63
|
+
contextPlugins.append(.location)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if let _ = configuration["setAutoRegisterForLocation"] {
|
|
67
|
+
config = config.setAutoRegisterForLocation(true)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if let value = configuration["timeToRefreshInterval"] as? Int {
|
|
71
|
+
config = config.setTimeToRefreshInterval(value)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if let value = configuration["timeToRefreshNoDataInterval"] as? Int {
|
|
75
|
+
config = config.setTimeToRefreshInterval(value)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if let locales = configuration["locales"] as? String,
|
|
79
|
+
let decoded = try? JSONDecoder().decode(Array<String>.self, from: Data(locales.utf8))
|
|
80
|
+
{
|
|
81
|
+
for locale in decoded {
|
|
82
|
+
let newLocale = Locale(identifier: locale)
|
|
83
|
+
locales.append(newLocale)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
Concierge.configure(configuration: config.build(),
|
|
88
|
+
contextPlugins: contextPlugins,
|
|
89
|
+
customLanguages: locales)
|
|
90
|
+
|
|
91
|
+
if let logging = configuration["logLevel"] as? String, let level = logLevel(logLevel: logging) {
|
|
92
|
+
Concierge.enableLogging(forLevel: level)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
FlybitsModuleSwift.completionHandler(with: nil, resolved: resolved, rejected: rejected)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@objc(anonymousConnect:rejected:)
|
|
100
|
+
func anonymousConnect(
|
|
101
|
+
resolved: @escaping RCTPromiseResolveBlock, rejected: @escaping RCTPromiseRejectBlock
|
|
102
|
+
) {
|
|
103
|
+
Concierge.connect(with: AnonymousConciergeIDP()) { error in
|
|
104
|
+
FlybitsModuleSwift.completionHandler(with: error, resolved: resolved, rejected: rejected)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@objc(authenticateJwtSignIn:resolved:rejected:)
|
|
109
|
+
func authenticateJwtSignIn(
|
|
110
|
+
jwt: String, resolved: @escaping RCTPromiseResolveBlock,
|
|
111
|
+
rejected: @escaping RCTPromiseRejectBlock
|
|
112
|
+
) {
|
|
113
|
+
Concierge.connect(with: JwtLoginConciergeIDP(jwtLoginToken: jwt)) { error in
|
|
114
|
+
FlybitsModuleSwift.completionHandler(with: error, resolved: resolved, rejected: rejected)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@objc(disconnect:rejected:)
|
|
119
|
+
func disconnect(
|
|
120
|
+
resolved: @escaping RCTPromiseResolveBlock, rejected: @escaping RCTPromiseRejectBlock
|
|
121
|
+
) {
|
|
122
|
+
Concierge.disconnect { error in
|
|
123
|
+
FlybitsModuleSwift.completionHandler(with: error, resolved: resolved, rejected: rejected)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@objc(isConnected:rejected:)
|
|
128
|
+
func isConnected(resolved: RCTPromiseResolveBlock, rejected: RCTPromiseRejectBlock) {
|
|
129
|
+
if Concierge.isConnected {
|
|
130
|
+
FlybitsModuleSwift.completionHandler(with: nil, successInput: "true", resolved: resolved, rejected: rejected)
|
|
131
|
+
} else {
|
|
132
|
+
FlybitsModuleSwift.completionHandler(with: nil, successInput: "false", resolved: resolved, rejected: rejected)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@objc(actionlink:resolved:rejected:)
|
|
137
|
+
func actionlink(userInfo: [String: Any],
|
|
138
|
+
resolved: @escaping RCTPromiseResolveBlock,
|
|
139
|
+
rejected: @escaping RCTPromiseRejectBlock
|
|
140
|
+
) {
|
|
141
|
+
if let data = userInfo["data"] as? [String: Any], let push = Concierge.handlePush(data) {
|
|
142
|
+
let value: String = Concierge.actionableLink(from: push).absoluteString
|
|
143
|
+
FlybitsModuleSwift.completionHandler(with: nil, successInput: value, resolved: resolved, rejected: rejected)
|
|
144
|
+
} else {
|
|
145
|
+
let error = NSError(domain: "com.flybits",
|
|
146
|
+
code: 2,
|
|
147
|
+
userInfo: ["description": "Provided userInfo can NOT be converted into ConciergePush object."])
|
|
148
|
+
FlybitsModuleSwift.completionHandler(with: error, resolved: resolved, rejected: rejected)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@objc(actionTypeSchemeParser:resolved:rejected:)
|
|
153
|
+
func actionTypeSchemeParser(actionableLink: String,
|
|
154
|
+
resolved: @escaping RCTPromiseResolveBlock,
|
|
155
|
+
rejected: @escaping RCTPromiseRejectBlock
|
|
156
|
+
) {
|
|
157
|
+
let successDictionary = FlybitsModuleSwift.fromSuccessArray(actionableLink)
|
|
158
|
+
|
|
159
|
+
guard let realActionableLink: String = successDictionary["result"] as? String else {
|
|
160
|
+
let error = NSError(domain: "com.flybits",
|
|
161
|
+
code: 3,
|
|
162
|
+
userInfo: ["description": "Not possible to parse the provided actionableLink"])
|
|
163
|
+
FlybitsModuleSwift.completionHandler(with: error, resolved: resolved, rejected: rejected)
|
|
164
|
+
return
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
let actionScheme = ActionTypeSchemeParser.parse(realActionableLink)
|
|
168
|
+
let actionableLinkDict: [String: Any] = [
|
|
169
|
+
"actionTypeIntent": actionScheme.intent.toString(),
|
|
170
|
+
"data": actionScheme.data,
|
|
171
|
+
]
|
|
172
|
+
|
|
173
|
+
do {
|
|
174
|
+
let jsonData = try JSONSerialization.data(withJSONObject: actionableLinkDict, options: [])
|
|
175
|
+
|
|
176
|
+
if let jsonString = String(data: jsonData, encoding: .utf8) {
|
|
177
|
+
FlybitsModuleSwift.completionHandler(with: nil, successInput: jsonString, resolved: resolved, rejected: rejected)
|
|
178
|
+
} else {
|
|
179
|
+
let error = NSError(domain: "com.flybits",
|
|
180
|
+
code: 4,
|
|
181
|
+
userInfo: ["description": "Not possible to parse the provided actionableLink"])
|
|
182
|
+
FlybitsModuleSwift.completionHandler(with: error, resolved: resolved, rejected: rejected)
|
|
183
|
+
}
|
|
184
|
+
} catch {
|
|
185
|
+
rejected(error.localizedDescription, "\((error as NSError).code)", error)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
func extractActionableLink(from input: [String: Any]) -> String {
|
|
190
|
+
guard
|
|
191
|
+
let detailsDict = input["details"] as? [String: Any],
|
|
192
|
+
let descriptionString = detailsDict["description"] as? String
|
|
193
|
+
else {
|
|
194
|
+
return ""
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return descriptionString
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@objc(isFlybitsPush:resolved:rejected:)
|
|
201
|
+
func isFlybitsPush(notification: NSDictionary,
|
|
202
|
+
resolved: @escaping RCTPromiseResolveBlock,
|
|
203
|
+
rejected: @escaping RCTPromiseRejectBlock
|
|
204
|
+
) {
|
|
205
|
+
var notificationDict = notification
|
|
206
|
+
|
|
207
|
+
if case .fcm = pushNetwork {
|
|
208
|
+
|
|
209
|
+
if let firstLayer = notification["data"] as? [String: String],
|
|
210
|
+
let base64String = firstLayer["data"],
|
|
211
|
+
let decodedData = Data(base64Encoded: base64String),
|
|
212
|
+
let jsonObject = try? JSONSerialization.jsonObject(with: decodedData, options: []),
|
|
213
|
+
let dict = jsonObject as? NSDictionary
|
|
214
|
+
{
|
|
215
|
+
notificationDict = dict
|
|
216
|
+
} else {
|
|
217
|
+
let error = NSError(domain: "com.flybits",
|
|
218
|
+
code: FlybitsModuleSwift.InvalidFormatError,
|
|
219
|
+
userInfo: ["description": "Invalid FCM Push notification body. The Flybits slice should be inside the root/data key"])
|
|
220
|
+
FlybitsModuleSwift.completionHandler(with: error, resolved: resolved, rejected: rejected)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if let provider = notificationDict["provider"] as? String, provider.lowercased() == "flybits" {
|
|
225
|
+
FlybitsModuleSwift.completionHandler(with: nil, successInput: "true", resolved: resolved, rejected: rejected)
|
|
226
|
+
} else {
|
|
227
|
+
FlybitsModuleSwift.completionHandler(with: nil, successInput: "false", resolved: resolved, rejected: rejected)
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@objc(notificationStatus:rejected:)
|
|
232
|
+
func notificationStatus(
|
|
233
|
+
resolved: @escaping RCTPromiseResolveBlock, rejected: @escaping RCTPromiseRejectBlock
|
|
234
|
+
) {
|
|
235
|
+
|
|
236
|
+
switch Concierge.pushTokenUploadStatus() {
|
|
237
|
+
case .unknown:
|
|
238
|
+
FlybitsModuleSwift.completionHandler(with: nil, successInput: "unknown", resolved: resolved, rejected: rejected)
|
|
239
|
+
case .deleted:
|
|
240
|
+
FlybitsModuleSwift.completionHandler(with: nil, successInput: "deleted", resolved: resolved, rejected: rejected)
|
|
241
|
+
case .sent:
|
|
242
|
+
FlybitsModuleSwift.completionHandler(with: nil, successInput: "sent", resolved: resolved, rejected: rejected)
|
|
243
|
+
default:
|
|
244
|
+
FlybitsModuleSwift.completionHandler(with: nil, successInput: "unknown", resolved: resolved, rejected: rejected)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
@objc(addToken:resolved:rejected:)
|
|
249
|
+
func addToken(
|
|
250
|
+
token: String, resolved: @escaping RCTPromiseResolveBlock,
|
|
251
|
+
rejected: @escaping RCTPromiseRejectBlock
|
|
252
|
+
) {
|
|
253
|
+
if let data = token.data(using: .utf8) {
|
|
254
|
+
Concierge.sendPush(token: data)
|
|
255
|
+
FlybitsModuleSwift.completionHandler(with: nil, resolved: resolved, rejected: rejected)
|
|
256
|
+
} else {
|
|
257
|
+
let error = NSError(domain: "com.flybits",
|
|
258
|
+
code: 5,
|
|
259
|
+
userInfo: ["description": "Token not convertable to data"])
|
|
260
|
+
FlybitsModuleSwift.completionHandler(with: error, resolved: resolved, rejected: rejected)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@objc(removeToken:rejected:)
|
|
265
|
+
func removeToken(
|
|
266
|
+
resolved: @escaping RCTPromiseResolveBlock, rejected: @escaping RCTPromiseRejectBlock
|
|
267
|
+
) {
|
|
268
|
+
Concierge.deletePushToken { error in
|
|
269
|
+
FlybitsModuleSwift.completionHandler(with: error, resolved: resolved, rejected: rejected)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private func logLevel(logLevel: String?) -> ConciergeLoggerLevel? {
|
|
274
|
+
guard let logLevel = logLevel else {
|
|
275
|
+
return nil
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
switch logLevel.lowercased() {
|
|
279
|
+
case "debug":
|
|
280
|
+
return .debug
|
|
281
|
+
default:
|
|
282
|
+
return .none
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private static func convertToSuccessJSON(_ input: String) -> String {
|
|
287
|
+
let inputDictionary: [String: Any] = ["success": true, "result": input]
|
|
288
|
+
|
|
289
|
+
return convertToJSON(inputDictionary)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
private static func convertToErrorJSON(_ input: NSError) -> String {
|
|
293
|
+
let inputDictionary: [String: Any] = ["success": false, "code": input.code, "message": input.localizedDescription]
|
|
294
|
+
|
|
295
|
+
return convertToJSON(inputDictionary)
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
private static func convertToErrorJSON(_ input: String) -> String {
|
|
299
|
+
let error = NSError(
|
|
300
|
+
domain: "com.flybits",
|
|
301
|
+
code: FlybitsModuleSwift.UndefinedError,
|
|
302
|
+
userInfo: ["description": input])
|
|
303
|
+
return convertToErrorJSON(error)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private static func convertToJSON(_ input: [String: Any]) -> String {
|
|
307
|
+
do {
|
|
308
|
+
let jsonData = try JSONSerialization.data(withJSONObject: input, options: [])
|
|
309
|
+
|
|
310
|
+
if let jsonString = String(data: jsonData, encoding: .utf8) {
|
|
311
|
+
return jsonString
|
|
312
|
+
} else {
|
|
313
|
+
return ""
|
|
314
|
+
}
|
|
315
|
+
} catch {
|
|
316
|
+
return ""
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
private static func completionHandler(with error: NSError?, successInput: String = "ok", resolved: RCTPromiseResolveBlock, rejected: RCTPromiseRejectBlock) {
|
|
321
|
+
if let error = error {
|
|
322
|
+
let errorJSON = FlybitsModuleSwift.convertToErrorJSON(error)
|
|
323
|
+
|
|
324
|
+
if errorJSON.isEmpty {
|
|
325
|
+
rejected(error.code.description, error.localizedDescription, error)
|
|
326
|
+
} else {
|
|
327
|
+
resolved(errorJSON)
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
let successJSON = convertToSuccessJSON(successInput)
|
|
331
|
+
|
|
332
|
+
if successJSON.isEmpty {
|
|
333
|
+
let error = NSError(
|
|
334
|
+
domain: "com.flybits",
|
|
335
|
+
code: FlybitsModuleSwift.UndefinedError,
|
|
336
|
+
userInfo: ["description": "Supposedly success scenario but JSON parsing failed."])
|
|
337
|
+
rejected(error.code.description, error.localizedDescription, error)
|
|
338
|
+
} else {
|
|
339
|
+
resolved(successJSON)
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
private static func fromSuccessArray(_ jsonInput: String) -> [String: Any] {
|
|
345
|
+
guard let data = jsonInput.data(using: .utf8) else {
|
|
346
|
+
return [String: Any]()
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
do {
|
|
350
|
+
if let dict = try JSONSerialization.jsonObject(with: data, options: [])
|
|
351
|
+
as? [String: Any]
|
|
352
|
+
{
|
|
353
|
+
return dict
|
|
354
|
+
}
|
|
355
|
+
} catch {
|
|
356
|
+
}
|
|
357
|
+
return [String: Any]()
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
@objc(Auth)
|
|
362
|
+
class ConciergeViewManagerAuth: RCTEventEmitter, FlybitsScope {
|
|
363
|
+
|
|
364
|
+
var hasListeners: Bool = false
|
|
365
|
+
|
|
366
|
+
override init() {
|
|
367
|
+
super.init()
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
deinit {
|
|
371
|
+
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
@objc(supportedEvents)
|
|
375
|
+
override func supportedEvents() -> [String]! {
|
|
376
|
+
return [
|
|
377
|
+
"Authentication-onStart"
|
|
378
|
+
]
|
|
379
|
+
}
|
|
380
|
+
@objc(startObserving)
|
|
381
|
+
override func startObserving() {
|
|
382
|
+
super.startObserving()
|
|
383
|
+
hasListeners = true
|
|
384
|
+
FlybitsManager.add(
|
|
385
|
+
scope: self, forkey: "ConciergeViewManagerAuth+\(ObjectIdentifier(self))")
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
@objc(stopObserving)
|
|
389
|
+
override func stopObserving() {
|
|
390
|
+
super.stopObserving()
|
|
391
|
+
FlybitsManager.removeScope(forKey: "ConciergeViewManagerAuth+\(ObjectIdentifier(self))")
|
|
392
|
+
hasListeners = false
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
func onStart(currentActiveUserIsOptedIn: Bool, authState: FlybitsSDK.ScopeAuthState) {
|
|
396
|
+
if hasListeners {
|
|
397
|
+
self.sendEvent(
|
|
398
|
+
withName: "Authentication-onStart",
|
|
399
|
+
body: ["body": ["authState": scopeAuthStateAsString(authState)]])
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
func onStop() {
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
func onConnected(user: FlybitsSDK.FlybitsUser) {
|
|
407
|
+
if hasListeners {
|
|
408
|
+
self.sendEvent(
|
|
409
|
+
withName: "Authentication-onStart",
|
|
410
|
+
body: ["body": ["authState": scopeAuthStateAsString(.connected)]])
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
func onDisconnected() {
|
|
415
|
+
if hasListeners {
|
|
416
|
+
self.sendEvent(
|
|
417
|
+
withName: "Authentication-onStart",
|
|
418
|
+
body: ["body": ["authState": scopeAuthStateAsString(.disconnected)]])
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
func onOptIn() {
|
|
423
|
+
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
func onOptOut() {
|
|
427
|
+
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
var identifier: String = ""
|
|
431
|
+
|
|
432
|
+
private func scopeAuthStateAsString(_ authState: FlybitsSDK.ScopeAuthState) -> String {
|
|
433
|
+
switch authState {
|
|
434
|
+
case .connected: return "connected"
|
|
435
|
+
case .connectedOptOut: return "connectedOptOut"
|
|
436
|
+
case .connecting: return "connecting"
|
|
437
|
+
case .disconnected: return "disconnected"
|
|
438
|
+
default: return "unknown"
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
extension ActionTypeIntent {
|
|
445
|
+
func toString() -> String {
|
|
446
|
+
let result: String
|
|
447
|
+
switch self {
|
|
448
|
+
case .unknown:
|
|
449
|
+
result = "unknown"
|
|
450
|
+
case .concierge:
|
|
451
|
+
result = "concierge"
|
|
452
|
+
case .web:
|
|
453
|
+
result = "web"
|
|
454
|
+
case .browser:
|
|
455
|
+
result = "browser"
|
|
456
|
+
case .universalLink:
|
|
457
|
+
result = "universalLink"
|
|
458
|
+
case .mail:
|
|
459
|
+
result = "mail"
|
|
460
|
+
case .phone:
|
|
461
|
+
result = "phone"
|
|
462
|
+
case .app:
|
|
463
|
+
result = "app"
|
|
464
|
+
case .details:
|
|
465
|
+
result = "details"
|
|
466
|
+
case .settings:
|
|
467
|
+
result = "settings"
|
|
468
|
+
case .optIn:
|
|
469
|
+
result = "optIn"
|
|
470
|
+
@unknown default:
|
|
471
|
+
result = "notMapped"
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return result
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
extension ConciergePushNetwork {
|
|
479
|
+
static func convertToObj(_ str: String) -> ConciergePushNetwork {
|
|
480
|
+
switch(str.lowercased()) {
|
|
481
|
+
case "fcm":
|
|
482
|
+
return ConciergePushNetwork.fcm
|
|
483
|
+
case "apns":
|
|
484
|
+
return ConciergePushNetwork.apns
|
|
485
|
+
default:
|
|
486
|
+
return ConciergePushNetwork.apns
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|