react-native-nami-sdk 3.2.2 → 3.2.3-2
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/README.md +9 -11
- package/android/build.gradle +3 -3
- package/android/src/main/java/com/nami/reactlibrary/NamiBridgeModule.kt +1 -1
- package/android/src/main/java/com/nami/reactlibrary/NamiCampaignManagerBridge.kt +73 -47
- package/build-utils/preflight.py +2 -1
- package/ios/Nami.m +1 -1
- package/ios/NamiCampaignManagerBridge.swift +10 -1
- package/package.json +1 -1
- package/react-native-nami-sdk.podspec +1 -1
package/README.md
CHANGED
|
@@ -2,20 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
# React Native Bridge for the Nami SDK
|
|
4
4
|
|
|
5
|
-
Nami
|
|
5
|
+
Nami ML gives you everything you need to power your paywall, streamline subscription management, and drive revenue growth through instantly deployable paywalls, precise targeting and segmentation, and enterprise-grade security and scaleability.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- No IAP code to write.
|
|
9
|
-
- Focus on your app experience.
|
|
10
|
-
- All edge cases are handled and no server is required.
|
|
11
|
-
- Includes is powerful built-in paywalls templates, built with native SwiftUI and Jetpack Compose
|
|
12
|
-
- Update paywalls easily using a browser-based paywall CMS.
|
|
13
|
-
- Conduct paywall A/B tests, to improve your conversion rate.
|
|
14
|
-
- Robust subscription analytics, webhooks, and much more.
|
|
7
|
+
Go beyond basic IAP and focus on results with:
|
|
15
8
|
|
|
16
|
-
|
|
9
|
+
* Library of smart paywall templates to choose from, implemented natively
|
|
10
|
+
* No-code paywall creator so you can launch a new paywall design instantly, without submitting an app update
|
|
11
|
+
* Experimentation engine to run paywall A/B tests so you can improve your conversion rates
|
|
12
|
+
* Built-in IAP & subscription management and analytics, so you don't need another solution
|
|
17
13
|
|
|
18
|
-
|
|
14
|
+
Nami is simple adopt while giving you the tools you need to improve revenue. Our free tier is generous, and gives you everything you need to get started. [Sign up for a free account](https://app.namiml.com/join/)
|
|
15
|
+
|
|
16
|
+
Get started by heading over to our [quick start guide](https://learn.namiml.com/public-docs/get-started/quickstart-guide)
|
|
19
17
|
|
|
20
18
|
## Getting started with React Native and Nami
|
|
21
19
|
|
package/android/build.gradle
CHANGED
|
@@ -37,7 +37,7 @@ android {
|
|
|
37
37
|
buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION)
|
|
38
38
|
defaultConfig {
|
|
39
39
|
minSdkVersion 22
|
|
40
|
-
targetSdkVersion
|
|
40
|
+
targetSdkVersion 34
|
|
41
41
|
versionCode 1
|
|
42
42
|
versionName "1.0"
|
|
43
43
|
}
|
|
@@ -85,8 +85,8 @@ dependencies {
|
|
|
85
85
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
86
86
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
|
87
87
|
|
|
88
|
-
playImplementation "com.namiml:sdk-android:3.2.
|
|
89
|
-
amazonImplementation "com.namiml:sdk-amazon:3.2.
|
|
88
|
+
playImplementation "com.namiml:sdk-android:3.2.3.1"
|
|
89
|
+
amazonImplementation "com.namiml:sdk-amazon:3.2.3.1"
|
|
90
90
|
|
|
91
91
|
implementation "com.facebook.react:react-native:+" // From node_modules
|
|
92
92
|
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
|
|
@@ -106,7 +106,7 @@ class NamiBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
106
106
|
} else {
|
|
107
107
|
Arguments.createArray()
|
|
108
108
|
}
|
|
109
|
-
val settingsList = mutableListOf("extendedClientInfo:react-native:3.2.
|
|
109
|
+
val settingsList = mutableListOf("extendedClientInfo:react-native:3.2.3")
|
|
110
110
|
namiCommandsReact?.toArrayList()?.filterIsInstance<String>()?.let { commandsFromReact ->
|
|
111
111
|
settingsList.addAll(commandsFromReact)
|
|
112
112
|
}
|
|
@@ -21,7 +21,7 @@ class NamiCampaignManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
21
21
|
const val CAMPAIGN_LABEL = "campaignLabel"
|
|
22
22
|
const val PAYWALL_ID = "paywallId"
|
|
23
23
|
const val ACTION = "action"
|
|
24
|
-
const val
|
|
24
|
+
const val SKU = "sku"
|
|
25
25
|
const val PURCHASE_ERROR = "purchaseError"
|
|
26
26
|
const val PURCHASES = "purchases"
|
|
27
27
|
const val CAMPAIGN_NAME = "campaignName"
|
|
@@ -51,7 +51,13 @@ class NamiCampaignManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
@ReactMethod
|
|
54
|
-
fun launch(
|
|
54
|
+
fun launch(
|
|
55
|
+
label: String?,
|
|
56
|
+
withUrl: String?,
|
|
57
|
+
context: ReadableMap?,
|
|
58
|
+
resultCallback: Callback,
|
|
59
|
+
actionCallback: Callback,
|
|
60
|
+
) {
|
|
55
61
|
var theActivity: Activity? = null
|
|
56
62
|
if (reactApplicationContext.hasCurrentActivity()) {
|
|
57
63
|
theActivity = reactApplicationContext.getCurrentActivity()
|
|
@@ -61,7 +67,7 @@ class NamiCampaignManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
61
67
|
if (context != null) {
|
|
62
68
|
val productGroups: MutableList<String> = mutableListOf()
|
|
63
69
|
val customAttributes: MutableMap<String, String> = mutableMapOf()
|
|
64
|
-
|
|
70
|
+
var customObject: MutableMap<String, Any> = mutableMapOf()
|
|
65
71
|
|
|
66
72
|
if (context.hasKey("productGroups")) {
|
|
67
73
|
val groups = context.getArray("productGroups")
|
|
@@ -91,12 +97,11 @@ class NamiCampaignManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
91
97
|
if (context.hasKey("customObject")) {
|
|
92
98
|
val attr = context.getMap("customObject")
|
|
93
99
|
if (attr != null) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
100
|
+
try {
|
|
101
|
+
customObject = attr.toHashMap().toMutableMap()
|
|
102
|
+
} catch (e: Exception) {
|
|
103
|
+
Log.d(LOG_TAG, "Unable to parse PaywallLaunchContext customObject $customObject")
|
|
98
104
|
}
|
|
99
|
-
Log.d(LOG_TAG, "customObject $customObject")
|
|
100
105
|
}
|
|
101
106
|
}
|
|
102
107
|
|
|
@@ -148,48 +153,59 @@ class NamiCampaignManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
148
153
|
actionCallback: Callback,
|
|
149
154
|
) {
|
|
150
155
|
val actionString = paywallEvent.action.toString()
|
|
151
|
-
val skuString = paywallEvent.sku?.skuId ?: ""
|
|
152
156
|
|
|
153
157
|
val purchasesArray = createPurchaseArray(paywallEvent.purchases)
|
|
154
158
|
|
|
155
|
-
val resultMap =
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
159
|
+
val resultMap =
|
|
160
|
+
Arguments.createMap().apply {
|
|
161
|
+
putString(CAMPAIGN_ID, paywallEvent.campaignId)
|
|
162
|
+
putString(CAMPAIGN_LABEL, paywallEvent.campaignLabel ?: "")
|
|
163
|
+
putString(PAYWALL_ID, paywallEvent.paywallId)
|
|
164
|
+
putString(ACTION, actionString)
|
|
165
|
+
putString(PURCHASE_ERROR, paywallEvent.purchaseError ?: "")
|
|
166
|
+
putArray(PURCHASES, purchasesArray)
|
|
167
|
+
putString(CAMPAIGN_NAME, paywallEvent.campaignName ?: "")
|
|
168
|
+
putString(CAMPAIGN_TYPE, paywallEvent.campaignType ?: "")
|
|
169
|
+
putString(CAMPAIGN_URL, paywallEvent.campaignUrl ?: "")
|
|
170
|
+
putString(PAYWALL_NAME, paywallEvent.paywallName ?: "")
|
|
171
|
+
putString(SEGMENT_ID, paywallEvent.segmentId ?: "")
|
|
172
|
+
putString(EXTERNAL_SEGMENT_ID, paywallEvent.externalSegmentId ?: "")
|
|
173
|
+
putString(DEEP_LINK_URL, paywallEvent.deeplinkUrl ?: "")
|
|
174
|
+
}
|
|
170
175
|
|
|
176
|
+
if (paywallEvent.sku != null) {
|
|
177
|
+
val skuMap =
|
|
178
|
+
Arguments.createMap().apply {
|
|
179
|
+
putString("id", paywallEvent.sku?.id ?: "")
|
|
180
|
+
putString("skuId", paywallEvent.sku?.skuId ?: "")
|
|
181
|
+
putString("name", paywallEvent.sku?.name ?: "")
|
|
182
|
+
putString("type", paywallEvent.sku?.type.toString().lowercase())
|
|
183
|
+
}
|
|
184
|
+
resultMap.putMap(SKU, skuMap)
|
|
171
185
|
}
|
|
172
186
|
|
|
173
187
|
if (paywallEvent.componentChange != null) {
|
|
174
|
-
val componentChangeMap =
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
188
|
+
val componentChangeMap =
|
|
189
|
+
Arguments.createMap().apply {
|
|
190
|
+
putString("id", paywallEvent.componentChange?.id ?: "")
|
|
191
|
+
putString("name", paywallEvent.componentChange?.name ?: "")
|
|
192
|
+
}
|
|
178
193
|
|
|
179
194
|
resultMap.putMap(COMPONENT_CHANGE, componentChangeMap)
|
|
180
195
|
}
|
|
181
196
|
|
|
182
197
|
if (paywallEvent.videoMetadata != null) {
|
|
183
|
-
val videoMetadataMap =
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
val videoMetadataMap =
|
|
199
|
+
Arguments.createMap().apply {
|
|
200
|
+
putString("id", paywallEvent.videoMetadata?.id ?: "")
|
|
201
|
+
putString("name", paywallEvent.videoMetadata?.name ?: "")
|
|
202
|
+
putString("url", paywallEvent.videoMetadata?.url ?: "")
|
|
203
|
+
putBoolean("autoplayVideo", paywallEvent.videoMetadata?.autoplayVideo ?: false)
|
|
204
|
+
putBoolean("muteByDefault", paywallEvent.videoMetadata?.muteByDefault ?: false)
|
|
205
|
+
putBoolean("loopVideo", paywallEvent.videoMetadata?.loopVideo ?: false)
|
|
206
|
+
putDouble("contentDuration", paywallEvent.videoMetadata?.contentDuration ?: 0.0)
|
|
207
|
+
putDouble("contentTimecode", paywallEvent.videoMetadata?.contentTimecode ?: 0.0)
|
|
208
|
+
}
|
|
193
209
|
|
|
194
210
|
resultMap.putMap(VIDEO_METADATA, videoMetadataMap)
|
|
195
211
|
}
|
|
@@ -213,7 +229,10 @@ class NamiCampaignManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
213
229
|
}
|
|
214
230
|
}
|
|
215
231
|
|
|
216
|
-
private fun emitEvent(
|
|
232
|
+
private fun emitEvent(
|
|
233
|
+
event: String,
|
|
234
|
+
map: WritableMap,
|
|
235
|
+
) {
|
|
217
236
|
val emitter = reactApplicationContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
218
237
|
if (emitter is DeviceEventManagerModule.RCTDeviceEventEmitter) {
|
|
219
238
|
emitter.emit(event, map)
|
|
@@ -222,7 +241,10 @@ class NamiCampaignManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
222
241
|
}
|
|
223
242
|
}
|
|
224
243
|
|
|
225
|
-
private fun handleResult(
|
|
244
|
+
private fun handleResult(
|
|
245
|
+
result: LaunchCampaignResult,
|
|
246
|
+
resultCallback: Callback,
|
|
247
|
+
) {
|
|
226
248
|
val resultMap = Arguments.createMap()
|
|
227
249
|
when (result) {
|
|
228
250
|
is LaunchCampaignResult.Success -> {
|
|
@@ -258,18 +280,22 @@ class NamiCampaignManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
258
280
|
}
|
|
259
281
|
|
|
260
282
|
@ReactMethod
|
|
261
|
-
fun isCampaignAvailable(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
283
|
+
fun isCampaignAvailable(
|
|
284
|
+
campaignSource: String?,
|
|
285
|
+
promise: Promise,
|
|
286
|
+
) {
|
|
287
|
+
val isCampaignAvailable =
|
|
288
|
+
when {
|
|
289
|
+
campaignSource == null -> NamiCampaignManager.isCampaignAvailable()
|
|
290
|
+
Uri.parse(campaignSource)?.scheme != null -> NamiCampaignManager.isCampaignAvailable(Uri.parse(campaignSource))
|
|
291
|
+
else -> NamiCampaignManager.isCampaignAvailable(campaignSource)
|
|
292
|
+
}
|
|
267
293
|
promise.resolve(isCampaignAvailable)
|
|
268
294
|
}
|
|
269
295
|
|
|
270
296
|
@ReactMethod
|
|
271
297
|
fun refresh() {
|
|
272
|
-
NamiCampaignManager.refresh
|
|
298
|
+
NamiCampaignManager.refresh { }
|
|
273
299
|
}
|
|
274
300
|
|
|
275
301
|
@ReactMethod
|
package/build-utils/preflight.py
CHANGED
|
@@ -6,6 +6,7 @@ import subprocess
|
|
|
6
6
|
|
|
7
7
|
# Regex to validate version numbers
|
|
8
8
|
PROD_VERSION_RE = re.compile(r"^\d+\.\d+\.\d+$")
|
|
9
|
+
PROD_VERSION_EXT_RE = re.compile(r"^\d+\.\d+\.\d+-\d$")
|
|
9
10
|
PRERELEASE_VERSION_RE = re.compile(r"^\d+\.\d+\.\d+-(alpha|beta|rc)\.\d+$")
|
|
10
11
|
|
|
11
12
|
early_access = str(os.getenv("EARLY_ACCESS"))
|
|
@@ -21,7 +22,7 @@ git_long_hash = (
|
|
|
21
22
|
)
|
|
22
23
|
|
|
23
24
|
# Check what kind of release this is and guard against non-conforming version numbers
|
|
24
|
-
if PROD_VERSION_RE.match(nami_sdk_version):
|
|
25
|
+
if PROD_VERSION_RE.match(nami_sdk_version) or PROD_VERSION_EXT_RE.match(nami_sdk_version):
|
|
25
26
|
if early_access == "true":
|
|
26
27
|
print(f"Early access value ('{early_access}') is not compatible with production version format '{nami_sdk_version}'")
|
|
27
28
|
sys.exit(1)
|
package/ios/Nami.m
CHANGED
|
@@ -50,7 +50,7 @@ RCT_EXPORT_METHOD(configure: (NSDictionary *)configDict completion: (RCTResponse
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
// Start commands with header iformation for Nami to let them know this is a React client.
|
|
53
|
-
NSMutableArray *namiCommandStrings = [NSMutableArray arrayWithArray:@[@"extendedClientInfo:react-native:3.2.
|
|
53
|
+
NSMutableArray *namiCommandStrings = [NSMutableArray arrayWithArray:@[@"extendedClientInfo:react-native:3.2.3"]];
|
|
54
54
|
|
|
55
55
|
// Add additional namiCommands app may have sent in.
|
|
56
56
|
NSObject *appCommandStrings = configDict[@"namiCommands"];
|
|
@@ -106,6 +106,15 @@ class RNNamiCampaignManager: RCTEventEmitter {
|
|
|
106
106
|
|
|
107
107
|
let dictionaries = paywallEvent.purchases.map { purchase in RNNamiPurchaseManager.purchaseToPurchaseDict(purchase) }
|
|
108
108
|
|
|
109
|
+
var skuDict: [String: Any?] = [:]
|
|
110
|
+
|
|
111
|
+
if let sku = paywallEvent.sku {
|
|
112
|
+
skuDict["id"] = sku.id
|
|
113
|
+
skuDict["name"] = sku.name
|
|
114
|
+
skuDict["skuId"] = sku.skuId
|
|
115
|
+
skuDict["type"] = sku.type.description
|
|
116
|
+
}
|
|
117
|
+
|
|
109
118
|
var componentChange: [String: Any?] = [:]
|
|
110
119
|
|
|
111
120
|
if let eventComponentChange = paywallEvent.componentChange {
|
|
@@ -137,7 +146,7 @@ class RNNamiCampaignManager: RCTEventEmitter {
|
|
|
137
146
|
"segmentId": paywallEvent.segmentId,
|
|
138
147
|
"externalSegmentId": paywallEvent.externalSegmentId,
|
|
139
148
|
"action": actionString,
|
|
140
|
-
"
|
|
149
|
+
"sku": skuDict,
|
|
141
150
|
"purchaseError": errorSting,
|
|
142
151
|
"purchases": dictionaries,
|
|
143
152
|
"deeplinkUrl": paywallEvent.deeplinkUrl,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nami-sdk",
|
|
3
|
-
"version": "3.2.2",
|
|
3
|
+
"version": "3.2.3-2",
|
|
4
4
|
"description": "React Native Module for Nami - Easy subscriptions & in-app purchases, with powerful built-in paywalls and A/B testing.",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"types": "index.d.ts",
|