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.
- package/android/build.gradle +33 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/live/smartlinks/reactnative/SmartLinksActivityLifecycle.kt +34 -0
- package/android/src/main/java/live/smartlinks/reactnative/SmartLinksBridgeHandler.kt +172 -0
- package/android/src/main/java/live/smartlinks/reactnative/SmartLinksModule.kt +299 -0
- package/android/src/main/java/live/smartlinks/reactnative/SmartLinksPackage.kt +16 -0
- package/ios/Linklytics/DeviceInfo.swift +114 -0
- package/ios/Linklytics/Linklytics.swift +581 -0
- package/ios/Linklytics/LinklyticsInterface.swift +10 -0
- package/ios/Linklytics/Managers/BatchEventManager.swift +218 -0
- package/ios/Linklytics/Managers/OfflineCache.swift +35 -0
- package/ios/Linklytics/Managers/SQLiteStorage.swift +225 -0
- package/ios/Linklytics/Models/AppResponse.swift +16 -0
- package/ios/Linklytics/Models/DeepLinkRoute.swift +24 -0
- package/ios/Linklytics/Models/DeferredLinkResponse.swift +81 -0
- package/ios/Linklytics/Models/DynamicLinkResponse.swift +13 -0
- package/ios/Linklytics/Models/EventResponse.swift +14 -0
- package/ios/Linklytics/Models/OfflineEvent.swift +80 -0
- package/ios/Linklytics/NetworkManager.swift +360 -0
- package/ios/Linklytics/SdkConstants.swift +29 -0
- package/ios/PrivacyInfo.xcprivacy +14 -0
- package/ios/SmartLinksModule.m +150 -0
- package/ios/SmartLinksModule.swift +281 -0
- package/package.json +41 -0
- package/react-native-smartlinks.podspec +27 -0
- package/react-native.config.js +12 -0
- package/src/index.ts +84 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
#if canImport(SmartLinksSDKCore)
|
|
4
|
+
import SmartLinksSDKCore
|
|
5
|
+
#elseif canImport(SmartLinksSDK)
|
|
6
|
+
import SmartLinksSDK
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
@objc(SmartLinksModule)
|
|
10
|
+
class SmartLinksModule: RCTEventEmitter {
|
|
11
|
+
|
|
12
|
+
private var hasListeners = false
|
|
13
|
+
|
|
14
|
+
override static func requiresMainQueueSetup() -> Bool {
|
|
15
|
+
return true
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
override func supportedEvents() -> [String]! {
|
|
19
|
+
return ["SmartLinksDeepLink"]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
override func startObserving() {
|
|
23
|
+
hasListeners = true
|
|
24
|
+
SmartLinksSdk.shared.setOnLinkReceivedListener { [weak self] route in
|
|
25
|
+
self?.emitDeepLink(route)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override func stopObserving() {
|
|
30
|
+
hasListeners = false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@objc(initialize:debugMode:resolver:rejecter:)
|
|
34
|
+
func initialize(_ apiKey: String, debugMode: Bool, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
35
|
+
SmartLinksSdk.shared.initialize(apiKey: apiKey, debugMode: debugMode)
|
|
36
|
+
SmartLinksSdk.shared.setOnLinkReceivedListener { [weak self] route in
|
|
37
|
+
guard self?.hasListeners == true else { return }
|
|
38
|
+
self?.emitDeepLink(route)
|
|
39
|
+
}
|
|
40
|
+
resolver(true)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@objc(getAppUserId:rejecter:)
|
|
44
|
+
func getAppUserId(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
45
|
+
resolver(SmartLinksIdentity.getAppUserId())
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@objc(sendEvent:params:resolver:rejecter:)
|
|
49
|
+
func sendEvent(_ eventName: String, params: [String: Any], resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
50
|
+
let parameters = params.mapValues { $0 as Any? }
|
|
51
|
+
SmartLinksSdk.shared.sendEvent(eventName, parameters: parameters)
|
|
52
|
+
resolver(nil)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@objc(generateLink:params:shortLink:resolver:rejecter:)
|
|
56
|
+
func generateLink(_ route: String, params: [String: Any], shortLink: Bool, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
57
|
+
let stringParams = params.mapValues { "\($0)" }
|
|
58
|
+
let link = SmartLinksSdk.shared.generateDynamicLink(route, parameters: stringParams, isShort: shortLink)
|
|
59
|
+
resolver(link)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@objc(registerLinkListener:rejecter:)
|
|
63
|
+
func registerLinkListener(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
64
|
+
if let route = SmartLinksSdk.shared.getLink() {
|
|
65
|
+
emitDeepLink(route)
|
|
66
|
+
}
|
|
67
|
+
resolver(nil)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@objc(fetchApps:rejecter:)
|
|
71
|
+
func fetchApps(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
72
|
+
SmartLinksBridgeAPI.fetchApps { json in
|
|
73
|
+
resolver(json)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@objc(submitFeedback:resolver:rejecter:)
|
|
78
|
+
func submitFeedback(_ args: [String: Any], resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
79
|
+
SmartLinksBridgeAPI.submitFeedback(
|
|
80
|
+
content: args["content"] as? String ?? "",
|
|
81
|
+
platform: args["platform"] as? String ?? "ios",
|
|
82
|
+
version: args["version"] as? String ?? "1.0",
|
|
83
|
+
name: args["name"] as? String,
|
|
84
|
+
email: args["email"] as? String,
|
|
85
|
+
isPremium: args["isPremium"] as? Bool ?? false,
|
|
86
|
+
attachmentPath: args["attachmentPath"] as? String,
|
|
87
|
+
completion: { json in resolver(json) }
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@objc(fetchAds:resolver:rejecter:)
|
|
92
|
+
func fetchAds(_ type: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
93
|
+
SmartLinksBridgeAPI.fetchAds(type: type) { json in
|
|
94
|
+
resolver(json)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@objc(trackAdImpression:resolver:rejecter:)
|
|
99
|
+
func trackAdImpression(_ adId: NSNumber, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
100
|
+
SmartLinksBridgeAPI.trackAdImpression(adId: adId.intValue) { json in
|
|
101
|
+
resolver(json)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@objc(trackAdClick:resolver:rejecter:)
|
|
106
|
+
func trackAdClick(_ adId: NSNumber, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
107
|
+
SmartLinksBridgeAPI.trackAdClick(adId: adId.intValue) { json in
|
|
108
|
+
resolver(json)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@objc(processAi:files:resolver:rejecter:)
|
|
113
|
+
func processAi(_ instructionsJson: String, files: [String: String], resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
114
|
+
SmartLinksBridgeAPI.processAi(instructionsJson: instructionsJson, files: files) { json in
|
|
115
|
+
resolver(json)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@objc(validatePromoCode:resolver:rejecter:)
|
|
120
|
+
func validatePromoCode(_ code: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
121
|
+
SmartLinksBridgeAPI.validatePromoCode(code) { json in
|
|
122
|
+
resolver(json)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@objc(redeemPromoCode:resolver:rejecter:)
|
|
127
|
+
func redeemPromoCode(_ code: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
128
|
+
SmartLinksBridgeAPI.redeemPromoCode(code) { json in
|
|
129
|
+
resolver(json)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@objc(verifyGooglePurchase:token:resolver:rejecter:)
|
|
134
|
+
func verifyGooglePurchase(_ productId: String, token: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
135
|
+
rejecter("UNSUPPORTED", "Google IAP verification is not supported on iOS", nil)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@objc(verifyApplePurchase:resolver:rejecter:)
|
|
139
|
+
func verifyApplePurchase(_ receiptData: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
140
|
+
SmartLinksBridgeAPI.verifyApplePurchase(receiptData: receiptData) { json in
|
|
141
|
+
resolver(json)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@objc(getCommunities:rejecter:)
|
|
146
|
+
func getCommunities(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
147
|
+
SmartLinksBridgeAPI.getCommunities { json in
|
|
148
|
+
resolver(json)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
@objc(getPosts:authToken:resolver:rejecter:)
|
|
153
|
+
func getPosts(_ communityId: NSNumber, authToken: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
154
|
+
SmartLinksBridgeAPI.getPosts(communityId: communityId.intValue, authToken: authToken) { json in
|
|
155
|
+
resolver(json)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@objc(socialAuthGoogle:project:resolver:rejecter:)
|
|
160
|
+
func socialAuthGoogle(_ accessToken: String, project: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
161
|
+
SmartLinksBridgeAPI.socialAuthGoogle(accessToken: accessToken, project: project) { json in
|
|
162
|
+
resolver(json)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@objc(getBlogs:search:resolver:rejecter:)
|
|
167
|
+
func getBlogs(_ page: NSNumber, search: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
168
|
+
SmartLinksBridgeAPI.getBlogs(page: page.intValue, search: search) { json in
|
|
169
|
+
resolver(json)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@objc(getBlogPost:resolver:rejecter:)
|
|
174
|
+
func getBlogPost(_ slug: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
175
|
+
SmartLinksBridgeAPI.getBlogPost(slug: slug) { json in
|
|
176
|
+
resolver(json)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@objc(getCommunity:rejecter:)
|
|
181
|
+
func getCommunity(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
182
|
+
SmartLinksBridgeAPI.getCommunity { json in resolver(json) }
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@objc(togglePostLike:authToken:resolver:rejecter:)
|
|
186
|
+
func togglePostLike(_ postId: NSNumber, authToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
187
|
+
SmartLinksBridgeAPI.togglePostLike(postId: postId.intValue, authToken: authToken) { json in
|
|
188
|
+
resolver(json)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@objc(createPost:title:content:authToken:resolver:rejecter:)
|
|
193
|
+
func createPost(_ communityId: String, title: String, content: String, authToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
194
|
+
SmartLinksBridgeAPI.createPost(
|
|
195
|
+
communityId: communityId,
|
|
196
|
+
title: title,
|
|
197
|
+
content: content,
|
|
198
|
+
authToken: authToken,
|
|
199
|
+
completion: { json in resolver(json) }
|
|
200
|
+
)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@objc(socialAuthApple:project:resolver:rejecter:)
|
|
204
|
+
func socialAuthApple(_ accessToken: String, project: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
205
|
+
SmartLinksBridgeAPI.socialAuthApple(accessToken: accessToken, project: project) { json in
|
|
206
|
+
resolver(json)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
@objc(getComments:authToken:resolver:rejecter:)
|
|
211
|
+
func getComments(_ postId: String, authToken: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
212
|
+
SmartLinksBridgeAPI.getComments(postId: postId, authToken: authToken) { json in
|
|
213
|
+
resolver(json)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@objc(createComment:content:authToken:parentId:resolver:rejecter:)
|
|
218
|
+
func createComment(_ postId: String, content: String, authToken: String, parentId: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
219
|
+
SmartLinksBridgeAPI.createComment(
|
|
220
|
+
postId: postId,
|
|
221
|
+
content: content,
|
|
222
|
+
authToken: authToken,
|
|
223
|
+
parentId: parentId,
|
|
224
|
+
completion: { json in resolver(json) }
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@objc(toggleCommentLike:authToken:resolver:rejecter:)
|
|
229
|
+
func toggleCommentLike(_ commentId: String, authToken: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
230
|
+
SmartLinksBridgeAPI.toggleCommentLike(commentId: commentId, authToken: authToken) { json in
|
|
231
|
+
resolver(json)
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
@objc(fetchActiveNotificationAd:language:isDebug:resolver:rejecter:)
|
|
236
|
+
func fetchActiveNotificationAd(_ appId: NSNumber?, language: String?, isDebug: Bool, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
237
|
+
SmartLinksBridgeAPI.fetchActiveNotificationAd(
|
|
238
|
+
appId: appId?.intValue,
|
|
239
|
+
language: language,
|
|
240
|
+
isDebug: isDebug,
|
|
241
|
+
completion: { json in resolver(json) }
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
@objc(registerDevice:platform:deviceType:appVersion:language:resolver:rejecter:)
|
|
246
|
+
func registerDevice(_ fcmToken: String, platform: String?, deviceType: String?, appVersion: String?, language: String?, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
247
|
+
SmartLinksBridgeAPI.registerDevice(
|
|
248
|
+
fcmToken: fcmToken,
|
|
249
|
+
platform: platform,
|
|
250
|
+
deviceType: deviceType,
|
|
251
|
+
appVersion: appVersion,
|
|
252
|
+
language: language,
|
|
253
|
+
completion: { json in resolver(json) }
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@objc(trackNotificationAdImpression:resolver:rejecter:)
|
|
258
|
+
func trackNotificationAdImpression(_ adId: NSNumber, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
259
|
+
SmartLinksBridgeAPI.trackNotificationAdImpression(adId: adId.intValue) { json in
|
|
260
|
+
resolver(json)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
@objc(trackNotificationAdClick:resolver:rejecter:)
|
|
265
|
+
func trackNotificationAdClick(_ adId: NSNumber, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
266
|
+
SmartLinksBridgeAPI.trackNotificationAdClick(adId: adId.intValue) { json in
|
|
267
|
+
resolver(json)
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private func emitDeepLink(_ route: DeepLinkRoute) {
|
|
272
|
+
let payload: [String: Any] = [
|
|
273
|
+
"route": route.route,
|
|
274
|
+
"params": route.parameters,
|
|
275
|
+
"link": route.link ?? "",
|
|
276
|
+
"appSlug": route.appSlug ?? "",
|
|
277
|
+
"is_first_launch": route.isFirstLaunch,
|
|
278
|
+
]
|
|
279
|
+
sendEvent(withName: "SmartLinksDeepLink", body: payload)
|
|
280
|
+
}
|
|
281
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-smartlinks",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Native bridge for SmartLinks analytics and deep links on React Native",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"types": "src/index.ts",
|
|
7
|
+
"react-native": "src/index.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"src",
|
|
10
|
+
"android/src",
|
|
11
|
+
"android/build.gradle",
|
|
12
|
+
"ios",
|
|
13
|
+
"react-native-smartlinks.podspec",
|
|
14
|
+
"react-native.config.js",
|
|
15
|
+
"!.npmignore"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"react": "*",
|
|
22
|
+
"react-native": "*"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"react": "^18.3.1",
|
|
26
|
+
"react-native": "^0.76.6",
|
|
27
|
+
"typescript": "^5.7.3"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"smartlinks",
|
|
31
|
+
"react-native",
|
|
32
|
+
"analytics",
|
|
33
|
+
"deep-linking"
|
|
34
|
+
],
|
|
35
|
+
"license": "Apache-2.0",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://gitlab.com/elmansoryanas/smartlinks-react-native.git",
|
|
39
|
+
"directory": "packages/native"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'react-native-smartlinks'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = 'Apache-2.0'
|
|
10
|
+
s.homepage = package['repository']['url']
|
|
11
|
+
s.authors = { 'SmartLinks' => 'support@smartlinks.live' }
|
|
12
|
+
s.platforms = { :ios => '15.0' }
|
|
13
|
+
s.source = {
|
|
14
|
+
:git => 'https://gitlab.com/elmansoryanas/smartlinks-react-native.git',
|
|
15
|
+
:tag => "v#{s.version}"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
s.source_files = 'ios/*.{h,m,mm,swift}'
|
|
19
|
+
s.resource_bundles = {
|
|
20
|
+
'react_native_smartlinks_Privacy' => ['ios/PrivacyInfo.xcprivacy']
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
s.dependency 'React-Core'
|
|
24
|
+
# Published from https://gitlab.com/elmansoryanas/smartlinks_ios
|
|
25
|
+
s.dependency 'SmartLinksSDK/Core', '~> 2.0.1'
|
|
26
|
+
s.swift_version = '5.9'
|
|
27
|
+
end
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export type DeepLinkRoute = {
|
|
4
|
+
route: string;
|
|
5
|
+
params: Record<string, string>;
|
|
6
|
+
link?: string;
|
|
7
|
+
appSlug?: string;
|
|
8
|
+
is_first_launch?: boolean;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type NativeSmartLinks = {
|
|
12
|
+
initialize(apiKey: string, debugMode: boolean): Promise<boolean>;
|
|
13
|
+
getAppUserId(): Promise<string | null>;
|
|
14
|
+
sendEvent(eventName: string, params: Record<string, unknown>): Promise<void>;
|
|
15
|
+
generateLink(
|
|
16
|
+
route: string,
|
|
17
|
+
params: Record<string, unknown>,
|
|
18
|
+
shortLink: boolean,
|
|
19
|
+
): Promise<string | null>;
|
|
20
|
+
registerLinkListener(): Promise<void>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const LINKING = NativeModules.SmartLinks as NativeSmartLinks | undefined;
|
|
24
|
+
|
|
25
|
+
const emitter = LINKING ? new NativeEventEmitter(NativeModules.SmartLinks) : null;
|
|
26
|
+
|
|
27
|
+
export async function nativeInitialize(
|
|
28
|
+
apiKey: string,
|
|
29
|
+
debugMode = false,
|
|
30
|
+
): Promise<boolean> {
|
|
31
|
+
if (!LINKING) {
|
|
32
|
+
if (__DEV__) {
|
|
33
|
+
console.warn('[SmartLinks] Native module unavailable');
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return LINKING.initialize(apiKey, debugMode);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function nativeGetAppUserId(): Promise<string | null> {
|
|
41
|
+
if (!LINKING) return null;
|
|
42
|
+
return LINKING.getAppUserId();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function nativeSendEvent(
|
|
46
|
+
eventName: string,
|
|
47
|
+
params: Record<string, unknown> = {},
|
|
48
|
+
): Promise<void> {
|
|
49
|
+
if (!LINKING) return;
|
|
50
|
+
await LINKING.sendEvent(eventName, params);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function nativeGenerateLink(
|
|
54
|
+
route: string,
|
|
55
|
+
params: Record<string, unknown> = {},
|
|
56
|
+
shortLink = true,
|
|
57
|
+
): Promise<string | null> {
|
|
58
|
+
if (!LINKING) return null;
|
|
59
|
+
return LINKING.generateLink(route, params, shortLink);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function addDeepLinkListener(
|
|
63
|
+
listener: (route: DeepLinkRoute) => void,
|
|
64
|
+
): () => void {
|
|
65
|
+
if (!emitter || !LINKING) {
|
|
66
|
+
return () => undefined;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const subscription = emitter.addListener('SmartLinksDeepLink', (payload) => {
|
|
70
|
+
listener({
|
|
71
|
+
route: payload.route ?? '',
|
|
72
|
+
params: payload.params ?? {},
|
|
73
|
+
link: payload.link,
|
|
74
|
+
appSlug: payload.appSlug ?? payload.app_slug,
|
|
75
|
+
is_first_launch: payload.is_first_launch,
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
void LINKING.registerLinkListener();
|
|
80
|
+
|
|
81
|
+
return () => subscription.remove();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const isNativeAvailable = Platform.OS === 'android' || Platform.OS === 'ios';
|