@purchasely/cordova-plugin-purchasely 4.4.0 → 5.1.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.
@@ -16,17 +16,17 @@
16
16
  "@purchasely/cordova-plugin-puchasely-google": "file:../../purchasely-google",
17
17
  "@purchasely/cordova-plugin-purchasely": "file:..",
18
18
  "cordova-android": "^13.0.0",
19
- "cordova-ios": "^7.1.0",
19
+ "cordova-ios": "^7.0.1",
20
20
  "cordova-plugin-puchasely-google": "file:../../purchasely-google",
21
21
  "cordova-plugin-purchasely": "file:.."
22
22
  },
23
23
  "cordova": {
24
24
  "plugins": {
25
- "@purchasely/cordova-plugin-puchasely-google": {},
26
- "@purchasely/cordova-plugin-purchasely": {}
25
+ "@purchasely/cordova-plugin-puchasely-google": {}
27
26
  },
28
27
  "platforms": [
29
- "android"
28
+ "android",
29
+ "ios"
30
30
  ]
31
31
  }
32
- }
32
+ }
@@ -17,6 +17,7 @@
17
17
  * under the License.
18
18
  */
19
19
 
20
+
20
21
  // Wait for the deviceready event before using any of Cordova's device APIs.
21
22
  // See https://cordova.apache.org/docs/en/latest/cordova/events/events.html#deviceready
22
23
  document.addEventListener('deviceready', onDeviceReady, false);
@@ -74,6 +75,21 @@ function onPuchaselySdkReady() {
74
75
  console.log(error);
75
76
  });
76
77
 
78
+ Purchasely.addUserAttributeListener((attribute) => {
79
+ if (attribute.action == Purchasely.UserAttributeAction.ADD) {
80
+ console.log("ADD Attribute: " + attribute.key)
81
+ console.log("ADD Attribute: " + attribute.value)
82
+ console.log("ADD Attribute: " + attribute.source)
83
+ console.log("ADD Attribute: " + attribute.type)
84
+ } else if (attribute.action == Purchasely.UserAttributeAction.REMOVE) {
85
+ console.log("REMOVE Attribute: " + attribute.key)
86
+ console.log("REMOVE Attribute: " + attribute.source)
87
+ }
88
+
89
+ }, (error) => {
90
+ console.log("Error: " + error)
91
+ })
92
+
77
93
  Purchasely.purchasedSubscription(() => {
78
94
  console.log("Purchased performed, reload content to unlock.");
79
95
  });
@@ -86,7 +102,27 @@ function onPuchaselySdkReady() {
86
102
 
87
103
  Purchasely.setLogLevel(Purchasely.LogLevel.DEBUG);
88
104
 
89
- Purchasely.setAttribute(Purchasely.Attribute.FIREBASE_APP_INSTANCE_ID, "1");
105
+ Purchasely.setAttribute(Purchasely.Attribute.FIREBASE_APP_INSTANCE_ID, "firebase_instance_id");
106
+ Purchasely.setAttribute(Purchasely.Attribute.AIRSHIP_CHANNEL_ID, "airship_channel_id");
107
+ Purchasely.setAttribute(Purchasely.Attribute.AIRSHIP_USER_ID, "airship_user_id");
108
+ Purchasely.setAttribute(Purchasely.Attribute.BATCH_INSTALLATION_ID, "batch_installation_id");
109
+ Purchasely.setAttribute(Purchasely.Attribute.ADJUST_ID, "adjust_id");
110
+ Purchasely.setAttribute(Purchasely.Attribute.APPSFLYER_ID, "appsflyer_id");
111
+ Purchasely.setAttribute(Purchasely.Attribute.MIXPANEL_DISTINCT_ID, "mixpanel_distinct_id");
112
+ Purchasely.setAttribute(Purchasely.Attribute.CLEVER_TAP_ID, "clever_tap_id");
113
+ Purchasely.setAttribute(Purchasely.Attribute.SENDINBLUE_USER_EMAIL, "sendinblue_user_email");
114
+ Purchasely.setAttribute(Purchasely.Attribute.ITERABLE_USER_EMAIL, "iterable_user_email");
115
+ Purchasely.setAttribute(Purchasely.Attribute.ITERABLE_USER_ID, "iterable_user_id");
116
+ Purchasely.setAttribute(Purchasely.Attribute.AT_INTERNET_ID_CLIENT, "at_internet_id_client");
117
+ Purchasely.setAttribute(Purchasely.Attribute.MPARTICLE_USER_ID, "mparticle_user_id");
118
+ Purchasely.setAttribute(Purchasely.Attribute.CUSTOMERIO_USER_ID, "customerio_user_id");
119
+ Purchasely.setAttribute(Purchasely.Attribute.CUSTOMERIO_USER_EMAIL, "customerio_user_email");
120
+ Purchasely.setAttribute(Purchasely.Attribute.BRANCH_USER_DEVELOPER_IDENTITY, "branch_user_developer_identity");
121
+ Purchasely.setAttribute(Purchasely.Attribute.AMPLITUDE_USER_ID, "amplitude_user_id");
122
+ Purchasely.setAttribute(Purchasely.Attribute.AMPLITUDE_DEVICE_ID, "amplitude_device_id");
123
+ Purchasely.setAttribute(Purchasely.Attribute.MOENGAGE_UNIQUE_ID, "moengage_unique_id");
124
+ Purchasely.setAttribute(Purchasely.Attribute.ONESIGNAL_EXTERNAL_ID, "onesignal_external_id");
125
+ Purchasely.setAttribute(Purchasely.Attribute.BATCH_CUSTOM_USER_ID, "batch_custom_user_id");
90
126
  Purchasely.setAttribute(Purchasely.Attribute.BATCH_INSTALLATION_ID, "testBatch1");
91
127
 
92
128
  Purchasely.readyToOpenDeeplink(true);
@@ -119,26 +155,55 @@ function onPuchaselySdkReady() {
119
155
  console.log("Error with purchase : " + error);
120
156
  });
121
157
 
158
+ Purchasely.setUserAttributeWithString("key_string", "value_string");
159
+ Purchasely.setUserAttributeWithBoolean("key_boolean", true);
160
+ Purchasely.setUserAttributeWithInt("key_int", 7);
161
+ Purchasely.setUserAttributeWithDouble("key_double", 4.5);
162
+ Purchasely.setUserAttributeWithDate("key_date", new Date().toISOString());
163
+
164
+ Purchasely.clearUserAttributes();
165
+
122
166
  Purchasely.setUserAttributeWithString("key_string", "value_string");
123
167
  Purchasely.setUserAttributeWithBoolean("key_boolean", true);
124
168
  Purchasely.setUserAttributeWithInt("key_int", 7);
125
169
  Purchasely.setUserAttributeWithDouble("key_double", 4.5);
126
170
  Purchasely.setUserAttributeWithDate("key_date", new Date().toISOString());
127
171
 
172
+ Purchasely.setUserAttributeWithStringArray("key_string_array", ["value1", "value2"]);
173
+ Purchasely.setUserAttributeWithIntArray("key_int_array", [1, 2, 3]);
174
+ Purchasely.setUserAttributeWithDoubleArray("key_double_array", [1.1, 2.2, 3.3]);
175
+ Purchasely.setUserAttributeWithBooleanArray("key_boolean_array", [true, false, true]);
176
+
128
177
  Purchasely.userAttribute("key_string", value => {
129
- console.log("User attribute string " + value);
178
+ console.log("User attribute string: " + value);
130
179
  });
131
180
 
132
181
  Purchasely.userAttribute("key_boolean", value => {
133
- console.log("User attribute boolean " + value);
182
+ console.log("User attribute boolean: " + value);
134
183
  });
135
184
 
136
185
  Purchasely.userAttribute("key_int", value => {
137
- console.log("User attribute int " + value);
186
+ console.log("User attribute int: " + value);
138
187
  });
139
188
 
140
189
  Purchasely.userAttribute("key_double", value => {
141
- console.log("User attribute double " + value);
190
+ console.log("User attribute double: " + value);
191
+ });
192
+
193
+ Purchasely.userAttribute("key_string_array", value => {
194
+ console.log("User attribute string array: " + value);
195
+ });
196
+
197
+ Purchasely.userAttribute("key_int_array", value => {
198
+ console.log("User attribute int array: " + value);
199
+ });
200
+
201
+ Purchasely.userAttribute("key_double_array", value => {
202
+ console.log("User attribute double array: " + value);
203
+ });
204
+
205
+ Purchasely.userAttribute("key_boolean_array", value => {
206
+ console.log("User attribute boolean array: " + value);
142
207
  });
143
208
 
144
209
  Purchasely.userAttribute("key_date", value => {
@@ -155,6 +220,8 @@ function onPuchaselySdkReady() {
155
220
  });
156
221
  });
157
222
 
223
+ Purchasely.removeUserAttributeListener();
224
+
158
225
  Purchasely.setPaywallActionInterceptor((result) => {
159
226
  console.log(result);
160
227
  console.log('Received action from paywall ' + result.info.presentationId);
@@ -193,6 +260,8 @@ function onPuchaselySdkReady() {
193
260
  Purchasely.onProcessAction(true);
194
261
  }
195
262
  });
263
+
264
+ Purchasely.clearBuiltInAttributes();
196
265
  }
197
266
 
198
267
  function openPresentation() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purchasely/cordova-plugin-purchasely",
3
- "version": "4.4.0",
3
+ "version": "5.1.0",
4
4
  "description": "Purchasely is a solution to ease the integration and boost your In-App Purchases & Subscriptions on the App Store, Google Play Store, Amazon Appstore and Huawei App Gallery.",
5
5
  "cordova": {
6
6
  "id": "@purchasely/cordova-plugin-purchasely",
package/plugin.xml CHANGED
@@ -1,5 +1,5 @@
1
1
  <?xml version='1.0' encoding='utf-8'?>
2
- <plugin id="@purchasely/cordova-plugin-purchasely" version="4.4.0" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
2
+ <plugin id="@purchasely/cordova-plugin-purchasely" version="5.1.0" xmlns="http://apache.org/cordova/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
3
3
  <name>Purchasely</name>
4
4
  <js-module name="Purchasely" src="www/Purchasely.js">
5
5
  <clobbers target="Purchasely" />
@@ -18,6 +18,8 @@
18
18
  <source-file src="src/ios/CDVPurchasely.m" />
19
19
  <header-file src="src/ios/CDVPurchasely+Events.h" />
20
20
  <source-file src="src/ios/CDVPurchasely+Events.m" />
21
+ <header-file src="src/ios/CDVPurchasely+UserAttributes.h" />
22
+ <source-file src="src/ios/CDVPurchasely+UserAttributes.m" />
21
23
  <header-file src="src/ios/Hybrid/Purchasely_Hybrid.h" />
22
24
  <header-file src="src/ios/Hybrid/UIViewController+Hybrid.h" />
23
25
  <source-file src="src/ios/Hybrid/UIViewController+Hybrid.m" />
@@ -36,7 +38,7 @@
36
38
  <source url="https://github.com/CocoaPods/Specs.git"/>
37
39
  </config>
38
40
  <pods use-frameworks="true">
39
- <pod name="Purchasely" spec="4.4.2"/>
41
+ <pod name="Purchasely" spec="5.1.0"/>
40
42
  </pods>
41
43
  </podspec>
42
44
  </platform>
@@ -61,7 +63,7 @@
61
63
  android:theme="@style/Theme.AppCompat.Light.NoActionBar">
62
64
  </activity>
63
65
  </config-file>
64
- <framework src="io.purchasely:core:4.4.2" />
66
+ <framework src="io.purchasely:core:5.1.0" />
65
67
  <source-file src="src/android/PurchaselyPlugin.kt" target-dir="java/cordova/plugin/purchasely" />
66
68
  <source-file src="src/android/PLYProductActivity.kt" target-dir="java/cordova/plugin/purchasely" />
67
69
  <source-file src="src/android/PLYSubscriptionsActivity.java" target-dir="src/cordova/plugin/purchasely" />
@@ -10,7 +10,7 @@ import androidx.appcompat.app.AppCompatActivity
10
10
  import androidx.core.view.WindowCompat
11
11
  import cordova.plugin.purchasely.PurchaselyPlugin.ProductActivity
12
12
  import io.purchasely.ext.PLYPresentation
13
- import io.purchasely.ext.PLYPresentationViewProperties
13
+ import io.purchasely.ext.PLYPresentationProperties
14
14
  import io.purchasely.ext.PLYProductViewResult
15
15
  import io.purchasely.ext.Purchasely
16
16
  import io.purchasely.models.PLYPlan
@@ -77,21 +77,21 @@ class PLYProductActivity : AppCompatActivity() {
77
77
  presentation = intent.extras?.getParcelable("presentation")
78
78
 
79
79
  paywallView = if(presentation != null) {
80
- presentation?.buildView(this, viewProperties = PLYPresentationViewProperties(onClose = {
80
+ presentation?.buildView(this, properties = PLYPresentationProperties(onClose = {
81
81
  container.removeAllViews()
82
82
  supportFinishAfterTransition()
83
83
  }), callback)
84
84
  } else {
85
85
  Purchasely.presentationView(
86
- this@PLYProductActivity,
87
- PLYPresentationViewProperties(
86
+ context = this@PLYProductActivity,
87
+ properties = PLYPresentationProperties(
88
88
  placementId = placementId,
89
89
  contentId = contentId,
90
90
  presentationId = presentationId,
91
91
  planId = planId,
92
92
  productId = productId,
93
93
  onLoaded = { isLoaded ->
94
- if(!isLoaded) return@PLYPresentationViewProperties
94
+ if(!isLoaded) return@PLYPresentationProperties
95
95
 
96
96
  val backgroundPaywall = paywallView?.findViewById<FrameLayout>(io.purchasely.R.id.content)?.background
97
97
  if(backgroundPaywall != null) {
@@ -103,7 +103,7 @@ class PLYProductActivity : AppCompatActivity() {
103
103
  supportFinishAfterTransition()
104
104
  }
105
105
  ),
106
- callback
106
+ callback = callback
107
107
  )
108
108
  }
109
109
 
@@ -142,7 +142,7 @@ class PLYProductActivity : AppCompatActivity() {
142
142
  companion object {
143
143
  @JvmStatic
144
144
  fun newIntent(activity: Activity?,
145
- properties: PLYPresentationViewProperties = PLYPresentationViewProperties(),
145
+ properties: PLYPresentationProperties = PLYPresentationProperties(),
146
146
  isFullScreen: Boolean = false,
147
147
  backgroundColor: String? = null) = Intent(activity, PLYProductActivity::class.java).apply {
148
148
  //remove old activity if still referenced to avoid issues
@@ -16,7 +16,7 @@ import io.purchasely.ext.PLYEvent
16
16
  import io.purchasely.ext.PLYPresentation
17
17
  import io.purchasely.ext.PLYPresentationAction
18
18
  import io.purchasely.ext.PLYPresentationType
19
- import io.purchasely.ext.PLYPresentationViewProperties
19
+ import io.purchasely.ext.PLYPresentationProperties
20
20
  import io.purchasely.ext.PLYProductViewResult
21
21
  import io.purchasely.ext.PLYRunningMode
22
22
  import io.purchasely.ext.PLYRunningMode.Full
@@ -29,6 +29,9 @@ import io.purchasely.ext.Purchasely
29
29
  import io.purchasely.ext.State
30
30
  import io.purchasely.ext.StoreType
31
31
  import io.purchasely.ext.SubscriptionsListener
32
+ import io.purchasely.ext.UserAttributeListener
33
+ import io.purchasely.storage.userData.PLYUserAttributeSource
34
+ import io.purchasely.storage.userData.PLYUserAttributeType
32
35
  import io.purchasely.models.PLYError
33
36
  import io.purchasely.models.PLYPlan
34
37
  import io.purchasely.models.PLYPresentationPlan
@@ -76,6 +79,8 @@ class PurchaselyPlugin : CordovaPlugin() {
76
79
 
77
80
  "close" -> close()
78
81
  "addEventsListener" -> addEventsListener(callbackContext)
82
+ "addUserAttributeListener" -> addUserAttributesListener(callbackContext)
83
+ "removeUserAttributeListener" -> removeUserAttributesListener()
79
84
  "removeEventsListener" -> removeEventsListener()
80
85
  "getAnonymousUserId" -> getAnonymousUserId(callbackContext)
81
86
  "userLogin" -> userLogin(getStringFromJson(args.getString(0)), callbackContext)
@@ -170,9 +175,14 @@ class PurchaselyPlugin : CordovaPlugin() {
170
175
  "setUserAttributeWithInt" -> setUserAttributeWithInt(getStringFromJson(args.getString(0)), args.getInt(1))
171
176
  "setUserAttributeWithDouble" -> setUserAttributeWithDouble(getStringFromJson(args.getString(0)), args.getDouble(1))
172
177
  "setUserAttributeWithDate" -> setUserAttributeWithDate(getStringFromJson(args.getString(0)), getStringFromJson(args.getString(1)))
178
+ "setUserAttributeWithStringArray" -> setUserAttributeWithStringArray(getStringFromJson(args.getString(0)), args.getJSONArray(1))
179
+ "setUserAttributeWithIntArray" -> setUserAttributeWithIntArray(getStringFromJson(args.getString(0)), args.getJSONArray(1))
180
+ "setUserAttributeWithDoubleArray" -> setUserAttributeWithDoubleArray(getStringFromJson(args.getString(0)), args.getJSONArray(1))
181
+ "setUserAttributeWithBooleanArray" -> setUserAttributeWithBooleanArray(getStringFromJson(args.getString(0)), args.getJSONArray(1))
173
182
  "userAttribute" -> userAttribute(getStringFromJson(args.getString(0)), callbackContext)
174
183
  "clearUserAttribute" -> clearUserAttribute(getStringFromJson(args.getString(0)))
175
184
  "clearUserAttributes" -> clearUserAttributes()
185
+ "clearBuiltInAttributes" -> clearBuiltInAttributes()
176
186
  "isEligibleForIntroOffer" -> isEligibleForIntroOffer(getStringFromJson(args.getString(0)), callbackContext)
177
187
  "signPromotionalOffer" -> signPromotionalOffer(getStringFromJson(args.getString(0)), getStringFromJson(args.getString(1)), callbackContext)
178
188
  else -> return false
@@ -270,6 +280,40 @@ class PurchaselyPlugin : CordovaPlugin() {
270
280
  Purchasely.close()
271
281
  }
272
282
 
283
+ private fun addUserAttributesListener(callbackContext: CallbackContext) {
284
+ attributesCallback = callbackContext
285
+ Purchasely.userAttributeListener = object: UserAttributeListener {
286
+ override fun onUserAttributeSet(
287
+ key: String,
288
+ type: PLYUserAttributeType,
289
+ value: Any,
290
+ source: PLYUserAttributeSource
291
+ ) {
292
+ val map = HashMap<String, Any?>()
293
+ map["action"] = "add"
294
+ map["key"] = key
295
+ map["type"] = type.name
296
+ map["value"] = value
297
+ map["source"] = source.name
298
+
299
+ val pluginResult = PluginResult(PluginResult.Status.OK, JSONObject(map))
300
+ pluginResult.keepCallback = true
301
+ attributesCallback?.sendPluginResult(pluginResult)
302
+ }
303
+
304
+ override fun onUserAttributeRemoved(key: String, source: PLYUserAttributeSource) {
305
+ val map = HashMap<String, Any?>()
306
+ map["action"] = "remove"
307
+ map["key"] = key
308
+ map["source"] = source.name
309
+
310
+ val pluginResult = PluginResult(PluginResult.Status.OK, JSONObject(map))
311
+ pluginResult.keepCallback = true
312
+ attributesCallback?.sendPluginResult(pluginResult)
313
+ }
314
+ }
315
+ }
316
+
273
317
  private fun addEventsListener(callbackContext: CallbackContext) {
274
318
  eventsCallback = callbackContext
275
319
  Purchasely.eventListener = object: EventListener {
@@ -284,6 +328,11 @@ class PurchaselyPlugin : CordovaPlugin() {
284
328
  }
285
329
  }
286
330
 
331
+ private fun removeUserAttributesListener() {
332
+ attributesCallback = null
333
+ Purchasely.userAttributeListener = null
334
+ }
335
+
287
336
  private fun removeEventsListener() {
288
337
  eventsCallback = null
289
338
  Purchasely.eventListener = null
@@ -331,7 +380,34 @@ class PurchaselyPlugin : CordovaPlugin() {
331
380
  private fun setAttribute(attribute: Int, value: String?) {
332
381
  if(value == null) return
333
382
 
334
- Purchasely.setAttribute(Attribute.values()[attribute], value)
383
+ val attributeKey = when (attribute) {
384
+ CordovaPLYAttribute.firebase_app_instance_id.ordinal -> Attribute.FIREBASE_APP_INSTANCE_ID
385
+ CordovaPLYAttribute.airship_channel_id.ordinal -> Attribute.AIRSHIP_CHANNEL_ID
386
+ CordovaPLYAttribute.airship_user_id.ordinal -> Attribute.AIRSHIP_USER_ID
387
+ CordovaPLYAttribute.batch_installation_id.ordinal -> Attribute.BATCH_INSTALLATION_ID
388
+ CordovaPLYAttribute.adjust_id.ordinal -> Attribute.ADJUST_ID
389
+ CordovaPLYAttribute.appsflyer_id.ordinal -> Attribute.APPSFLYER_ID
390
+ CordovaPLYAttribute.mixpanel_distinct_id.ordinal -> Attribute.MIXPANEL_DISTINCT_ID
391
+ CordovaPLYAttribute.clever_tap_id.ordinal -> Attribute.CLEVER_TAP_ID
392
+ CordovaPLYAttribute.sendinblueUserEmail.ordinal -> Attribute.SENDINBLUE_USER_EMAIL
393
+ CordovaPLYAttribute.iterableUserEmail.ordinal -> Attribute.ITERABLE_USER_EMAIL
394
+ CordovaPLYAttribute.iterableUserId.ordinal -> Attribute.ITERABLE_USER_ID
395
+ CordovaPLYAttribute.atInternetIdClient.ordinal -> Attribute.AT_INTERNET_ID_CLIENT
396
+ CordovaPLYAttribute.mParticleUserId.ordinal -> Attribute.MPARTICLE_USER_ID
397
+ CordovaPLYAttribute.customerioUserId.ordinal -> Attribute.CUSTOMERIO_USER_ID
398
+ CordovaPLYAttribute.customerioUserEmail.ordinal -> Attribute.CUSTOMERIO_USER_EMAIL
399
+ CordovaPLYAttribute.branchUserDeveloperIdentity.ordinal -> Attribute.BRANCH_USER_DEVELOPER_IDENTITY
400
+ CordovaPLYAttribute.amplitudeUserId.ordinal -> Attribute.AMPLITUDE_USER_ID
401
+ CordovaPLYAttribute.amplitudeDeviceId.ordinal -> Attribute.AMPLITUDE_DEVICE_ID
402
+ CordovaPLYAttribute.moengageUniqueId.ordinal -> Attribute.MOENGAGE_UNIQUE_ID
403
+ CordovaPLYAttribute.oneSignalExternalId.ordinal -> Attribute.ONESIGNAL_EXTERNAL_ID
404
+ CordovaPLYAttribute.batchCustomUserId.ordinal -> Attribute.BATCH_CUSTOM_USER_ID
405
+ else -> null
406
+ }
407
+
408
+ attributeKey?.let {
409
+ Purchasely.setAttribute(attribute = it, value = value)
410
+ }
335
411
  }
336
412
 
337
413
  private fun setDefaultPresentationResultHandler(callbackContext: CallbackContext) {
@@ -430,7 +506,7 @@ class PurchaselyPlugin : CordovaPlugin() {
430
506
  presentationId: String?,
431
507
  contentId: String?,
432
508
  callbackContext: CallbackContext) {
433
- val properties = PLYPresentationViewProperties(
509
+ val properties = PLYPresentationProperties(
434
510
  placementId = placementId,
435
511
  presentationId = presentationId,
436
512
  contentId = contentId)
@@ -461,7 +537,7 @@ class PurchaselyPlugin : CordovaPlugin() {
461
537
  Pair("planVendorId", planVendorId),
462
538
  Pair("storeProductId", storeProductId),
463
539
  Pair("basePlanId", basePlanId),
464
- Pair("offerId", offerId)
540
+ //Pair("offerId", offerId)
465
541
  )
466
542
  }
467
543
 
@@ -486,7 +562,7 @@ class PurchaselyPlugin : CordovaPlugin() {
486
562
  purchaseCallback = callbackContext
487
563
 
488
564
  cordova.activity.let { activity ->
489
- val intent = PLYProductActivity.newIntent(activity, PLYPresentationViewProperties(), isFullScreen, loadingBackgroundColor).apply {
565
+ val intent = PLYProductActivity.newIntent(activity, PLYPresentationProperties(), isFullScreen, loadingBackgroundColor).apply {
490
566
  putExtra("presentation", presentation)
491
567
  }
492
568
  activity.startActivity(intent)
@@ -758,6 +834,58 @@ class PurchaselyPlugin : CordovaPlugin() {
758
834
  )
759
835
  }
760
836
 
837
+ fun setUserAttributeWithStringArray(key: String?, value: JSONArray?) {
838
+ if(key == null || value == null) return
839
+ val list = mutableListOf<String>()
840
+ for (i in 0 until value.length()) {
841
+ try {
842
+ list.add(value.getString(i))
843
+ } catch (e: JSONException) {
844
+ Log.e("Purchasely", "Error in string array" + e.message, e)
845
+ }
846
+ }
847
+ Purchasely.setUserAttribute(key, list.toTypedArray())
848
+ }
849
+
850
+ fun setUserAttributeWithIntArray(key: String?, value: JSONArray?) {
851
+ if(key == null || value == null) return
852
+ val list = mutableListOf<Int>()
853
+ for (i in 0 until value.length()) {
854
+ try {
855
+ list.add(value.getInt(i))
856
+ } catch (e: JSONException) {
857
+ Log.e("Purchasely", "Error in int array" + e.message, e)
858
+ }
859
+ }
860
+ Purchasely.setUserAttribute(key, list.toTypedArray())
861
+ }
862
+
863
+ fun setUserAttributeWithDoubleArray(key: String?, value: JSONArray?) {
864
+ if (key == null || value == null) return
865
+ val list = mutableListOf<Float>()
866
+ for (i in 0 until value.length()) {
867
+ try {
868
+ list.add(value.getDouble(i).toFloat())
869
+ } catch (e: JSONException) {
870
+ Log.e("Purchasely", "Error in double array: ${e.message}", e)
871
+ }
872
+ }
873
+ Purchasely.setUserAttribute(key, list.toTypedArray())
874
+ }
875
+
876
+ fun setUserAttributeWithBooleanArray(key: String?, value: JSONArray?) {
877
+ if(key == null || value == null) return
878
+ val list = mutableListOf<Boolean>()
879
+ for (i in 0 until value.length()) {
880
+ try {
881
+ list.add(value.getBoolean(i))
882
+ } catch (e: JSONException) {
883
+ Log.e("Purchasely", "Error in boolean array" + e.message, e)
884
+ }
885
+ }
886
+ Purchasely.setUserAttribute(key, list.toTypedArray())
887
+ }
888
+
761
889
  fun setUserAttributeWithString(key: String?, value: String?) {
762
890
  if(key == null || value == null) return
763
891
  Purchasely.setUserAttribute(key, value)
@@ -800,14 +928,16 @@ class PurchaselyPlugin : CordovaPlugin() {
800
928
  fun userAttribute(key: String?, callbackContext: CallbackContext) {
801
929
  if(key == null) return
802
930
  val result = getUserAttributeValueForCordova(Purchasely.userAttribute(key))
803
- if(result != null) {
804
- callbackContext.success(getUserAttributeValueForCordova(result))
805
- } else {
806
- callbackContext.error("No user attribute found with $key")
931
+ when (result) {
932
+ is JSONArray -> callbackContext.success(result)
933
+ is String -> callbackContext.success(result)
934
+ is Int -> callbackContext.success(result)
935
+ is Boolean -> callbackContext.success(if (result) 1 else 0)
936
+ else -> callbackContext.error("No user attribute found with $key")
807
937
  }
808
938
  }
809
939
 
810
- private fun getUserAttributeValueForCordova(value: Any?): String? {
940
+ private fun getUserAttributeValueForCordova(value: Any?): Any? {
811
941
  return when (value) {
812
942
  is Date -> {
813
943
  val format = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@@ -822,11 +952,18 @@ class PurchaselyPlugin : CordovaPlugin() {
822
952
  ""
823
953
  }
824
954
  }
825
- is Int -> value.toString()
955
+ is Int -> value
826
956
  //awful but to keep same precision so 1.2f = 1.2 double and not 1.20000056
827
- is Float -> value.toString().toDouble().toString()
957
+ is Float -> value.toString().toDouble()
828
958
  is String -> value
829
- is Boolean -> value.toString()
959
+ is Boolean -> value
960
+ is Array<*> -> {
961
+ val jsonArray = JSONArray()
962
+ value.forEach {
963
+ jsonArray.put(getUserAttributeValueForCordova(it))
964
+ }
965
+ jsonArray
966
+ }
830
967
  else -> null
831
968
  }
832
969
  }
@@ -840,6 +977,10 @@ class PurchaselyPlugin : CordovaPlugin() {
840
977
  Purchasely.clearUserAttributes()
841
978
  }
842
979
 
980
+ fun clearBuiltInAttributes() {
981
+ Purchasely.clearBuiltInAttributes()
982
+ }
983
+
843
984
  private fun isEligibleForIntroOffer(planId: String?, callbackContext: CallbackContext) {
844
985
  Purchasely.plan(planId,
845
986
  onSuccess = { plan ->
@@ -906,6 +1047,7 @@ class PurchaselyPlugin : CordovaPlugin() {
906
1047
  var defaultCallback: CallbackContext? = null
907
1048
  var purchaseCallback: CallbackContext? = null
908
1049
  var eventsCallback: CallbackContext? = null
1050
+ var attributesCallback: CallbackContext? = null
909
1051
  var productActivity: ProductActivity? = null
910
1052
 
911
1053
  var interceptorActivity: WeakReference<Activity>? = null
@@ -955,4 +1097,53 @@ class PurchaselyPlugin : CordovaPlugin() {
955
1097
  return map
956
1098
  }
957
1099
  }
1100
+
1101
+ // WARNING: This enum must be strictly identical to the one in the JS side (Purchasely.js).
1102
+ enum class CordovaPLYAttribute {
1103
+ firebase_app_instance_id,
1104
+ airship_channel_id,
1105
+ airship_user_id,
1106
+ batch_installation_id,
1107
+ adjust_id,
1108
+ appsflyer_id,
1109
+ mixpanel_distinct_id,
1110
+ clever_tap_id,
1111
+ sendinblueUserEmail,
1112
+ iterableUserEmail,
1113
+ iterableUserId,
1114
+ atInternetIdClient,
1115
+ mParticleUserId,
1116
+ customerioUserId,
1117
+ customerioUserEmail,
1118
+ branchUserDeveloperIdentity,
1119
+ amplitudeUserId,
1120
+ amplitudeDeviceId,
1121
+ moengageUniqueId,
1122
+ oneSignalExternalId,
1123
+ batchCustomUserId,
1124
+
1125
+ /*
1126
+ FIREBASE_APP_INSTANCE_ID: 0,
1127
+ AIRSHIP_CHANNEL_ID: 1,
1128
+ AIRSHIP_USER_ID: 2,
1129
+ BATCH_INSTALLATION_ID: 3,
1130
+ ADJUST_ID: 4,
1131
+ APPSFLYER_ID: 5,
1132
+ MIXPANEL_DISTINCT_ID: 6,
1133
+ CLEVER_TAP_ID: 7,
1134
+ SENDINBLUE_USER_EMAIL: 8,
1135
+ ITERABLE_USER_EMAIL: 9,
1136
+ ITERABLE_USER_ID: 10,
1137
+ AT_INTERNET_ID_CLIENT: 11,
1138
+ MPARTICLE_USER_ID: 12,
1139
+ CUSTOMERIO_USER_ID: 13,
1140
+ CUSTOMERIO_USER_EMAIL: 14,
1141
+ BRANCH_USER_DEVELOPER_IDENTITY: 15,
1142
+ AMPLITUDE_USER_ID: 16,
1143
+ AMPLITUDE_DEVICE_ID: 17,
1144
+ MOENGAGE_UNIQUE_ID: 18,
1145
+ ONESIGNAL_EXTERNAL_ID: 19,
1146
+ BATCH_CUSTOM_USER_ID: 20,
1147
+ */
1148
+ }
958
1149
  }
@@ -0,0 +1,35 @@
1
+ //
2
+ // CDVPurchasely+UserAttributes.h
3
+ // Purchasely Cordova Plugin
4
+ //
5
+ // Created by Florian HUET on 26/03/2025.
6
+ //
7
+
8
+ #import <Cordova/CDVPlugin.h>
9
+ #import "CDVPurchasely.h"
10
+
11
+ @interface CDVPurchasely (UserAttributes) {
12
+
13
+ }
14
+
15
+ - (void)onUserAttributeSetWithKey:(NSString * _Nonnull)key
16
+ type:(enum PLYUserAttributeType)type
17
+ value:(id _Nullable)value
18
+ source:(enum PLYUserAttributeSource)source;
19
+
20
+ - (void)onUserAttributeRemovedWithKey:(NSString * _Nonnull)key
21
+ source:(enum PLYUserAttributeSource)source;
22
+
23
+ @end
24
+
25
+ @interface PLYUserAttributeTypeHelper : NSObject
26
+
27
+ + (NSString *_Nullable)stringFromUserAttributeType:(PLYUserAttributeType)type;
28
+
29
+ @end
30
+
31
+ @interface PLYUserAttributeSourceHelper : NSObject
32
+
33
+ + (NSString *_Nullable)stringFromUserAttributeSource:(PLYUserAttributeSource)source;
34
+
35
+ @end