react-native-nami-sdk 3.3.3-4 → 3.3.3-6

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.
@@ -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.3.3.3"
89
- amazonImplementation "com.namiml:sdk-amazon:3.3.3.3"
88
+ playImplementation "com.namiml:sdk-android:3.3.3.5"
89
+ amazonImplementation "com.namiml:sdk-amazon:3.3.3.5"
90
90
 
91
91
  implementation "com.facebook.react:react-native:+" // From node_modules
92
92
  coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.0.4"
@@ -3,23 +3,24 @@ package com.namiml.reactnative
3
3
  import android.app.Activity
4
4
  import android.net.Uri
5
5
  import android.util.Log
6
+ import androidx.core.net.toUri
6
7
  import com.facebook.react.bridge.*
7
8
  import com.facebook.react.module.annotations.ReactModule
8
9
  import com.facebook.react.modules.core.DeviceEventManagerModule
9
10
  import com.facebook.react.turbomodule.core.interfaces.TurboModule
10
11
  import com.namiml.billing.NamiPurchase
12
+ import com.namiml.campaign.LaunchCampaignError
11
13
  import com.namiml.campaign.LaunchCampaignResult
12
14
  import com.namiml.campaign.NamiCampaign
13
15
  import com.namiml.campaign.NamiCampaignManager
14
16
  import com.namiml.paywall.model.NamiPaywallEvent
15
17
  import com.namiml.paywall.model.PaywallLaunchContext
16
- import androidx.core.net.toUri
17
18
 
18
19
  @ReactModule(name = NamiCampaignManagerBridgeModule.NAME)
19
20
  class NamiCampaignManagerBridgeModule internal constructor(
20
- private val reactContext: ReactApplicationContext
21
- ) : ReactContextBaseJavaModule(reactContext), TurboModule {
22
-
21
+ private val reactContext: ReactApplicationContext,
22
+ ) : ReactContextBaseJavaModule(reactContext),
23
+ TurboModule {
23
24
  companion object {
24
25
  const val NAME = "RNNamiCampaignManager"
25
26
  const val CAMPAIGN_ID = "campaignId"
@@ -42,10 +43,7 @@ class NamiCampaignManagerBridgeModule internal constructor(
42
43
  const val NAMI_PAYWALL_EVENT = "NamiPaywallEvent"
43
44
  }
44
45
 
45
-
46
- override fun getName(): String {
47
- return NAME
48
- }
46
+ override fun getName(): String = NAME
49
47
 
50
48
  private fun campaignToReadableMap(campaign: NamiCampaign): ReadableMap {
51
49
  val readableMap = Arguments.createMap()
@@ -94,7 +92,37 @@ class NamiCampaignManagerBridgeModule internal constructor(
94
92
  val keyIterator = attr.keySetIterator()
95
93
  while (keyIterator.hasNextKey()) {
96
94
  val key = keyIterator.nextKey()
97
- customAttributes[key] = attr.getString(key) ?: ""
95
+ try {
96
+ // Handle different data types and store with proper types
97
+ val value: Any =
98
+ when (attr.getType(key)) {
99
+ ReadableType.String -> attr.getString(key) ?: ""
100
+ ReadableType.Boolean -> attr.getBoolean(key)
101
+ ReadableType.Number -> {
102
+ // Try to get as int first, then as double
103
+ try {
104
+ attr.getInt(key)
105
+ } catch (e: Exception) {
106
+ attr.getDouble(key)
107
+ }
108
+ }
109
+ ReadableType.Null -> ""
110
+ ReadableType.Array -> attr.getArray(key)?.toArrayList() ?: emptyList<Any>()
111
+ ReadableType.Map -> attr.getMap(key)?.toHashMap() ?: emptyMap<String, Any>()
112
+ }
113
+ customAttributes[key] = value
114
+ } catch (e: Exception) {
115
+ // Log the error and try to store the value as a string representation
116
+ Log.w(NAME, "Error parsing customAttribute '$key': ${e.message}. Attempting string conversion.")
117
+ try {
118
+ // Fallback: try to get the dynamic value and convert to string
119
+ val dynamicValue = attr.getDynamic(key)
120
+ customAttributes[key] = dynamicValue.asString() ?: ""
121
+ } catch (fallbackError: Exception) {
122
+ // If all else fails, log and skip this attribute
123
+ Log.e(NAME, "Failed to parse customAttribute '$key': ${fallbackError.message}. Skipping.")
124
+ }
125
+ }
98
126
  }
99
127
  Log.d(NAME, "customAttributes $customAttributes")
100
128
  }
@@ -120,8 +148,7 @@ class NamiCampaignManagerBridgeModule internal constructor(
120
148
 
121
149
  if (theActivity != null) {
122
150
  reactApplicationContext.runOnUiQueueThread {
123
- val paywallActionCallback = {
124
- paywallEvent: NamiPaywallEvent ->
151
+ val paywallActionCallback = { paywallEvent: NamiPaywallEvent ->
125
152
  handlePaywallCallback(
126
153
  paywallEvent,
127
154
  actionCallback,
@@ -184,7 +211,13 @@ class NamiCampaignManagerBridgeModule internal constructor(
184
211
  putString("id", paywallEvent.sku?.id ?: "")
185
212
  putString("skuId", paywallEvent.sku?.skuId ?: "")
186
213
  putString("name", paywallEvent.sku?.name ?: "")
187
- putString("type", paywallEvent.sku?.type.toString().lowercase())
214
+ putString(
215
+ "type",
216
+ paywallEvent.sku
217
+ ?.type
218
+ .toString()
219
+ .lowercase(),
220
+ )
188
221
  }
189
222
  resultMap.putMap(SKU, skuMap)
190
223
  }
@@ -222,8 +255,8 @@ class NamiCampaignManagerBridgeModule internal constructor(
222
255
  emitEvent(NAMI_PAYWALL_EVENT, resultMap)
223
256
  }
224
257
 
225
- private fun createPurchaseArray(purchases: List<NamiPurchase>?): WritableArray {
226
- return WritableNativeArray().apply {
258
+ private fun createPurchaseArray(purchases: List<NamiPurchase>?): WritableArray =
259
+ WritableNativeArray().apply {
227
260
  purchases?.forEach { purchase ->
228
261
  try {
229
262
  pushMap(purchase.toPurchaseDict())
@@ -232,7 +265,6 @@ class NamiCampaignManagerBridgeModule internal constructor(
232
265
  }
233
266
  }
234
267
  }
235
- }
236
268
 
237
269
  private fun emitEvent(
238
270
  event: String,
@@ -246,17 +278,46 @@ class NamiCampaignManagerBridgeModule internal constructor(
246
278
  }
247
279
  }
248
280
 
281
+ /**
282
+ * Maps Android LaunchCampaignError enum values to iOS-compatible error codes
283
+ * to ensure consistent error handling across platforms in React Native.
284
+ */
285
+ private fun mapErrorCodeToIOS(androidError: LaunchCampaignError): Int =
286
+ when (androidError) {
287
+ LaunchCampaignError.DEFAULT_CAMPAIGN_NOT_FOUND -> 0
288
+ LaunchCampaignError.LABELED_CAMPAIGN_NOT_FOUND -> 1
289
+ LaunchCampaignError.CAMPAIGN_DATA_NOT_FOUND -> 2
290
+ LaunchCampaignError.PAYWALL_ALREADY_DISPLAYED -> 3
291
+ LaunchCampaignError.SDK_NOT_INITIALIZED -> 4
292
+ LaunchCampaignError.URL_CAMPAIGN_NOT_FOUND -> 6
293
+ LaunchCampaignError.PRODUCT_GROUPS_NOT_FOUND -> 8
294
+ }
295
+
249
296
  private fun handleResult(
250
297
  result: LaunchCampaignResult,
251
298
  resultCallback: Callback,
252
299
  ) {
253
- val resultMap = Arguments.createMap()
254
300
  when (result) {
255
301
  is LaunchCampaignResult.Success -> {
256
302
  resultCallback.invoke(true)
257
303
  }
258
304
  is LaunchCampaignResult.Failure -> {
259
- resultCallback.invoke(false, "${result.error}")
305
+ val error = result.error
306
+ val errorInfo =
307
+ if (error is LaunchCampaignError) {
308
+ Arguments.createMap().apply {
309
+ putInt("code", mapErrorCodeToIOS(error))
310
+ putString("domain", "LaunchCampaignError")
311
+ putString("message", error.errorMessage.ifEmpty { error.toString() })
312
+ }
313
+ } else {
314
+ Arguments.createMap().apply {
315
+ putInt("code", -1)
316
+ putString("domain", "Unknown")
317
+ putString("message", error.toString())
318
+ }
319
+ }
320
+ resultCallback.invoke(false, errorInfo)
260
321
  }
261
322
  }
262
323
  }
@@ -279,8 +340,8 @@ class NamiCampaignManagerBridgeModule internal constructor(
279
340
  val isCampaignAvailable =
280
341
  when {
281
342
  campaignSource == null -> NamiCampaignManager.isCampaignAvailable()
282
- campaignSource.toUri().scheme != null -> NamiCampaignManager.isCampaignAvailable(
283
- campaignSource.toUri())
343
+ campaignSource.toUri().scheme != null ->
344
+ NamiCampaignManager.isCampaignAvailable(campaignSource.toUri())
284
345
  else -> NamiCampaignManager.isCampaignAvailable(campaignSource)
285
346
  }
286
347
  promise.resolve(isCampaignAvailable)
@@ -2,4 +2,4 @@
2
2
  * Auto-generated file. Do not edit manually.
3
3
  * React Native Nami SDK version.
4
4
  */
5
- export declare const NAMI_REACT_NATIVE_VERSION = "3.3.3-4";
5
+ export declare const NAMI_REACT_NATIVE_VERSION = "3.3.3-6";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nami-sdk",
3
- "version": "3.3.3-4",
3
+ "version": "3.3.3-6",
4
4
  "description": "React Native SDK for Nami - No-code paywall management with A/B testing.",
5
5
  "main": "index.ts",
6
6
  "types": "dist/index.d.ts",
package/src/version.ts CHANGED
@@ -2,4 +2,4 @@
2
2
  * Auto-generated file. Do not edit manually.
3
3
  * React Native Nami SDK version.
4
4
  */
5
- export const NAMI_REACT_NATIVE_VERSION = '3.3.3-4';
5
+ export const NAMI_REACT_NATIVE_VERSION = '3.3.3-6';