@dashx/react-native 0.1.11 → 0.1.14

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.
@@ -97,8 +97,12 @@ dependencies {
97
97
 
98
98
  implementation 'com.google.code.gson:gson:2.8.6'
99
99
 
100
- compileOnly 'com.google.firebase:firebase-core:17.2.1'
101
- compileOnly 'com.google.firebase:firebase-messaging:20.0.1'
100
+ // Import the Firebase BoM (see: https://firebase.google.com/docs/android/learn-more#bom)
101
+ implementation platform('com.google.firebase:firebase-bom:28.3.0')
102
+ implementation 'com.google.firebase:firebase-messaging-ktx'
103
+
104
+ // The Firebase SDK for Google Analytics is needed for delivery reports
105
+ implementation 'com.google.firebase:firebase-analytics-ktx'
102
106
  }
103
107
 
104
108
  def configureReactNativePom(def pom) {
@@ -2,9 +2,9 @@
2
2
  package="com.dashx.rn.sdk">
3
3
 
4
4
  <application>
5
- <service android:name="com.dashx.rn.sdk.DashXMessagingService">
6
- <intent-filter android:priority="1">
7
- <action android:name="com.google.firebase.MESSAGING_EVENT"/>
5
+ <service android:name=".DashXMessagingService" android:exported="false">
6
+ <intent-filter>
7
+ <action android:name="com.google.firebase.MESSAGING_EVENT" />
8
8
  </intent-filter>
9
9
  </service>
10
10
  </application>
@@ -12,7 +12,7 @@ class DashXActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks {
12
12
  private var startSession = System.currentTimeMillis().toDouble()
13
13
 
14
14
  init {
15
- dashXClient.trackAppStarted()
15
+ dashXClient?.trackAppStarted()
16
16
  }
17
17
 
18
18
  override fun onActivityPaused(activity: Activity) {
@@ -20,7 +20,7 @@ class DashXActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks {
20
20
  return
21
21
  }
22
22
 
23
- dashXClient.trackAppSession(System.currentTimeMillis().toDouble() - startSession)
23
+ dashXClient?.trackAppSession(System.currentTimeMillis().toDouble() - startSession)
24
24
  }
25
25
 
26
26
  override fun onActivityResumed(activity: Activity) {
@@ -29,7 +29,7 @@ class DashXActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks {
29
29
  }
30
30
 
31
31
  startSession = System.currentTimeMillis().toDouble()
32
- dashXClient.trackAppStarted(fromBackground = true)
32
+ dashXClient?.trackAppStarted(fromBackground = true)
33
33
  }
34
34
 
35
35
  override fun onActivityStarted(activity: Activity) {
@@ -37,10 +37,10 @@ class DashXActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks {
37
37
  return
38
38
  }
39
39
 
40
- val packageManager = activity?.packageManager
40
+ val packageManager = activity.packageManager
41
41
  val info = packageManager?.getActivityInfo(activity.componentName, PackageManager.GET_META_DATA)
42
42
  val activityLabel = info?.loadLabel(packageManager)
43
- activityLabel?.let { it -> dashXClient.screen(it.toString(), hashMapOf()) }
43
+ activityLabel?.let { it -> dashXClient?.screen(it.toString(), hashMapOf()) }
44
44
  }
45
45
 
46
46
  override fun onActivityDestroyed(activity: Activity) {
@@ -16,35 +16,37 @@ class DashXClientInterceptor private constructor() {
16
16
 
17
17
  fun createDashXClient(reactApplicationContext: ReactApplicationContext, publicKey: String, baseURI: String?, targetEnvironment: String?, targetInstallation: String?) {
18
18
  this.reactApplicationContext = reactApplicationContext
19
- client = DashX(reactApplicationContext.applicationContext, publicKey!!, baseURI, targetEnvironment, targetInstallation)
19
+ client = DashX(reactApplicationContext.applicationContext, publicKey, baseURI, targetEnvironment, targetInstallation)
20
20
  }
21
21
 
22
- fun getDashXClient(): com.dashx.sdk.DashXClient {
23
- if (client == null) {
24
- throw Exception("DashXClient not initialised")
25
- }
26
-
27
- return client!!
22
+ fun getDashXClient(): com.dashx.sdk.DashXClient? {
23
+ return client
28
24
  }
29
25
 
30
26
  fun handleMessage(remoteMessage: RemoteMessage) {
31
- val notification = remoteMessage.notification
27
+ val notificationData = remoteMessage.getData()
28
+
29
+ DashXLog.d(tag, "Notification Data: " + notificationData)
30
+
32
31
  val eventProperties: WritableMap = Arguments.createMap()
33
- DashXLog.d(tag, "Data: " + remoteMessage.data)
34
32
 
35
33
  try {
36
- eventProperties.putMap("data", convertToWritableMap(remoteMessage.data, listOf(dashXNotificationFilter)))
34
+ eventProperties.putMap("data", convertToWritableMap(notificationData, listOf(dashXNotificationFilter)))
37
35
  } catch (e: Exception) {
38
- DashXLog.d(tag, "Encountered an error while parsing notification data")
39
36
  e.printStackTrace()
37
+ DashXLog.d(tag, "Encountered an error while parsing notification data.")
40
38
  }
41
39
 
40
+ val notification = remoteMessage.getNotification()
41
+
42
42
  if (notification != null) {
43
43
  val notificationProperties: WritableMap = Arguments.createMap()
44
- notificationProperties.putString("title", notification.title)
45
- notificationProperties.putString("body", notification.body)
44
+ notificationProperties.putString("title", notification.getTitle())
45
+ notificationProperties.putString("body", notification.getBody())
46
+
46
47
  eventProperties.putMap("notification", notificationProperties)
47
- DashXLog.d(tag, "onMessageReceived: " + notification.title)
48
+
49
+ DashXLog.d(tag, "onMessageReceived with Title: " + notification.getTitle() + " and Body: " + notification.getBody())
48
50
  }
49
51
 
50
52
  sendJsEvent("messageReceived", eventProperties)
@@ -11,13 +11,18 @@ class DashXExceptionHandler(private val mainExceptionHandler: Thread.UncaughtExc
11
11
  return
12
12
  }
13
13
 
14
- val dashXExceptionHandler = DashXExceptionHandler(defaultExceptionHandler)
15
- Thread.setDefaultUncaughtExceptionHandler(dashXExceptionHandler)
14
+ if (defaultExceptionHandler != null) {
15
+ val dashXExceptionHandler = DashXExceptionHandler(defaultExceptionHandler)
16
+ Thread.setDefaultUncaughtExceptionHandler(dashXExceptionHandler)
17
+ }
16
18
  }
17
19
  }
18
20
 
19
21
  override fun uncaughtException(thread: Thread, exception: Throwable) {
20
- dashXClient.trackAppCrashed(exception)
22
+ if (dashXClient != null) {
23
+ dashXClient.trackAppCrashed(exception)
24
+ }
25
+
21
26
  mainExceptionHandler.uncaughtException(thread, exception)
22
27
  }
23
28
  }
@@ -10,8 +10,11 @@ class DashXMessagingService : FirebaseMessagingService() {
10
10
 
11
11
  override fun onNewToken(token: String) {
12
12
  super.onNewToken(token)
13
- dashXClient.setDeviceToken(token)
14
13
  DashXLog.d(tag, "onNewToken: $token")
14
+
15
+ if (dashXClient != null) {
16
+ dashXClient.setDeviceToken(token)
17
+ }
15
18
  }
16
19
 
17
20
  override fun onMessageReceived(remoteMessage: RemoteMessage) {
@@ -3,7 +3,7 @@ package com.dashx.rn.sdk
3
3
  import com.facebook.react.bridge.*
4
4
  import com.dashx.sdk.DashXLog
5
5
  import com.google.android.gms.tasks.OnCompleteListener
6
- import com.google.firebase.iid.FirebaseInstanceId
6
+ import com.google.firebase.messaging.FirebaseMessaging
7
7
 
8
8
  class DashXModule(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
9
9
  private val tag = DashXModule::class.java.simpleName
@@ -28,7 +28,7 @@ class DashXModule(private val reactContext: ReactApplicationContext) : ReactCont
28
28
  options.getStringIfPresent("targetEnvironment"),
29
29
  options.getStringIfPresent("targetInstallation")
30
30
  )
31
- interceptor.getDashXClient().generateAnonymousUid()
31
+ interceptor.getDashXClient()?.generateAnonymousUid()
32
32
 
33
33
  if (options.hasKey("trackAppLifecycleEvents") && options.getBoolean("trackAppLifecycleEvents")) {
34
34
  DashXExceptionHandler.enable()
@@ -39,28 +39,28 @@ class DashXModule(private val reactContext: ReactApplicationContext) : ReactCont
39
39
  DashXActivityLifecycleCallbacks.enableScreenTracking(reactContext.applicationContext)
40
40
  }
41
41
 
42
- FirebaseInstanceId.getInstance().instanceId
42
+ FirebaseMessaging.getInstance().getToken()
43
43
  .addOnCompleteListener(OnCompleteListener { task ->
44
44
  if (!task.isSuccessful) {
45
- DashXLog.d(tag, "getInstanceId failed $task.exception")
45
+ DashXLog.d(tag, "FirebaseMessaging.getInstance().getToken() failed: $task.exception")
46
46
  return@OnCompleteListener
47
47
  }
48
48
 
49
- val token = task.result?.token
50
- token?.let { it -> interceptor.getDashXClient().setDeviceToken(it) }
49
+ val token = task.getResult()
50
+ token?.let { it -> interceptor.getDashXClient()?.setDeviceToken(it) }
51
51
  DashXLog.d(tag, "Firebase Initialised with: $token")
52
- })
52
+ });
53
53
  }
54
54
 
55
55
  @ReactMethod
56
56
  fun identify(uid: String?, options: ReadableMap?) {
57
57
  val optionsHashMap = options?.toHashMap()
58
- interceptor.getDashXClient().identify(uid, optionsHashMap as HashMap<String, String>?)
58
+ interceptor.getDashXClient()?.identify(uid, optionsHashMap as HashMap<String, String>?)
59
59
  }
60
60
 
61
61
  @ReactMethod
62
62
  fun reset() {
63
- interceptor.getDashXClient().reset()
63
+ interceptor.getDashXClient()?.reset()
64
64
  }
65
65
 
66
66
  @ReactMethod
@@ -72,22 +72,22 @@ class DashXModule(private val reactContext: ReactApplicationContext) : ReactCont
72
72
  return
73
73
  }
74
74
 
75
- interceptor.getDashXClient().track(event, jsonData)
75
+ interceptor.getDashXClient()?.track(event, jsonData)
76
76
  }
77
77
 
78
78
  @ReactMethod
79
79
  fun screen(screenName: String, data: ReadableMap?) {
80
- interceptor.getDashXClient().screen(screenName, data?.toHashMap() as HashMap<String, String>)
80
+ interceptor.getDashXClient()?.screen(screenName, data?.toHashMap() as HashMap<String, String>)
81
81
  }
82
82
 
83
83
  @ReactMethod
84
84
  fun setIdentityToken(identityToken: String) {
85
- interceptor.getDashXClient().setIdentityToken(identityToken)
85
+ interceptor.getDashXClient()?.setIdentityToken(identityToken)
86
86
  }
87
87
 
88
88
  @ReactMethod
89
89
  fun fetchContent(urn: String, options: ReadableMap?, promise: Promise) {
90
- interceptor.getDashXClient().fetchContent(
90
+ interceptor.getDashXClient()?.fetchContent(
91
91
  urn,
92
92
  options?.getBooleanIfPresent("preview"),
93
93
  options?.getStringIfPresent("language"),
@@ -119,7 +119,7 @@ class DashXModule(private val reactContext: ReactApplicationContext) : ReactCont
119
119
  throw Exception("Encountered an error while parsing order")
120
120
  }
121
121
 
122
- interceptor.getDashXClient().searchContent(
122
+ interceptor.getDashXClient()?.searchContent(
123
123
  contentType,
124
124
  options?.getString("returnType") ?: "all",
125
125
  jsonFilter,
@@ -159,7 +159,7 @@ class DashXModule(private val reactContext: ReactApplicationContext) : ReactCont
159
159
  throw Exception("Encountered an error while parsing custom")
160
160
  }
161
161
 
162
- interceptor.getDashXClient().addItemToCart(
162
+ interceptor.getDashXClient()?.addItemToCart(
163
163
  itemId,
164
164
  pricingId,
165
165
  quantity,
@@ -176,7 +176,7 @@ class DashXModule(private val reactContext: ReactApplicationContext) : ReactCont
176
176
 
177
177
  @ReactMethod
178
178
  fun fetchCart(promise: Promise) {
179
- interceptor.getDashXClient().fetchCart(
179
+ interceptor.getDashXClient()?.fetchCart(
180
180
  onError = {
181
181
  promise.reject("EUNSPECIFIED", it)
182
182
  },
@@ -185,9 +185,9 @@ class DashXModule(private val reactContext: ReactApplicationContext) : ReactCont
185
185
  }
186
186
  )
187
187
  }
188
-
188
+
189
189
  @ReactMethod
190
190
  fun subscribe() {
191
- interceptor.getDashXClient().subscribe()
191
+ interceptor.getDashXClient()?.subscribe()
192
192
  }
193
193
  }
package/ios/API.swift CHANGED
@@ -2169,6 +2169,7 @@ public enum DashXGql {
2169
2169
  subscribeContact(input: $input) {
2170
2170
  __typename
2171
2171
  id
2172
+ value
2172
2173
  }
2173
2174
  }
2174
2175
  """
@@ -2220,6 +2221,7 @@ public enum DashXGql {
2220
2221
  return [
2221
2222
  GraphQLField("__typename", type: .nonNull(.scalar(String.self))),
2222
2223
  GraphQLField("id", type: .nonNull(.scalar(UUID.self))),
2224
+ GraphQLField("value", type: .nonNull(.scalar(String.self))),
2223
2225
  ]
2224
2226
  }
2225
2227
 
@@ -2229,8 +2231,8 @@ public enum DashXGql {
2229
2231
  self.resultMap = unsafeResultMap
2230
2232
  }
2231
2233
 
2232
- public init(id: UUID) {
2233
- self.init(unsafeResultMap: ["__typename": "Contact", "id": id])
2234
+ public init(id: UUID, value: String) {
2235
+ self.init(unsafeResultMap: ["__typename": "Contact", "id": id, "value": value])
2234
2236
  }
2235
2237
 
2236
2238
  public var __typename: String {
@@ -2250,6 +2252,15 @@ public enum DashXGql {
2250
2252
  resultMap.updateValue(newValue, forKey: "id")
2251
2253
  }
2252
2254
  }
2255
+
2256
+ public var value: String {
2257
+ get {
2258
+ return resultMap["value"]! as! String
2259
+ }
2260
+ set {
2261
+ resultMap.updateValue(newValue, forKey: "value")
2262
+ }
2263
+ }
2253
2264
  }
2254
2265
  }
2255
2266
  }
@@ -3,6 +3,7 @@ import Foundation
3
3
  struct Constants {
4
4
  static let PACKAGE_NAME = "com.dashx.sdk"
5
5
  static let USER_PREFERENCES_KEY_ANONYMOUS_UID = "\(PACKAGE_NAME).anonymous_uid"
6
+ static let USER_PREFERENCES_KEY_DEVICE_TOKEN = "\(PACKAGE_NAME).device_token"
6
7
  static let USER_PREFERENCES_KEY_BUILD = "\(PACKAGE_NAME).build"
7
8
  static let INTERNAL_EVENT_APP_INSTALLED = "Application Installed"
8
9
  static let INTERNAL_EVENT_APP_UPDATED = "Application Updated"
@@ -3,23 +3,28 @@ import Foundation
3
3
  @objc(DashXAppDelegate)
4
4
  class DashXAppDelegate: NSObject {
5
5
  static func swizzleDidReceiveRemoteNotification() {
6
- DispatchQueue.main.async {
7
- let appDelegate = UIApplication.shared.delegate
8
- let appDelegateClass = object_getClass(appDelegate)
6
+ let appDelegate = UIApplication.shared.delegate
7
+ let appDelegateClass = object_getClass(appDelegate)
9
8
 
10
- let originalSelector = #selector(UIApplicationDelegate.application(_:didReceiveRemoteNotification:))
11
- let swizzledSelector = #selector(
12
- DashXAppDelegate.self.handleMessage(_:didReceiveRemoteNotification:)
13
- )
9
+ let originalSelector = #selector(UIApplicationDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:))
10
+ let swizzledSelector = #selector(DashXAppDelegate.self.handleMessage(_:didReceiveRemoteNotification:fetchCompletionHandler:))
14
11
 
15
- try? swizzler(appDelegateClass!, DashXAppDelegate.self, originalSelector, swizzledSelector)
12
+ guard let swizzledMethod = class_getInstanceMethod(DashXAppDelegate.self, swizzledSelector) else {
13
+ return
14
+ }
15
+
16
+ if let originalMethod = class_getInstanceMethod(appDelegateClass, originalSelector) {
17
+ // exchange implementation
18
+ method_exchangeImplementations(originalMethod, swizzledMethod)
19
+ } else {
20
+ // add implementation
21
+ class_addMethod(appDelegateClass, swizzledSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
16
22
  }
17
23
  }
18
24
 
25
+ // Based on - https://firebase.google.com/docs/cloud-messaging/ios/receive
19
26
  @objc
20
- func handleMessage(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
21
- var properties: [String: [String: Any]] = [ "notification": [:] ]
22
-
27
+ func handleMessage(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
23
28
  DashXLog.d(tag: #function, "Received APN: \(userInfo)")
24
29
 
25
30
  guard let remoteMessage = try? FirebaseRemoteMessage(decoding: userInfo) else {
@@ -27,9 +32,7 @@ class DashXAppDelegate: NSObject {
27
32
  return
28
33
  }
29
34
 
30
- properties["notification"]?["title"] = remoteMessage.aps.alert.title
31
- properties["notification"]?["body"] = remoteMessage.aps.alert.body
32
-
33
- DashXEventEmitter.instance.dispatch(name: "messageReceived", body: properties)
35
+ completionHandler(.newData)
36
+ DashXEventEmitter.instance.dispatch(name: "messageReceived", body: userInfo)
34
37
  }
35
38
  }
@@ -119,6 +119,18 @@ class DashXClient {
119
119
 
120
120
  track(Constants.INTERNAL_EVENT_APP_SCREEN_VIEWED, withData: properties?.merging([ "name": screenName], uniquingKeysWith: { (_, new) in new }) as NSDictionary?)
121
121
  }
122
+
123
+ // https://stackoverflow.com/a/11197770
124
+ func getDeviceModel() -> String {
125
+ var systemInfo = utsname()
126
+ uname(&systemInfo)
127
+ let machineMirror = Mirror(reflecting: systemInfo.machine)
128
+ return machineMirror.children.reduce("") { identifier, element in
129
+ guard let value = element.value as? Int8, value != 0 else { return identifier }
130
+ return identifier + String(UnicodeScalar(UInt8(value)))
131
+ }
132
+ }
133
+
122
134
  // MARK: -- subscribe
123
135
 
124
136
  func subscribe() {
@@ -129,14 +141,24 @@ class DashXClient {
129
141
 
130
142
  self.mustSubscribe = false
131
143
 
132
- let deviceKind = "IOS"
144
+ let preferences = UserDefaults.standard
145
+ let deviceTokenKey = Constants.USER_PREFERENCES_KEY_DEVICE_TOKEN
133
146
 
147
+ if preferences.string(forKey: deviceTokenKey) == deviceToken {
148
+ DashXLog.d(tag: #function, "Already subscribed: \(String(describing: deviceToken))")
149
+ return
150
+ }
151
+
134
152
  let subscribeContactInput = DashXGql.SubscribeContactInput(
135
153
  accountUid: uid,
136
154
  accountAnonymousUid: anonymousUid!,
137
- name: deviceKind,
155
+ name: UIDevice.current.model,
138
156
  kind: .ios,
139
- value: deviceToken!
157
+ value: deviceToken!,
158
+ osName: UIDevice.current.systemName,
159
+ osVersion: UIDevice.current.systemVersion,
160
+ deviceModel: getDeviceModel(),
161
+ deviceManufacturer: "Apple"
140
162
  )
141
163
 
142
164
  DashXLog.d(tag: #function, "Calling subscribe with \(subscribeContactInput)")
@@ -146,7 +168,10 @@ class DashXClient {
146
168
  Network.shared.apollo.perform(mutation: subscribeContactMutation) { result in
147
169
  switch result {
148
170
  case .success(let graphQLResult):
149
- DashXLog.d(tag: #function, "Sent subscribe with \(String(describing: graphQLResult))")
171
+ if graphQLResult.data != nil {
172
+ preferences.set(graphQLResult.data?.subscribeContact.value, forKey: deviceTokenKey)
173
+ DashXLog.d(tag: #function, "Sent subscribe with \(String(describing: graphQLResult))")
174
+ }
150
175
  case .failure(let error):
151
176
  DashXLog.d(tag: #function, "Encountered an error during subscribe(): \(error)")
152
177
  }
@@ -1,5 +1,6 @@
1
1
  mutation SubscribeContact($input: SubscribeContactInput!) {
2
2
  subscribeContact(input: $input) {
3
3
  id
4
+ value
4
5
  }
5
6
  }