react-native-smartlinks 2.0.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.
Files changed (27) hide show
  1. package/android/build.gradle +33 -0
  2. package/android/src/main/AndroidManifest.xml +4 -0
  3. package/android/src/main/java/live/smartlinks/reactnative/SmartLinksActivityLifecycle.kt +34 -0
  4. package/android/src/main/java/live/smartlinks/reactnative/SmartLinksBridgeHandler.kt +172 -0
  5. package/android/src/main/java/live/smartlinks/reactnative/SmartLinksModule.kt +299 -0
  6. package/android/src/main/java/live/smartlinks/reactnative/SmartLinksPackage.kt +16 -0
  7. package/ios/Linklytics/DeviceInfo.swift +114 -0
  8. package/ios/Linklytics/Linklytics.swift +581 -0
  9. package/ios/Linklytics/LinklyticsInterface.swift +10 -0
  10. package/ios/Linklytics/Managers/BatchEventManager.swift +218 -0
  11. package/ios/Linklytics/Managers/OfflineCache.swift +35 -0
  12. package/ios/Linklytics/Managers/SQLiteStorage.swift +225 -0
  13. package/ios/Linklytics/Models/AppResponse.swift +16 -0
  14. package/ios/Linklytics/Models/DeepLinkRoute.swift +24 -0
  15. package/ios/Linklytics/Models/DeferredLinkResponse.swift +81 -0
  16. package/ios/Linklytics/Models/DynamicLinkResponse.swift +13 -0
  17. package/ios/Linklytics/Models/EventResponse.swift +14 -0
  18. package/ios/Linklytics/Models/OfflineEvent.swift +80 -0
  19. package/ios/Linklytics/NetworkManager.swift +360 -0
  20. package/ios/Linklytics/SdkConstants.swift +29 -0
  21. package/ios/PrivacyInfo.xcprivacy +14 -0
  22. package/ios/SmartLinksModule.m +150 -0
  23. package/ios/SmartLinksModule.swift +281 -0
  24. package/package.json +41 -0
  25. package/react-native-smartlinks.podspec +27 -0
  26. package/react-native.config.js +12 -0
  27. package/src/index.ts +84 -0
@@ -0,0 +1,80 @@
1
+ import Foundation
2
+
3
+ public struct AnyCodable: Codable {
4
+ public let value: Any
5
+
6
+ public init(_ value: Any) {
7
+ self.value = value
8
+ }
9
+
10
+ public init(from decoder: Decoder) throws {
11
+ let container = try decoder.singleValueContainer()
12
+ if let x = try? container.decode(String.self) {
13
+ value = x
14
+ } else if let x = try? container.decode(Int.self) {
15
+ value = x
16
+ } else if let x = try? container.decode(Double.self) {
17
+ value = x
18
+ } else if let x = try? container.decode(Bool.self) {
19
+ value = x
20
+ } else if let x = try? container.decode([String: AnyCodable].self) {
21
+ value = x.mapValues { $0.value }
22
+ } else if let x = try? container.decode([AnyCodable].self) {
23
+ value = x.map { $0.value }
24
+ } else {
25
+ throw DecodingError.dataCorruptedError(in: container, debugDescription: "AnyCodable value cannot be decoded")
26
+ }
27
+ }
28
+
29
+ public func encode(to encoder: Encoder) throws {
30
+ var container = encoder.singleValueContainer()
31
+ if let x = value as? String {
32
+ try container.encode(x)
33
+ } else if let x = value as? Int {
34
+ try container.encode(x)
35
+ } else if let x = value as? Double {
36
+ try container.encode(x)
37
+ } else if let x = value as? Bool {
38
+ try container.encode(x)
39
+ } else if let x = value as? [String: Any] {
40
+ try container.encode(x.mapValues { AnyCodable($0) })
41
+ } else if let x = value as? [Any] {
42
+ try container.encode(x.map { AnyCodable($0) })
43
+ } else {
44
+ throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: container.codingPath, debugDescription: "AnyCodable value cannot be encoded"))
45
+ }
46
+ }
47
+ }
48
+
49
+ public struct OfflineEvent: Codable {
50
+ let id: String
51
+ let eventName: String
52
+ let parameters: [String: AnyCodable]
53
+ let deviceInfo: [String: AnyCodable]
54
+ let timestamp: Int64
55
+ var retryCount: Int
56
+ let appUserId: String?
57
+ let isDebug: Bool
58
+
59
+ init(eventName: String, parameters: [String: Any], deviceInfo: [String: Any] = [:], timestamp: Int64 = Int64(Date().timeIntervalSince1970 * 1000), appUserId: String? = nil, isDebug: Bool = false) {
60
+ self.id = UUID().uuidString
61
+ self.eventName = eventName
62
+ self.parameters = parameters.mapValues { AnyCodable($0) }
63
+ self.deviceInfo = deviceInfo.mapValues { AnyCodable($0) }
64
+ self.timestamp = timestamp
65
+ self.retryCount = 0
66
+ self.appUserId = appUserId
67
+ self.isDebug = isDebug
68
+ }
69
+
70
+ init(id: String, eventName: String, parameters: [String: AnyCodable], deviceInfo: [String: AnyCodable], timestamp: Int64, retryCount: Int, appUserId: String?, isDebug: Bool) {
71
+ self.id = id
72
+ self.eventName = eventName
73
+ self.parameters = parameters
74
+ self.deviceInfo = deviceInfo
75
+ self.timestamp = timestamp
76
+ self.retryCount = retryCount
77
+ self.appUserId = appUserId
78
+ self.isDebug = isDebug
79
+ }
80
+ }
@@ -0,0 +1,360 @@
1
+ import Foundation
2
+
3
+ class NetworkManager {
4
+
5
+ // MARK: - Properties
6
+ private let urlSession: URLSession
7
+ private let apiKey: String
8
+ private let isDebugMode: Bool
9
+
10
+ // MARK: - Initialization
11
+ init(apiKey: String, debugMode: Bool = false) {
12
+ self.apiKey = apiKey
13
+ self.isDebugMode = debugMode
14
+
15
+ let config = URLSessionConfiguration.default
16
+ config.timeoutIntervalForRequest = 30
17
+ config.timeoutIntervalForResource = 60
18
+ self.urlSession = URLSession(configuration: config)
19
+ }
20
+
21
+ // MARK: - Public Methods
22
+
23
+ // MARK: - Public Methods
24
+
25
+ func sendEvent(event: OfflineEvent, completion: @escaping (Result<Data?, Error>) -> Void) {
26
+ let endpoint = SdkConstants.getEventEndpoint(version: Linklytics.apiVersionString)
27
+
28
+ guard let url = URL(string: endpoint) else {
29
+ completion(.failure(NetworkError.invalidURL))
30
+ return
31
+ }
32
+
33
+ // Prepare body with metadata
34
+ let requestBody: [String: Any] = [
35
+ "event_name": event.eventName,
36
+ "params": event.parameters.mapValues { $0.value },
37
+ "device_info": event.deviceInfo.mapValues { $0.value },
38
+ "event_id": event.id,
39
+ "timestamp": event.timestamp,
40
+ "debug": event.isDebug
41
+ ]
42
+
43
+ sendRequest(url: url, body: requestBody, completion: completion)
44
+ }
45
+
46
+ func sendEvent(eventName: String, parameters: [String: Any], completion: @escaping (Result<Data?, Error>) -> Void) {
47
+ // Legacy/Direct support helper -> routes to new logic if needed, or just wraps creation
48
+ // But for consistency we should use the new sendEvent(event:) internally if possible,
49
+ // OR just duplicate logic. Since BatchEventManager creates OfflineEvents,
50
+ // let's update this to create a temporary OfflineEvent for consistency?
51
+ // Actually, just keep direct implementation but add ID/Timestamp
52
+
53
+ let endpoint = SdkConstants.getEventEndpoint(version: Linklytics.apiVersionString)
54
+ guard let url = URL(string: endpoint) else {
55
+ completion(.failure(NetworkError.invalidURL))
56
+ return
57
+ }
58
+
59
+ let requestBody: [String: Any] = [
60
+ "event_name": eventName,
61
+ "params": parameters,
62
+ "event_id": UUID().uuidString,
63
+ "timestamp": Int64(Date().timeIntervalSince1970 * 1000)
64
+ ]
65
+
66
+ sendRequest(url: url, body: requestBody, completion: completion)
67
+ }
68
+
69
+ func sendBatchEvents(events: [OfflineEvent], appUserId: String? = nil, debug: Bool? = nil, completion: @escaping (Result<Data?, Error>) -> Void) {
70
+ let endpoint = SdkConstants.getBatchEventsEndpoint(version: Linklytics.apiVersionString)
71
+
72
+ guard let url = URL(string: endpoint) else {
73
+ completion(.failure(NetworkError.invalidURL))
74
+ return
75
+ }
76
+
77
+ let eventsList = events.map { event -> [String: Any] in
78
+ return [
79
+ "event_name": event.eventName,
80
+ "params": event.parameters.mapValues { $0.value },
81
+ "device_info": event.deviceInfo.mapValues { $0.value },
82
+ "event_id": event.id,
83
+ "timestamp": event.timestamp,
84
+ "debug": event.isDebug
85
+ ]
86
+ }
87
+
88
+ var requestBody: [String: Any] = [
89
+ "events": eventsList
90
+ ]
91
+
92
+ if let appUserId = appUserId {
93
+ requestBody["app_user_id"] = appUserId
94
+ }
95
+
96
+ if let debug = debug {
97
+ requestBody["debug"] = debug
98
+ }
99
+
100
+ sendRequest(url: url, body: requestBody, completion: completion)
101
+ }
102
+
103
+ private func sendRequest(url: URL, body: [String: Any], completion: @escaping (Result<Data?, Error>) -> Void) {
104
+ guard let jsonData = try? JSONSerialization.data(withJSONObject: body) else {
105
+ completion(.failure(NetworkError.serializationError))
106
+ return
107
+ }
108
+
109
+ var request = URLRequest(url: url)
110
+ request.httpMethod = "POST"
111
+ request.setValue("application/json", forHTTPHeaderField: "Content-Type")
112
+ request.setValue(apiKey, forHTTPHeaderField: "api-key")
113
+ request.httpBody = jsonData
114
+
115
+ if isDebugMode {
116
+ print("Linklytics: Sending HTTP request to \(url.absoluteString)")
117
+ if let jsonString = String(data: jsonData, encoding: .utf8) {
118
+ print("Linklytics: Request body: \(jsonString)")
119
+ }
120
+ }
121
+
122
+ urlSession.dataTask(with: request) { [weak self] data, response, error in
123
+ if let error = error {
124
+ if self?.isDebugMode == true {
125
+ print("Linklytics: Request failed: \(error)")
126
+ }
127
+ completion(.failure(error))
128
+ return
129
+ }
130
+
131
+ if let httpResponse = response as? HTTPURLResponse {
132
+ if self?.isDebugMode == true {
133
+ print("Linklytics: Response code: \(httpResponse.statusCode)")
134
+ }
135
+ // Check for 200..299
136
+ if !(200...299).contains(httpResponse.statusCode) {
137
+ // Create error based on status
138
+ // For now just continue, but logically this might be a server error we should retry?
139
+ // BatchEventManager handles retry on failure result.
140
+ // If we return success here for 500, we won't retry.
141
+ // So we should return failure for non-200.
142
+ completion(.failure(NSError(domain: "Linklytics", code: httpResponse.statusCode, userInfo: nil)))
143
+ return
144
+ }
145
+ }
146
+
147
+ completion(.success(data))
148
+ }.resume()
149
+ }
150
+
151
+ // Keep existing fetchDeferredLink and others...
152
+
153
+ func fetchDeferredLink(fingerprint: String, appUserId: String, deviceInfo: [String: String], completion: @escaping (Result<Data?, Error>) -> Void) {
154
+ let endpoint = SdkConstants.getDeferredLinksEndpoint(version: Linklytics.apiVersionString)
155
+
156
+ guard let url = URL(string: endpoint) else {
157
+ completion(.failure(NetworkError.invalidURL))
158
+ return
159
+ }
160
+
161
+ let requestBody: [String: Any] = [
162
+ "fingerprint": fingerprint,
163
+ "app_user_id": appUserId,
164
+ "platform": "ios",
165
+ "device_info": deviceInfo
166
+ ]
167
+
168
+ guard let jsonData = try? JSONSerialization.data(withJSONObject: requestBody) else {
169
+ completion(.failure(NetworkError.serializationError))
170
+ return
171
+ }
172
+
173
+ var request = URLRequest(url: url)
174
+ request.httpMethod = "POST"
175
+ request.setValue("application/json", forHTTPHeaderField: "Content-Type")
176
+ request.setValue(apiKey, forHTTPHeaderField: "api-key")
177
+ request.httpBody = jsonData
178
+
179
+ if isDebugMode {
180
+ print("Linklytics: Fetching deferred deep link from \(endpoint)")
181
+ if let jsonString = String(data: jsonData, encoding: .utf8) {
182
+ print("Linklytics: Request body: \(jsonString)")
183
+ }
184
+ }
185
+
186
+ urlSession.dataTask(with: request) { [weak self] data, response, error in
187
+ if let error = error {
188
+ completion(.failure(error))
189
+ return
190
+ }
191
+
192
+ guard let data = data else {
193
+ completion(.failure(NetworkError.noData))
194
+ return
195
+ }
196
+
197
+ if let httpResponse = response as? HTTPURLResponse {
198
+ if self?.isDebugMode == true {
199
+ print("Linklytics: Deferred link response code: \(httpResponse.statusCode)")
200
+ if let bodyString = String(data: data, encoding: .utf8) {
201
+ print("Linklytics: Deferred link response body: \(bodyString)")
202
+ } else {
203
+ print("Linklytics: Deferred link response body: <non-UTF8 data, size=\(data.count) bytes>")
204
+ }
205
+ }
206
+ if httpResponse.statusCode == 404 || httpResponse.statusCode == 204 {
207
+ completion(.failure(NetworkError.noData))
208
+ return
209
+ }
210
+ }
211
+
212
+ completion(.success(data))
213
+ }.resume()
214
+ }
215
+
216
+ func generateDynamicLink(url: String, parameters: [String: String]?, completion: @escaping (Result<DynamicLinkResponse, Error>) -> Void) {
217
+ let endpoint = SdkConstants.getDynamicLinksEndpoint(version: Linklytics.apiVersionString)
218
+
219
+ guard let requestURL = URL(string: endpoint) else {
220
+ completion(.failure(NetworkError.invalidURL))
221
+ return
222
+ }
223
+
224
+ let requestBody: [String: Any] = [
225
+ "route": url,
226
+ "params": parameters ?? [:],
227
+ ]
228
+
229
+ guard let jsonData = try? JSONSerialization.data(withJSONObject: requestBody) else {
230
+ completion(.failure(NetworkError.serializationError))
231
+ return
232
+ }
233
+
234
+ var request = URLRequest(url: requestURL)
235
+ request.httpMethod = "POST"
236
+ request.setValue("application/json", forHTTPHeaderField: "Content-Type")
237
+ request.setValue(apiKey, forHTTPHeaderField: "api-key")
238
+ request.httpBody = jsonData
239
+
240
+ if isDebugMode {
241
+ print("Linklytics: Generating dynamic link at \(endpoint)")
242
+ print("Linklytics: Input parameters: \(parameters ?? [:])")
243
+ print("Linklytics: Request body object: \(requestBody)")
244
+ if let jsonString = String(data: jsonData, encoding: .utf8) {
245
+ print("Linklytics: Request body JSON: \(jsonString)")
246
+ }
247
+ }
248
+
249
+ urlSession.dataTask(with: request) { [weak self] data, response, error in
250
+ if let error = error {
251
+ if self?.isDebugMode == true {
252
+ print("Linklytics: Failed to generate dynamic link, error: \(error)")
253
+ }
254
+ completion(.failure(error))
255
+ return
256
+ }
257
+
258
+ guard let data = data else {
259
+ completion(.failure(NetworkError.noData))
260
+ return
261
+ }
262
+
263
+ if let httpResponse = response as? HTTPURLResponse {
264
+ if self?.isDebugMode == true {
265
+ print("Linklytics: Dynamic link response code: \(httpResponse.statusCode)")
266
+ if let bodyString = String(data: data, encoding: .utf8) {
267
+ print("Linklytics: Dynamic link response body: \(bodyString)")
268
+ } else {
269
+ print("Linklytics: Dynamic link response body: <non-UTF8 data, size=\(data.count) bytes>")
270
+ }
271
+ }
272
+ }
273
+
274
+ do {
275
+ let dynamicLinkResponse = try JSONDecoder().decode(DynamicLinkResponse.self, from: data)
276
+ completion(.success(dynamicLinkResponse))
277
+ } catch {
278
+ if self?.isDebugMode == true {
279
+ print("Linklytics: Failed to decode dynamic link response: \(error)")
280
+ }
281
+ completion(.failure(error))
282
+ }
283
+ }.resume()
284
+ }
285
+
286
+ func getApp(completion: @escaping (Result<AppResponse, Error>) -> Void) {
287
+ let endpoint = SdkConstants.getAppEndpoint(version: Linklytics.apiVersionString)
288
+
289
+ guard let url = URL(string: endpoint) else {
290
+ completion(.failure(NetworkError.invalidURL))
291
+ return
292
+ }
293
+
294
+ var request = URLRequest(url: url)
295
+ request.httpMethod = "GET"
296
+ request.setValue("application/json", forHTTPHeaderField: "Content-Type")
297
+ request.setValue(apiKey, forHTTPHeaderField: "api-key")
298
+
299
+ if isDebugMode {
300
+ print("Linklytics: Getting app info from \(endpoint)")
301
+ }
302
+
303
+ urlSession.dataTask(with: request) { [weak self] data, response, error in
304
+ if let error = error {
305
+ if self?.isDebugMode == true {
306
+ print("Linklytics: Failed to get app info, error: \(error)")
307
+ }
308
+ completion(.failure(error))
309
+ return
310
+ }
311
+
312
+ guard let data = data else {
313
+ completion(.failure(NetworkError.noData))
314
+ return
315
+ }
316
+
317
+ if let httpResponse = response as? HTTPURLResponse {
318
+ if self?.isDebugMode == true {
319
+ print("Linklytics: App info response code: \(httpResponse.statusCode)")
320
+ if let bodyString = String(data: data, encoding: .utf8) {
321
+ print("Linklytics: App info response body: \(bodyString)")
322
+ } else {
323
+ print("Linklytics: App info response body: <non-UTF8 data, size=\(data.count) bytes>")
324
+ }
325
+ }
326
+ }
327
+
328
+ do {
329
+ let appResponse = try JSONDecoder().decode(AppResponse.self, from: data)
330
+ completion(.success(appResponse))
331
+ } catch {
332
+ if self?.isDebugMode == true {
333
+ print("Linklytics: Failed to decode app response: \(error)")
334
+ }
335
+ completion(.failure(error))
336
+ }
337
+ }.resume()
338
+ }
339
+ }
340
+
341
+ // MARK: - Network Errors
342
+ enum NetworkError: Error {
343
+ case invalidURL
344
+ case serializationError
345
+ case noData
346
+ case notImplemented
347
+
348
+ var localizedDescription: String {
349
+ switch self {
350
+ case .invalidURL:
351
+ return "Invalid URL"
352
+ case .serializationError:
353
+ return "Failed to serialize request data"
354
+ case .noData:
355
+ return "No data received"
356
+ case .notImplemented:
357
+ return "Feature not implemented"
358
+ }
359
+ }
360
+ }
@@ -0,0 +1,29 @@
1
+ import Foundation
2
+
3
+ struct SdkConstants {
4
+ static let baseURL = "https://smartlinks.live"
5
+ private static let eventsEndpointVersioned = "/api/version/events"
6
+ private static let deferredLinksEndpoint = "/api/version/deferred-links"
7
+ private static let dynamicLinksEndpoint = "/api/version/links/create"
8
+ private static let appEndpoint = "/api/version/app"
9
+
10
+ static func getEventEndpoint(version: String) -> String {
11
+ return baseURL + eventsEndpointVersioned.replacingOccurrences(of: "version", with: version)
12
+ }
13
+
14
+ static func getDeferredLinksEndpoint(version: String) -> String {
15
+ return baseURL + deferredLinksEndpoint.replacingOccurrences(of: "version", with: version)
16
+ }
17
+
18
+ static func getDynamicLinksEndpoint(version: String) -> String {
19
+ return baseURL + dynamicLinksEndpoint.replacingOccurrences(of: "version", with: version)
20
+ }
21
+
22
+ static func getAppEndpoint(version: String) -> String {
23
+ return baseURL + appEndpoint.replacingOccurrences(of: "version", with: version)
24
+ }
25
+
26
+ static func getBatchEventsEndpoint(version: String) -> String {
27
+ return baseURL + eventsEndpointVersioned.replacingOccurrences(of: "version", with: version) + "/batch"
28
+ }
29
+ }
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>NSPrivacyTrackingDomains</key>
6
+ <array/>
7
+ <key>NSPrivacyAccessedAPITypes</key>
8
+ <array/>
9
+ <key>NSPrivacyCollectedDataTypes</key>
10
+ <array/>
11
+ <key>NSPrivacyTracking</key>
12
+ <false/>
13
+ </dict>
14
+ </plist>
@@ -0,0 +1,150 @@
1
+ #import <React/RCTBridgeModule.h>
2
+ #import <React/RCTEventEmitter.h>
3
+
4
+ @interface RCT_EXTERN_REMAP_MODULE(SmartLinks, SmartLinksModule, RCTEventEmitter)
5
+
6
+ RCT_EXTERN_METHOD(initialize:(NSString *)apiKey
7
+ debugMode:(BOOL)debugMode
8
+ resolver:(RCTPromiseResolveBlock)resolve
9
+ rejecter:(RCTPromiseRejectBlock)reject)
10
+
11
+ RCT_EXTERN_METHOD(getAppUserId:(RCTPromiseResolveBlock)resolve
12
+ rejecter:(RCTPromiseRejectBlock)reject)
13
+
14
+ RCT_EXTERN_METHOD(sendEvent:(NSString *)eventName
15
+ params:(NSDictionary *)params
16
+ resolver:(RCTPromiseResolveBlock)resolve
17
+ rejecter:(RCTPromiseRejectBlock)reject)
18
+
19
+ RCT_EXTERN_METHOD(generateLink:(NSString *)route
20
+ params:(NSDictionary *)params
21
+ shortLink:(BOOL)shortLink
22
+ resolver:(RCTPromiseResolveBlock)resolve
23
+ rejecter:(RCTPromiseRejectBlock)reject)
24
+
25
+ RCT_EXTERN_METHOD(registerLinkListener:(RCTPromiseResolveBlock)resolve
26
+ rejecter:(RCTPromiseRejectBlock)reject)
27
+
28
+ RCT_EXTERN_METHOD(fetchApps:(RCTPromiseResolveBlock)resolve
29
+ rejecter:(RCTPromiseRejectBlock)reject)
30
+
31
+ RCT_EXTERN_METHOD(submitFeedback:(NSDictionary *)args
32
+ resolver:(RCTPromiseResolveBlock)resolve
33
+ rejecter:(RCTPromiseRejectBlock)reject)
34
+
35
+ RCT_EXTERN_METHOD(fetchAds:(NSString *)type
36
+ resolver:(RCTPromiseResolveBlock)resolve
37
+ rejecter:(RCTPromiseRejectBlock)reject)
38
+
39
+ RCT_EXTERN_METHOD(trackAdImpression:(nonnull NSNumber *)adId
40
+ resolver:(RCTPromiseResolveBlock)resolve
41
+ rejecter:(RCTPromiseRejectBlock)reject)
42
+
43
+ RCT_EXTERN_METHOD(trackAdClick:(nonnull NSNumber *)adId
44
+ resolver:(RCTPromiseResolveBlock)resolve
45
+ rejecter:(RCTPromiseRejectBlock)reject)
46
+
47
+ RCT_EXTERN_METHOD(processAi:(NSString *)instructionsJson
48
+ files:(NSDictionary *)files
49
+ resolver:(RCTPromiseResolveBlock)resolve
50
+ rejecter:(RCTPromiseRejectBlock)reject)
51
+
52
+ RCT_EXTERN_METHOD(validatePromoCode:(NSString *)code
53
+ resolver:(RCTPromiseResolveBlock)resolve
54
+ rejecter:(RCTPromiseRejectBlock)reject)
55
+
56
+ RCT_EXTERN_METHOD(redeemPromoCode:(NSString *)code
57
+ resolver:(RCTPromiseResolveBlock)resolve
58
+ rejecter:(RCTPromiseRejectBlock)reject)
59
+
60
+ RCT_EXTERN_METHOD(verifyGooglePurchase:(NSString *)productId
61
+ token:(NSString *)token
62
+ resolver:(RCTPromiseResolveBlock)resolve
63
+ rejecter:(RCTPromiseRejectBlock)reject)
64
+
65
+ RCT_EXTERN_METHOD(verifyApplePurchase:(NSString *)receiptData
66
+ resolver:(RCTPromiseResolveBlock)resolve
67
+ rejecter:(RCTPromiseRejectBlock)reject)
68
+
69
+ RCT_EXTERN_METHOD(getCommunities:(RCTPromiseResolveBlock)resolve
70
+ rejecter:(RCTPromiseRejectBlock)reject)
71
+
72
+ RCT_EXTERN_METHOD(getPosts:(nonnull NSNumber *)communityId
73
+ authToken:(NSString *)authToken
74
+ resolver:(RCTPromiseResolveBlock)resolve
75
+ rejecter:(RCTPromiseRejectBlock)reject)
76
+
77
+ RCT_EXTERN_METHOD(socialAuthGoogle:(NSString *)accessToken
78
+ project:(NSString *)project
79
+ resolver:(RCTPromiseResolveBlock)resolve
80
+ rejecter:(RCTPromiseRejectBlock)reject)
81
+
82
+ RCT_EXTERN_METHOD(getBlogs:(nonnull NSNumber *)page
83
+ search:(NSString *)search
84
+ resolver:(RCTPromiseResolveBlock)resolve
85
+ rejecter:(RCTPromiseRejectBlock)reject)
86
+
87
+ RCT_EXTERN_METHOD(getBlogPost:(NSString *)slug
88
+ resolver:(RCTPromiseResolveBlock)resolve
89
+ rejecter:(RCTPromiseRejectBlock)reject)
90
+
91
+ RCT_EXTERN_METHOD(getCommunity:(RCTPromiseResolveBlock)resolve
92
+ rejecter:(RCTPromiseRejectBlock)reject)
93
+
94
+ RCT_EXTERN_METHOD(togglePostLike:(nonnull NSNumber *)postId
95
+ authToken:(NSString *)authToken
96
+ resolver:(RCTPromiseResolveBlock)resolve
97
+ rejecter:(RCTPromiseRejectBlock)reject)
98
+
99
+ RCT_EXTERN_METHOD(createPost:(NSString *)communityId
100
+ title:(NSString *)title
101
+ content:(NSString *)content
102
+ authToken:(NSString *)authToken
103
+ resolver:(RCTPromiseResolveBlock)resolve
104
+ rejecter:(RCTPromiseRejectBlock)reject)
105
+
106
+ RCT_EXTERN_METHOD(socialAuthApple:(NSString *)accessToken
107
+ project:(NSString *)project
108
+ resolver:(RCTPromiseResolveBlock)resolve
109
+ rejecter:(RCTPromiseRejectBlock)reject)
110
+
111
+ RCT_EXTERN_METHOD(getComments:(NSString *)postId
112
+ authToken:(NSString *)authToken
113
+ resolver:(RCTPromiseResolveBlock)resolve
114
+ rejecter:(RCTPromiseRejectBlock)reject)
115
+
116
+ RCT_EXTERN_METHOD(createComment:(NSString *)postId
117
+ content:(NSString *)content
118
+ authToken:(NSString *)authToken
119
+ parentId:(NSString *)parentId
120
+ resolver:(RCTPromiseResolveBlock)resolve
121
+ rejecter:(RCTPromiseRejectBlock)reject)
122
+
123
+ RCT_EXTERN_METHOD(toggleCommentLike:(NSString *)commentId
124
+ authToken:(NSString *)authToken
125
+ resolver:(RCTPromiseResolveBlock)resolve
126
+ rejecter:(RCTPromiseRejectBlock)reject)
127
+
128
+ RCT_EXTERN_METHOD(fetchActiveNotificationAd:(NSNumber *)appId
129
+ language:(NSString *)language
130
+ isDebug:(BOOL)isDebug
131
+ resolver:(RCTPromiseResolveBlock)resolve
132
+ rejecter:(RCTPromiseRejectBlock)reject)
133
+
134
+ RCT_EXTERN_METHOD(registerDevice:(NSString *)fcmToken
135
+ platform:(NSString *)platform
136
+ deviceType:(NSString *)deviceType
137
+ appVersion:(NSString *)appVersion
138
+ language:(NSString *)language
139
+ resolver:(RCTPromiseResolveBlock)resolve
140
+ rejecter:(RCTPromiseRejectBlock)reject)
141
+
142
+ RCT_EXTERN_METHOD(trackNotificationAdImpression:(nonnull NSNumber *)adId
143
+ resolver:(RCTPromiseResolveBlock)resolve
144
+ rejecter:(RCTPromiseRejectBlock)reject)
145
+
146
+ RCT_EXTERN_METHOD(trackNotificationAdClick:(nonnull NSNumber *)adId
147
+ resolver:(RCTPromiseResolveBlock)resolve
148
+ rejecter:(RCTPromiseRejectBlock)reject)
149
+
150
+ @end