@dashx/react-native 1.1.5 → 1.3.0

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/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
2
+ import NativeDashXReactNative from './src/NativeDashXReactNative';
2
3
 
3
4
  function getLinkingError() {
4
5
  return (
@@ -12,8 +13,10 @@ function getLinkingError() {
12
13
  let _nativeDashX = null;
13
14
  function getNativeDashX() {
14
15
  if (!_nativeDashX) {
15
- _nativeDashX = NativeModules.DashXReactNative
16
- ? NativeModules.DashXReactNative
16
+ const nativeModule =
17
+ NativeDashXReactNative || NativeModules.DashXReactNative;
18
+ _nativeDashX = nativeModule
19
+ ? nativeModule
17
20
  : new Proxy(
18
21
  {},
19
22
  {
@@ -55,17 +58,16 @@ const DashX = {
55
58
  },
56
59
 
57
60
  setIdentity(uid, token) {
58
- if (!uid || typeof uid !== 'string') {
59
- throw new Error(
60
- 'DashX.setIdentity: uid is required and must be a string'
61
- );
61
+ // Both uid and token are nullable passthroughs to the native SDK. Only
62
+ // validate TYPE here — the native side decides semantics. `undefined` is
63
+ // normalized to `null` because the RN bridge can't carry undefined.
64
+ if (uid !== null && uid !== undefined && typeof uid !== 'string') {
65
+ throw new Error('DashX.setIdentity: uid must be a string or null');
62
66
  }
63
- if (!token || typeof token !== 'string') {
64
- throw new Error(
65
- 'DashX.setIdentity: token is required and must be a string'
66
- );
67
+ if (token !== null && token !== undefined && typeof token !== 'string') {
68
+ throw new Error('DashX.setIdentity: token must be a string or null');
67
69
  }
68
- return getNativeDashX().setIdentity(uid, token);
70
+ return getNativeDashX().setIdentity(uid ?? null, token ?? null);
69
71
  },
70
72
 
71
73
  reset() {
@@ -216,6 +218,15 @@ const DashX = {
216
218
  }
217
219
  return getEventEmitter().addListener('linkReceived', callback);
218
220
  },
221
+
222
+ onNotificationClicked(callback) {
223
+ if (typeof callback !== 'function') {
224
+ throw new Error(
225
+ 'DashX.onNotificationClicked: callback must be a function'
226
+ );
227
+ }
228
+ return getEventEmitter().addListener('notificationClicked', callback);
229
+ },
219
230
  };
220
231
 
221
232
  export default DashX;
@@ -0,0 +1,257 @@
1
+ import Foundation
2
+ import UIKit
3
+ import UserNotifications
4
+ import DashX
5
+ import FirebaseMessaging
6
+
7
+ /// The result of handling a notification response.
8
+ /// Consumers can use `url` to navigate and `actionIdentifier` for custom action handling.
9
+ @objc(DashXNotificationResponseResult)
10
+ public final class DashXNotificationResponseResult: NSObject {
11
+ @objc public let userInfo: [AnyHashable: Any]
12
+ @objc public let actionIdentifier: String
13
+ /// The DashX notification URL, if present in the payload.
14
+ @objc public let url: URL?
15
+ /// The resolved navigation intent for the tap / action button.
16
+ /// Non-@objc (the enum isn't representable in Obj-C); read via Swift.
17
+ public let navigationAction: NavigationAction?
18
+
19
+ init(userInfo: [AnyHashable: Any], actionIdentifier: String, url: URL?, navigationAction: NavigationAction?) {
20
+ self.userInfo = userInfo
21
+ self.actionIdentifier = actionIdentifier
22
+ self.url = url
23
+ self.navigationAction = navigationAction
24
+ }
25
+ }
26
+
27
+ @objc(DashXNotificationHandler)
28
+ public final class DashXNotificationHandler: NSObject {
29
+
30
+ @objc
31
+ public static func handleRemoteNotification(
32
+ userInfo: [AnyHashable: Any],
33
+ completionHandler: @escaping (UIBackgroundFetchResult) -> Void
34
+ ) {
35
+ Messaging.messaging().appDidReceiveMessage(userInfo)
36
+
37
+ DashXEventEmitter.instance.dispatch(
38
+ name: "messageReceived",
39
+ body: bridgeSafePayload(from: userInfo)
40
+ )
41
+
42
+ guard let dashxData = userInfo.dashxNotificationData() else {
43
+ completionHandler(.noData)
44
+ return
45
+ }
46
+
47
+ DashX.trackMessage(message: userInfo, event: .delivered)
48
+
49
+ let content = UNMutableNotificationContent()
50
+ content.sound = UNNotificationSound.default
51
+ content.title = dashxData.title
52
+ content.body = dashxData.body
53
+ content.userInfo = userInfo
54
+ content.categoryIdentifier = Constants.DASHX_NOTIFICATION_CATEGORY_IDENTIFIER
55
+
56
+ var actions: [UNNotificationAction] = []
57
+ if let actionButtons = dashxData.actionButtons {
58
+ for button in actionButtons {
59
+ actions.append(
60
+ UNNotificationAction(
61
+ identifier: button.identifier,
62
+ title: button.label,
63
+ options: [.foreground]
64
+ )
65
+ )
66
+ }
67
+ }
68
+
69
+ let category = UNNotificationCategory(
70
+ identifier: Constants.DASHX_NOTIFICATION_CATEGORY_IDENTIFIER,
71
+ actions: actions,
72
+ intentIdentifiers: [],
73
+ options: .customDismissAction
74
+ )
75
+ UNUserNotificationCenter.current().setNotificationCategories([category])
76
+
77
+ if let imagePath = dashxData.image, let imageURL = URL(string: imagePath) {
78
+ createNotificationWithImage(id: dashxData.id, imageURL: imageURL, content: content)
79
+ } else {
80
+ createNotification(id: dashxData.id, content: content)
81
+ }
82
+
83
+ completionHandler(.newData)
84
+ }
85
+
86
+ @objc
87
+ @discardableResult
88
+ public static func handleNotificationResponse(_ response: UNNotificationResponse) -> DashXNotificationResponseResult {
89
+ let userInfo = response.notification.request.content.userInfo
90
+
91
+ Messaging.messaging().appDidReceiveMessage(userInfo)
92
+
93
+ DashXEventEmitter.instance.dispatch(
94
+ name: "messageReceived",
95
+ body: bridgeSafePayload(from: userInfo)
96
+ )
97
+
98
+ if response.actionIdentifier == UNNotificationDismissActionIdentifier {
99
+ DashX.trackMessage(message: userInfo, event: .dismissed)
100
+ } else {
101
+ DashX.trackMessage(message: userInfo, event: .clicked)
102
+ }
103
+
104
+ let notificationUrl = userInfo.dashxNotificationUrl()
105
+ let dashxData = userInfo.dashxNotificationData()
106
+ let navigationAction = dashxData?.navigationAction(forActionIdentifier: response.actionIdentifier)
107
+
108
+ if response.actionIdentifier != UNNotificationDismissActionIdentifier {
109
+ DashXEventEmitter.instance.dispatch(
110
+ name: "notificationClicked",
111
+ body: [
112
+ "notification": bridgeSafePayload(from: userInfo),
113
+ "action": jsonDictionary(from: navigationAction) ?? NSNull(),
114
+ "actionIdentifier": response.actionIdentifier,
115
+ ]
116
+ )
117
+ }
118
+
119
+ return DashXNotificationResponseResult(
120
+ userInfo: userInfo,
121
+ actionIdentifier: response.actionIdentifier,
122
+ url: notificationUrl,
123
+ navigationAction: navigationAction
124
+ )
125
+ }
126
+
127
+ // MARK: - Device Token
128
+
129
+ /// Bridges the APNS device token to Firebase Cloud Messaging and registers
130
+ /// the FCM token with DashX. Call this from
131
+ /// `application(_:didRegisterForRemoteNotificationsWithDeviceToken:)`.
132
+ @objc
133
+ public static func handleDeviceToken(_ deviceToken: Data) {
134
+ // Force the APNs environment explicitly rather than using `.unknown`
135
+ // (auto-detect). Firebase's auto-detection reads the token's aps
136
+ // entitlement from the signed binary and sometimes mis-tags dev
137
+ // builds as production, producing an FCM token whose pushes silently
138
+ // fail at APNs with 410 Unregistered.
139
+ #if DEBUG
140
+ Messaging.messaging().setAPNSToken(deviceToken, type: .sandbox)
141
+ #else
142
+ Messaging.messaging().setAPNSToken(deviceToken, type: .prod)
143
+ #endif
144
+ Messaging.messaging().token { token, error in
145
+ if let token = token {
146
+ DashX.setFCMToken(to: token)
147
+ }
148
+ }
149
+ }
150
+
151
+ // MARK: - Foreground Notification
152
+
153
+ /// Handles a notification that arrived while the app is in the foreground.
154
+ /// Tracks the delivery event, emits `messageReceived` to JS, forwards to
155
+ /// Firebase analytics, and presents the notification as a banner with sound.
156
+ /// Call this from `userNotificationCenter(_:willPresent:withCompletionHandler:)`.
157
+ @objc
158
+ public static func handleForegroundNotification(
159
+ _ notification: UNNotification,
160
+ completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
161
+ ) {
162
+ let userInfo = notification.request.content.userInfo
163
+
164
+ Messaging.messaging().appDidReceiveMessage(userInfo)
165
+
166
+ DashX.trackMessage(message: userInfo, event: .delivered)
167
+
168
+ DashXEventEmitter.instance.dispatch(
169
+ name: "messageReceived",
170
+ body: bridgeSafePayload(from: userInfo)
171
+ )
172
+
173
+ completionHandler([.banner, .sound])
174
+ }
175
+
176
+ // MARK: - Private Helpers
177
+
178
+ private static func createNotification(id: String, content: UNMutableNotificationContent) {
179
+ let request = UNNotificationRequest(identifier: id, content: content, trigger: nil)
180
+ UNUserNotificationCenter.current().add(request) { error in
181
+ if let error = error {
182
+ DashXLog.d(tag: #function, "Failed to schedule notification: \(error.localizedDescription)")
183
+ }
184
+ }
185
+ }
186
+
187
+ private static func createNotificationWithImage(
188
+ id: String,
189
+ imageURL: URL,
190
+ content: UNMutableNotificationContent
191
+ ) {
192
+ let task = URLSession.shared.downloadTask(with: imageURL) { location, _, error in
193
+ guard let location = location, error == nil else {
194
+ createNotification(id: id, content: content)
195
+ return
196
+ }
197
+
198
+ let tmpDir = FileManager.default.temporaryDirectory
199
+ let tmpFile = tmpDir.appendingPathComponent(UUID().uuidString + ".png")
200
+
201
+ do {
202
+ try FileManager.default.moveItem(at: location, to: tmpFile)
203
+ let attachment = try UNNotificationAttachment(
204
+ identifier: "\(id)-attachment",
205
+ url: tmpFile,
206
+ options: nil
207
+ )
208
+ content.attachments = [attachment]
209
+ createNotification(id: id, content: content)
210
+ } catch {
211
+ createNotification(id: id, content: content)
212
+ }
213
+ }
214
+ task.resume()
215
+ }
216
+
217
+ /// Serializes a ``NavigationAction`` into the JS-bridge shape mirrored by
218
+ /// `NavigationAction` in `index.d.ts`. Returns `nil` for `nil` input.
219
+ private static func jsonDictionary(from action: NavigationAction?) -> [String: Any]? {
220
+ guard let action else { return nil }
221
+ switch action {
222
+ case .deepLink(let url):
223
+ return ["type": "deepLink", "url": url.absoluteString]
224
+ case .screen(let name, let data):
225
+ var dict: [String: Any] = ["type": "screen", "name": name]
226
+ if let data { dict["data"] = data }
227
+ return dict
228
+ case .richLanding(let url):
229
+ return ["type": "richLanding", "url": url.absoluteString]
230
+ case .clickAction(let actionString):
231
+ return ["type": "clickAction", "action": actionString]
232
+ }
233
+ }
234
+
235
+ private static func bridgeSafePayload(from userInfo: [AnyHashable: Any]) -> [String: Any] {
236
+ userInfo.reduce(into: [String: Any]()) { result, pair in
237
+ let key = String(describing: pair.key)
238
+ let value = pair.value
239
+ if let str = value as? String {
240
+ result[key] = str
241
+ } else if let num = value as? NSNumber {
242
+ result[key] = num
243
+ } else if let dict = value as? [AnyHashable: Any] {
244
+ result[key] = bridgeSafePayload(from: dict)
245
+ } else if let arr = value as? [Any] {
246
+ result[key] = arr.map { item -> Any in
247
+ if let str = item as? String { return str }
248
+ if let num = item as? NSNumber { return num }
249
+ if let d = item as? [AnyHashable: Any] { return bridgeSafePayload(from: d) }
250
+ return "\(item)"
251
+ }
252
+ } else {
253
+ result[key] = "\(value)"
254
+ }
255
+ }
256
+ }
257
+ }
@@ -1,5 +1,3 @@
1
1
  #import <React/RCTBridgeModule.h>
2
2
  #import <React/RCTEventEmitter.h>
3
3
  #import <React/RCTViewManager.h>
4
- #import <React_RCTAppDelegate/RCTDefaultReactNativeFactoryDelegate.h>
5
- #import <React_RCTAppDelegate/RCTReactNativeFactory.h>
@@ -1,6 +1,10 @@
1
1
  #import <React/RCTBridgeModule.h>
2
2
  #import <React/RCTEventEmitter.h>
3
3
 
4
+ #ifdef RCT_NEW_ARCH_ENABLED
5
+ #import "RNDashXReactNativeSpec.h"
6
+ #endif
7
+
4
8
  @interface RCT_EXTERN_MODULE(DashXReactNative, RCTEventEmitter)
5
9
 
6
10
  RCT_EXTERN_METHOD(configure:(NSDictionary *)options);
@@ -13,13 +17,13 @@ RCT_EXTERN_METHOD(track:(NSString *)event data:(NSDictionary * _Nullable)data);
13
17
 
14
18
  RCT_EXTERN_METHOD(screen:(NSString *)screenName data:(NSDictionary * _Nullable)data);
15
19
 
16
- RCT_EXTERN_METHOD(fetchRecord:(NSString *)urn options:(NSDictionary * _Nullable)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject);
20
+ RCT_EXTERN_METHOD(fetchRecord:(NSString *)urn options:(NSDictionary * _Nullable)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject);
17
21
 
18
- RCT_EXTERN_METHOD(searchRecords:(NSString *)resource options:(NSDictionary * _Nullable)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject);
22
+ RCT_EXTERN_METHOD(searchRecords:(NSString *)resource options:(NSDictionary * _Nullable)options resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject);
19
23
 
20
- RCT_EXTERN_METHOD(fetchStoredPreferences:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject);
24
+ RCT_EXTERN_METHOD(fetchStoredPreferences:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject);
21
25
 
22
- RCT_EXTERN_METHOD(saveStoredPreferences:(NSDictionary *)preferenceData resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject);
26
+ RCT_EXTERN_METHOD(saveStoredPreferences:(NSDictionary *)preferenceData resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject);
23
27
 
24
28
  RCT_EXTERN_METHOD(reset);
25
29
 
@@ -27,18 +31,37 @@ RCT_EXTERN_METHOD(subscribe);
27
31
 
28
32
  RCT_EXTERN_METHOD(unsubscribe);
29
33
 
30
- RCT_EXTERN_METHOD(setLogLevel:(int *)level);
34
+ RCT_EXTERN_METHOD(setLogLevel:(double)level);
31
35
 
32
- RCT_EXTERN_METHOD(uploadAsset:(NSString *)filePath resource:(NSString *)resource attribute:(NSString *)attribute resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject);
36
+ RCT_EXTERN_METHOD(uploadAsset:(NSString *)filePath resource:(NSString *)resource attribute:(NSString *)attribute resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject);
33
37
 
34
- RCT_EXTERN_METHOD(fetchAsset:(NSString *)assetId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject);
38
+ RCT_EXTERN_METHOD(fetchAsset:(NSString *)assetId resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject);
35
39
 
36
40
  RCT_EXTERN_METHOD(enableLifecycleTracking);
37
41
 
38
42
  RCT_EXTERN_METHOD(enableAdTracking);
39
43
 
40
- RCT_EXTERN_METHOD(requestNotificationPermission:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject);
44
+ RCT_EXTERN_METHOD(processURL:(NSString *)url source:(NSString * _Nullable)source forwardToLinkHandler:(BOOL)forwardToLinkHandler);
45
+
46
+ RCT_EXTERN_METHOD(trackNotificationNavigation:(NSDictionary * _Nullable)action notificationId:(NSString * _Nullable)notificationId);
47
+
48
+ RCT_EXTERN_METHOD(requestNotificationPermission:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject);
49
+
50
+ RCT_EXTERN_METHOD(getNotificationPermissionStatus:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject);
51
+
52
+ @end
53
+
54
+ #ifdef RCT_NEW_ARCH_ENABLED
55
+ @interface DashXReactNative () <NativeDashXReactNativeSpec>
56
+ @end
57
+
58
+ @implementation DashXReactNative (TurboModule)
41
59
 
42
- RCT_EXTERN_METHOD(getNotificationPermissionStatus:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject);
60
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
61
+ (const facebook::react::ObjCTurboModule::InitParams &)params
62
+ {
63
+ return std::make_shared<facebook::react::NativeDashXReactNativeSpecJSI>(params);
64
+ }
43
65
 
44
66
  @end
67
+ #endif
@@ -16,7 +16,7 @@ class DashXReactNative: RCTEventEmitter {
16
16
  }
17
17
 
18
18
  override func supportedEvents() -> [String] {
19
- return ["messageReceived", "linkReceived"]
19
+ return ["messageReceived", "linkReceived", "notificationClicked"]
20
20
  }
21
21
 
22
22
  @objc(configure:)
@@ -60,8 +60,8 @@ class DashXReactNative: RCTEventEmitter {
60
60
  DashX.screen(screenName, withData: data as? [String: Any])
61
61
  }
62
62
 
63
- @objc(fetchRecord:options:resolver:rejecter:)
64
- func fetchRecord(_ urn: String, options: NSDictionary?, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
63
+ @objc(fetchRecord:options:resolve:reject:)
64
+ func fetchRecord(_ urn: String, options: NSDictionary?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
65
65
  DashXClient.instance.fetchRecord(
66
66
  urn: urn,
67
67
  preview: options?["preview"] as? Bool,
@@ -77,8 +77,8 @@ class DashXReactNative: RCTEventEmitter {
77
77
  }
78
78
  }
79
79
 
80
- @objc(searchRecords:options:resolver:rejecter:)
81
- func searchRecords(_ resource: String, options: NSDictionary?, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
80
+ @objc(searchRecords:options:resolve:reject:)
81
+ func searchRecords(_ resource: String, options: NSDictionary?, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
82
82
  DashXClient.instance.searchRecords(
83
83
  resource: resource,
84
84
  filter: options?["filter"] as? [String: Any],
@@ -98,8 +98,8 @@ class DashXReactNative: RCTEventEmitter {
98
98
  }
99
99
  }
100
100
 
101
- @objc(fetchStoredPreferences:rejecter:)
102
- func fetchStoredPreferences(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
101
+ @objc(fetchStoredPreferences:reject:)
102
+ func fetchStoredPreferences(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
103
103
  DashXClient.instance.fetchStoredPreferences { result in
104
104
  switch result {
105
105
  case .success(let prefs): resolve(prefs)
@@ -108,8 +108,8 @@ class DashXReactNative: RCTEventEmitter {
108
108
  }
109
109
  }
110
110
 
111
- @objc(saveStoredPreferences:resolver:rejecter:)
112
- func saveStoredPreferences(_ preferenceData: NSDictionary, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
111
+ @objc(saveStoredPreferences:resolve:reject:)
112
+ func saveStoredPreferences(_ preferenceData: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
113
113
  guard let dict = preferenceData as? [String: Any] else {
114
114
  reject("EINVAL", "preferenceData must be a plain object", nil)
115
115
  return
@@ -133,13 +133,21 @@ class DashXReactNative: RCTEventEmitter {
133
133
  }
134
134
 
135
135
  @objc(setLogLevel:)
136
- func setLogLevel(_ level: Int) {
137
- let logLevel = DashXLog.LogLevel(rawValue: level) ?? DashXLog.LogLevel.off
136
+ func setLogLevel(_ level: Double) {
137
+ // JS contract: 0 = off, 1 = errors, 2 = debug
138
+ // Native SDK: off = -1, error = 0, info = 1, debug = 2
139
+ let logLevel: DashXLog.LogLevel
140
+ switch Int(level) {
141
+ case 0: logLevel = .off
142
+ case 1: logLevel = .error
143
+ case 2: logLevel = .debug
144
+ default: logLevel = .off
145
+ }
138
146
  DashXLog.setLogLevel(to: logLevel)
139
147
  }
140
148
 
141
- @objc(uploadAsset:resource:attribute:resolver:rejecter:)
142
- func uploadAsset(_ filePath: String, resource: String, attribute: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
149
+ @objc(uploadAsset:resource:attribute:resolve:reject:)
150
+ func uploadAsset(_ filePath: String, resource: String, attribute: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
143
151
  let fileURL = URL(fileURLWithPath: filePath)
144
152
  DashXClient.instance.uploadAsset(fileURL: fileURL, resource: resource, attribute: attribute) { result in
145
153
  switch result {
@@ -156,8 +164,8 @@ class DashXReactNative: RCTEventEmitter {
156
164
  }
157
165
  }
158
166
 
159
- @objc(fetchAsset:resolver:rejecter:)
160
- func fetchAsset(_ assetId: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
167
+ @objc(fetchAsset:resolve:reject:)
168
+ func fetchAsset(_ assetId: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
161
169
  DashXClient.instance.fetchAsset(assetId: assetId) { result in
162
170
  switch result {
163
171
  case .success(let assetResponse):
@@ -217,13 +225,13 @@ class DashXReactNative: RCTEventEmitter {
217
225
  DashX.trackNotificationNavigation(navigationAction, notificationId: notificationId as String?)
218
226
  }
219
227
 
220
- @objc(requestNotificationPermission:rejecter:)
221
- func requestNotificationPermission(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
228
+ @objc(requestNotificationPermission:reject:)
229
+ func requestNotificationPermission(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
222
230
  DashX.requestNotificationPermission { status in resolve(status.rawValue) }
223
231
  }
224
232
 
225
- @objc(getNotificationPermissionStatus:rejecter:)
226
- func getNotificationPermissionStatus(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
233
+ @objc(getNotificationPermissionStatus:reject:)
234
+ func getNotificationPermissionStatus(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
227
235
  DashX.getNotificationPermissionStatus { status in resolve(status.rawValue) }
228
236
  }
229
237
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@dashx/react-native",
3
3
  "title": "DashX React Native",
4
- "version": "1.1.5",
4
+ "version": "1.3.0",
5
5
  "description": "DashX SDK for React Native",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
@@ -22,8 +22,17 @@
22
22
  "index.js",
23
23
  "index.d.ts",
24
24
  "ios",
25
+ "src",
25
26
  "README.md"
26
27
  ],
28
+ "codegenConfig": {
29
+ "name": "RNDashXReactNativeSpec",
30
+ "type": "modules",
31
+ "jsSrcsDir": "src",
32
+ "android": {
33
+ "javaPackageName": "com.dashx.rn.sdk"
34
+ }
35
+ },
27
36
  "scripts": {
28
37
  "test": "jest",
29
38
  "lint": "eslint index.js"
@@ -49,7 +58,7 @@
49
58
  },
50
59
  "peerDependencies": {
51
60
  "react": ">=17.0.0",
52
- "react-native": ">=0.71.0"
61
+ "react-native": ">=0.74.0"
53
62
  },
54
63
  "devDependencies": {
55
64
  "@commitlint/config-conventional": "^17.0.2",
@@ -0,0 +1,42 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+
4
+ export interface Spec extends TurboModule {
5
+ configure(options: Object): void;
6
+ identify(options: Object | null): void;
7
+ setIdentity(uid: string | null, token: string | null): void;
8
+ reset(): void;
9
+ track(event: string, data: Object | null): void;
10
+ screen(screenName: string, data: Object | null): void;
11
+ fetchRecord(urn: string, options: Object | null): Promise<Object>;
12
+ searchRecords(resource: string, options: Object | null): Promise<Object[]>;
13
+ fetchStoredPreferences(): Promise<Object>;
14
+ saveStoredPreferences(preferenceData: Object): Promise<Object>;
15
+ subscribe(): void;
16
+ unsubscribe(): void;
17
+ setLogLevel(level: number): void;
18
+ uploadAsset(
19
+ filePath: string,
20
+ resource: string,
21
+ attribute: string
22
+ ): Promise<Object>;
23
+ fetchAsset(assetId: string): Promise<Object>;
24
+ enableLifecycleTracking(): void;
25
+ enableAdTracking(): void;
26
+ processURL(
27
+ url: string,
28
+ source: string | null,
29
+ forwardToLinkHandler: boolean
30
+ ): void;
31
+ trackNotificationNavigation(
32
+ action: Object | null,
33
+ notificationId: string | null
34
+ ): void;
35
+ requestNotificationPermission(): Promise<number>;
36
+ getNotificationPermissionStatus(): Promise<number>;
37
+
38
+ addListener(eventName: string): void;
39
+ removeListeners(count: number): void;
40
+ }
41
+
42
+ export default TurboModuleRegistry.get<Spec>('DashXReactNative');