@purchasely/cordova-plugin-purchasely 4.3.1 → 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.
@@ -15,19 +15,18 @@
15
15
  "devDependencies": {
16
16
  "@purchasely/cordova-plugin-puchasely-google": "file:../../purchasely-google",
17
17
  "@purchasely/cordova-plugin-purchasely": "file:..",
18
- "cordova-android": "^12.0.1",
18
+ "cordova-android": "^13.0.0",
19
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
28
  "android",
30
29
  "ios"
31
30
  ]
32
31
  }
33
- }
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.3.1",
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.3.1" 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.3.4"/>
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.3.4" />
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
 
@@ -131,11 +131,6 @@ class PLYProductActivity : AppCompatActivity() {
131
131
  PurchaselyPlugin.productActivity = productActivity
132
132
  }
133
133
 
134
- override fun onDestroy() {
135
- PurchaselyPlugin.productActivity?.activity = null
136
- super.onDestroy()
137
- }
138
-
139
134
  private val callback: (PLYProductViewResult, PLYPlan?) -> Unit = { result, plan ->
140
135
  PurchaselyPlugin.sendPurchaseResult(
141
136
  result,
@@ -147,7 +142,7 @@ class PLYProductActivity : AppCompatActivity() {
147
142
  companion object {
148
143
  @JvmStatic
149
144
  fun newIntent(activity: Activity?,
150
- properties: PLYPresentationViewProperties = PLYPresentationViewProperties(),
145
+ properties: PLYPresentationProperties = PLYPresentationProperties(),
151
146
  isFullScreen: Boolean = false,
152
147
  backgroundColor: String? = null) = Intent(activity, PLYProductActivity::class.java).apply {
153
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)
@@ -136,6 +141,7 @@ class PurchaselyPlugin : CordovaPlugin() {
136
141
  "restoreAllProducts" -> restoreAllProducts(callbackContext)
137
142
  "silentRestoreAllProducts" -> restoreAllProducts(callbackContext)
138
143
  "userSubscriptions" -> userSubscriptions(callbackContext)
144
+ "userSubscriptionsHistory" -> userSubscriptionsHistory(callbackContext)
139
145
  "isDeeplinkHandled" -> isDeeplinkHandled(
140
146
  getStringFromJson(args.getString(0)),
141
147
  callbackContext
@@ -169,9 +175,14 @@ class PurchaselyPlugin : CordovaPlugin() {
169
175
  "setUserAttributeWithInt" -> setUserAttributeWithInt(getStringFromJson(args.getString(0)), args.getInt(1))
170
176
  "setUserAttributeWithDouble" -> setUserAttributeWithDouble(getStringFromJson(args.getString(0)), args.getDouble(1))
171
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))
172
182
  "userAttribute" -> userAttribute(getStringFromJson(args.getString(0)), callbackContext)
173
183
  "clearUserAttribute" -> clearUserAttribute(getStringFromJson(args.getString(0)))
174
184
  "clearUserAttributes" -> clearUserAttributes()
185
+ "clearBuiltInAttributes" -> clearBuiltInAttributes()
175
186
  "isEligibleForIntroOffer" -> isEligibleForIntroOffer(getStringFromJson(args.getString(0)), callbackContext)
176
187
  "signPromotionalOffer" -> signPromotionalOffer(getStringFromJson(args.getString(0)), getStringFromJson(args.getString(1)), callbackContext)
177
188
  else -> return false
@@ -269,6 +280,40 @@ class PurchaselyPlugin : CordovaPlugin() {
269
280
  Purchasely.close()
270
281
  }
271
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
+
272
317
  private fun addEventsListener(callbackContext: CallbackContext) {
273
318
  eventsCallback = callbackContext
274
319
  Purchasely.eventListener = object: EventListener {
@@ -283,6 +328,11 @@ class PurchaselyPlugin : CordovaPlugin() {
283
328
  }
284
329
  }
285
330
 
331
+ private fun removeUserAttributesListener() {
332
+ attributesCallback = null
333
+ Purchasely.userAttributeListener = null
334
+ }
335
+
286
336
  private fun removeEventsListener() {
287
337
  eventsCallback = null
288
338
  Purchasely.eventListener = null
@@ -330,7 +380,34 @@ class PurchaselyPlugin : CordovaPlugin() {
330
380
  private fun setAttribute(attribute: Int, value: String?) {
331
381
  if(value == null) return
332
382
 
333
- 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
+ }
334
411
  }
335
412
 
336
413
  private fun setDefaultPresentationResultHandler(callbackContext: CallbackContext) {
@@ -429,7 +506,7 @@ class PurchaselyPlugin : CordovaPlugin() {
429
506
  presentationId: String?,
430
507
  contentId: String?,
431
508
  callbackContext: CallbackContext) {
432
- val properties = PLYPresentationViewProperties(
509
+ val properties = PLYPresentationProperties(
433
510
  placementId = placementId,
434
511
  presentationId = presentationId,
435
512
  contentId = contentId)
@@ -460,7 +537,7 @@ class PurchaselyPlugin : CordovaPlugin() {
460
537
  Pair("planVendorId", planVendorId),
461
538
  Pair("storeProductId", storeProductId),
462
539
  Pair("basePlanId", basePlanId),
463
- Pair("offerId", offerId)
540
+ //Pair("offerId", offerId)
464
541
  )
465
542
  }
466
543
 
@@ -485,7 +562,7 @@ class PurchaselyPlugin : CordovaPlugin() {
485
562
  purchaseCallback = callbackContext
486
563
 
487
564
  cordova.activity.let { activity ->
488
- val intent = PLYProductActivity.newIntent(activity, PLYPresentationViewProperties(), isFullScreen, loadingBackgroundColor).apply {
565
+ val intent = PLYProductActivity.newIntent(activity, PLYPresentationProperties(), isFullScreen, loadingBackgroundColor).apply {
489
566
  putExtra("presentation", presentation)
490
567
  }
491
568
  activity.startActivity(intent)
@@ -539,6 +616,38 @@ class PurchaselyPlugin : CordovaPlugin() {
539
616
  )
540
617
  }
541
618
 
619
+ private fun userSubscriptionsHistory(callbackContext: CallbackContext) {
620
+ Purchasely.userSubscriptionsHistory(
621
+ false,
622
+ object : SubscriptionsListener {
623
+ override fun onSuccess(list: List<PLYSubscriptionData>) {
624
+ val result = JSONArray()
625
+ for (i in list.indices) {
626
+ val data = list[i]
627
+ val map = HashMap(data.toMap())
628
+ map["plan"] = transformPlanToMap(data.plan)
629
+ map["product"] = data.product.toMap()
630
+ if (data.data.storeType == StoreType.GOOGLE_PLAY_STORE) {
631
+ map["subscriptionSource"] = StoreType.GOOGLE_PLAY_STORE.ordinal
632
+ } else if (data.data.storeType == StoreType.AMAZON_APP_STORE) {
633
+ map["subscriptionSource"] = StoreType.AMAZON_APP_STORE.ordinal
634
+ } else if (data.data.storeType == StoreType.HUAWEI_APP_GALLERY) {
635
+ map["subscriptionSource"] = StoreType.HUAWEI_APP_GALLERY.ordinal
636
+ } else if (data.data.storeType == StoreType.APPLE_APP_STORE) {
637
+ map["subscriptionSource"] = StoreType.APPLE_APP_STORE.ordinal
638
+ }
639
+ result.put(JSONObject(map))
640
+ }
641
+ callbackContext.success(result)
642
+ }
643
+
644
+ override fun onFailure(throwable: Throwable) {
645
+ callbackContext.error(throwable.message)
646
+ }
647
+ }
648
+ )
649
+ }
650
+
542
651
  private fun isDeeplinkHandled(deeplink: String?, callbackContext: CallbackContext) {
543
652
  if (deeplink == null) {
544
653
  callbackContext.error("Deeplink must not be null")
@@ -725,6 +834,58 @@ class PurchaselyPlugin : CordovaPlugin() {
725
834
  )
726
835
  }
727
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
+
728
889
  fun setUserAttributeWithString(key: String?, value: String?) {
729
890
  if(key == null || value == null) return
730
891
  Purchasely.setUserAttribute(key, value)
@@ -767,14 +928,16 @@ class PurchaselyPlugin : CordovaPlugin() {
767
928
  fun userAttribute(key: String?, callbackContext: CallbackContext) {
768
929
  if(key == null) return
769
930
  val result = getUserAttributeValueForCordova(Purchasely.userAttribute(key))
770
- if(result != null) {
771
- callbackContext.success(getUserAttributeValueForCordova(result))
772
- } else {
773
- 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")
774
937
  }
775
938
  }
776
939
 
777
- private fun getUserAttributeValueForCordova(value: Any?): String? {
940
+ private fun getUserAttributeValueForCordova(value: Any?): Any? {
778
941
  return when (value) {
779
942
  is Date -> {
780
943
  val format = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@@ -789,11 +952,18 @@ class PurchaselyPlugin : CordovaPlugin() {
789
952
  ""
790
953
  }
791
954
  }
792
- is Int -> value.toString()
955
+ is Int -> value
793
956
  //awful but to keep same precision so 1.2f = 1.2 double and not 1.20000056
794
- is Float -> value.toString().toDouble().toString()
957
+ is Float -> value.toString().toDouble()
795
958
  is String -> value
796
- 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
+ }
797
967
  else -> null
798
968
  }
799
969
  }
@@ -807,6 +977,10 @@ class PurchaselyPlugin : CordovaPlugin() {
807
977
  Purchasely.clearUserAttributes()
808
978
  }
809
979
 
980
+ fun clearBuiltInAttributes() {
981
+ Purchasely.clearBuiltInAttributes()
982
+ }
983
+
810
984
  private fun isEligibleForIntroOffer(planId: String?, callbackContext: CallbackContext) {
811
985
  Purchasely.plan(planId,
812
986
  onSuccess = { plan ->
@@ -873,6 +1047,7 @@ class PurchaselyPlugin : CordovaPlugin() {
873
1047
  var defaultCallback: CallbackContext? = null
874
1048
  var purchaseCallback: CallbackContext? = null
875
1049
  var eventsCallback: CallbackContext? = null
1050
+ var attributesCallback: CallbackContext? = null
876
1051
  var productActivity: ProductActivity? = null
877
1052
 
878
1053
  var interceptorActivity: WeakReference<Activity>? = null
@@ -922,4 +1097,53 @@ class PurchaselyPlugin : CordovaPlugin() {
922
1097
  return map
923
1098
  }
924
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
+ }
925
1149
  }