@purchasely/cordova-plugin-purchasely 6.0.0-rc.3 → 6.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/README.md +22 -14
- package/__tests__/Purchasely.test.js +820 -155
- package/example/IOS_8_1_1_TEST_MATRIX.md +25 -0
- package/example/e2e/README.md +2 -2
- package/example/e2e/helpers/driver.js +135 -18
- package/example/e2e/specs/bridge.e2e.js +116 -13
- package/example/e2e/specs/dismiss.e2e.js +32 -12
- package/example/e2e/tools/ci_run_e2e.sh +15 -1
- package/example/e2e/tools/ci_run_e2e_ios.sh +12 -2
- package/example/e2e/wdio.android.conf.js +3 -0
- package/example/e2e/wdio.ios.conf.js +26 -1
- package/example/ios.sh +6 -5
- package/example/package-lock.json +3 -3
- package/example/package.json +2 -2
- package/example/www/js/index.js +62 -58
- package/package.json +1 -1
- package/plugin.xml +3 -3
- package/src/android/PurchaselyPlugin.kt +247 -67
- package/src/ios/CDVPurchasely+Events.m +7 -1
- package/src/ios/CDVPurchasely.h +11 -0
- package/src/ios/CDVPurchasely.m +158 -6
- package/src/ios/Hybrid/PLYPlan+Hybrid.m +19 -0
- package/src/ios/Hybrid/PLYSubscription+Hybrid.m +13 -0
- package/www/Purchasely.js +390 -46
package/www/Purchasely.js
CHANGED
|
@@ -8,25 +8,32 @@ var defaultError = (e) => { console.log(e); }
|
|
|
8
8
|
// - a full transition object { type, dismissible?, width?, height?, backgroundColor? }
|
|
9
9
|
// where width/height are { type: 'pixel'|'percentage', value: Number } (width is
|
|
10
10
|
// popin-only, height drives drawer+popin) and backgroundColor is a hex string.
|
|
11
|
-
//
|
|
11
|
+
// CDV-W-12: when no displayMode is given, sends undefined (not a forced fullScreen
|
|
12
|
+
// default) so both natives' nil/null handling honors the backend-configured transition
|
|
13
|
+
// for that placement/screen, as documented in their own displayModeFromTransition /
|
|
14
|
+
// transitionFromMap helpers.
|
|
12
15
|
function normalizeTransition(mode) {
|
|
13
16
|
if (mode === true) return { type: 'fullScreen' };
|
|
14
17
|
if (mode === false) return { type: 'modal' };
|
|
15
18
|
if (typeof mode === 'string') return { type: mode };
|
|
16
19
|
if (mode && typeof mode === 'object' && mode.type) return mode;
|
|
17
|
-
return
|
|
20
|
+
return undefined;
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
// Wire a present* command's callback stream
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
+
// Wire a present* command's callback stream -- used identically for the direct present*
|
|
24
|
+
// actions and for the preload() -> display() re-display path (native `presentPresentation`),
|
|
25
|
+
// so both surface the same lifecycle regardless of how display() was reached. Purchasely 6.0
|
|
26
|
+
// emits presentation lifecycle events during display: the native side sends keep-alive
|
|
27
|
+
// envelopes { event: 'presented', presentation } and { event: 'closeRequested' }, then the
|
|
23
28
|
// dismiss OUTCOME (which has no `event` key) as the final, non-kept callback.
|
|
24
|
-
// `callbacks` may carry onPresented(presentation, error) and onCloseRequested().
|
|
29
|
+
// `callbacks` may carry onPresented(presentation, error) and onCloseRequested(). The
|
|
30
|
+
// 'presented' envelope's presentation is screenId-normalized like everywhere else (preload(),
|
|
31
|
+
// outcome.presentation) -- never the raw native payload.
|
|
25
32
|
function presentationDispatcher(success, callbacks) {
|
|
26
33
|
callbacks = callbacks || {};
|
|
27
34
|
return function (payload) {
|
|
28
35
|
if (payload && payload.event === 'presented') {
|
|
29
|
-
if (callbacks.onPresented) callbacks.onPresented(payload.presentation
|
|
36
|
+
if (callbacks.onPresented) callbacks.onPresented(normalizePresentation(payload.presentation), payload.error || null);
|
|
30
37
|
return;
|
|
31
38
|
}
|
|
32
39
|
if (payload && payload.event === 'closeRequested') {
|
|
@@ -56,12 +63,57 @@ exports.start = function (options, success, error) {
|
|
|
56
63
|
var opts = options || {};
|
|
57
64
|
var cordovaSdkVersion = cordova.define.moduleMap['cordova/plugin_list'].exports['metadata']['cordova-plugin-purchasely']
|
|
58
65
|
if(!cordovaSdkVersion) {
|
|
59
|
-
cordovaSdkVersion = "6.0.0
|
|
66
|
+
cordovaSdkVersion = "6.0.0";
|
|
60
67
|
}
|
|
61
68
|
opts.sdkVersion = cordovaSdkVersion;
|
|
62
69
|
exec(success, error, 'Purchasely', 'start', [opts]);
|
|
63
70
|
};
|
|
64
71
|
|
|
72
|
+
// Purchasely 6.0: fluent alias of exports.start(options, ...) (parity with the
|
|
73
|
+
// RN/Flutter Purchasely.builder(apiKey)). Accumulates options via the chain
|
|
74
|
+
// below, then delegates to the very same exports.start -- no new native action.
|
|
75
|
+
// .start(success, error) supports both idioms: pass callbacks for the Cordova
|
|
76
|
+
// (success, error) style, or omit them for a Promise resolving the
|
|
77
|
+
// isConfigured boolean (rejecting on native failure).
|
|
78
|
+
function PLYStartBuilder(apiKey) {
|
|
79
|
+
this._options = { apiKey: apiKey };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
PLYStartBuilder.prototype.appUserId = function (value) { this._options.appUserId = value; return this; };
|
|
83
|
+
PLYStartBuilder.prototype.runningMode = function (value) { this._options.runningMode = value; return this; };
|
|
84
|
+
PLYStartBuilder.prototype.logLevel = function (value) { this._options.logLevel = value; return this; };
|
|
85
|
+
PLYStartBuilder.prototype.allowDeeplink = function (value) { this._options.allowDeeplink = value; return this; };
|
|
86
|
+
PLYStartBuilder.prototype.allowCampaigns = function (value) { this._options.allowCampaigns = value; return this; };
|
|
87
|
+
PLYStartBuilder.prototype.stores = function (value) { this._options.stores = value; return this; };
|
|
88
|
+
PLYStartBuilder.prototype.storekitVersion = function (value) { this._options.storekitVersion = value; return this; };
|
|
89
|
+
PLYStartBuilder.prototype.storeKit1 = function (value) { this._options.storeKit1 = value; return this; };
|
|
90
|
+
PLYStartBuilder.prototype.deeplink = function (value) { this._options.deeplink = value; return this; };
|
|
91
|
+
|
|
92
|
+
PLYStartBuilder.prototype.start = function (success, error) {
|
|
93
|
+
if (success) {
|
|
94
|
+
exports.start(this._options, success, error);
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
var options = this._options;
|
|
98
|
+
return new Promise(function (resolve, reject) {
|
|
99
|
+
exports.start(options, resolve, function (nativeError) {
|
|
100
|
+
reject(normalizeError(nativeError));
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
exports.builder = function (apiKey) {
|
|
106
|
+
return new PLYStartBuilder(apiKey);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// REC-18 / PAR-18: addEventListener is the canonical name (matches RN's naming).
|
|
110
|
+
// addEventsListener (plural "Events", the original Cordova-only spelling) is kept as a
|
|
111
|
+
// deprecated alias.
|
|
112
|
+
exports.addEventListener = function (success, error) {
|
|
113
|
+
exec(success, error, 'Purchasely', 'addEventsListener', []);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// @deprecated use addEventListener instead.
|
|
65
117
|
exports.addEventsListener = function (success, error) {
|
|
66
118
|
exec(success, error, 'Purchasely', 'addEventsListener', []);
|
|
67
119
|
};
|
|
@@ -74,6 +126,12 @@ exports.removeUserAttributeListener = function () {
|
|
|
74
126
|
exec(() => {}, defaultError, 'Purchasely', 'removeUserAttributeListener', []);
|
|
75
127
|
};
|
|
76
128
|
|
|
129
|
+
// REC-18 / PAR-18: canonical name, paired with addEventListener.
|
|
130
|
+
exports.removeEventListener = function () {
|
|
131
|
+
exec(() => {}, defaultError, 'Purchasely', 'removeEventsListener', []);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// @deprecated use removeEventListener instead.
|
|
77
135
|
exports.removeEventsListener = function () {
|
|
78
136
|
exec(() => {}, defaultError, 'Purchasely', 'removeEventsListener', []);
|
|
79
137
|
};
|
|
@@ -86,8 +144,11 @@ exports.userLogin = function (userId, success) {
|
|
|
86
144
|
exec(success, defaultError, 'Purchasely', 'userLogin', [userId]);
|
|
87
145
|
};
|
|
88
146
|
|
|
89
|
-
|
|
90
|
-
|
|
147
|
+
// PAR-30: clearUserAttributes controls whether logout also clears locally cached user
|
|
148
|
+
// attributes (native default true on both platforms).
|
|
149
|
+
exports.userLogout = function (clearUserAttributes) {
|
|
150
|
+
var clear = clearUserAttributes === undefined ? true : clearUserAttributes;
|
|
151
|
+
exec(() => {}, defaultError, 'Purchasely', 'userLogout', [clear]);
|
|
91
152
|
};
|
|
92
153
|
|
|
93
154
|
exports.setLogLevel = function (logLevel) {
|
|
@@ -123,39 +184,240 @@ exports.synchronize = function (success, error) {
|
|
|
123
184
|
exec(success || (() => {}), error || defaultError, 'Purchasely', 'synchronize', []);
|
|
124
185
|
};
|
|
125
186
|
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
187
|
+
// Purchasely 6.0: the v5 presentation surface (fetchPresentation*, present-
|
|
188
|
+
// Presentation*, presentPresentation, backPresentation) is REMOVED, not
|
|
189
|
+
// deprecated -- replaced by the v6 builder below (parity with the React
|
|
190
|
+
// Native/Flutter SDKs; see MIGRATION-v6.md). It re-wraps the very same native
|
|
191
|
+
// exec actions used by v5 (fetchPresentation, presentPresentation,
|
|
192
|
+
// presentPresentationWithIdentifier/ForPlacement/ForDefault, backPresentation,
|
|
193
|
+
// closeAllScreens): no new native action is introduced.
|
|
194
|
+
//
|
|
195
|
+
// Purchasely.presentation.placement(id) | .screen(id) | .defaultSource() // alias: .default()
|
|
196
|
+
// .contentId(id)
|
|
197
|
+
// .backgroundColor(hex)
|
|
198
|
+
// .onLoaded(cb) / .onPresented(cb) / .onCloseRequested(cb) / .onDismissed(cb)
|
|
199
|
+
// .build()
|
|
200
|
+
// .preload() -> Promise<loadedPresentation> (screenId is authoritative;
|
|
201
|
+
// the resolved object also exposes display()/close()/back())
|
|
202
|
+
// .display(transition?) -> Promise<outcome> ({ presentation, purchaseResult, plan, closeReason, error })
|
|
203
|
+
// .close() -> closeAllScreens()
|
|
204
|
+
// .back() -> navigate back within the displayed presentation
|
|
205
|
+
//
|
|
206
|
+
// screenId is authoritative: normalizePresentation always resolves it (tolerating
|
|
207
|
+
// a raw `id` fallback) and only exposes the documented presentation fields. Any
|
|
208
|
+
// native re-display handle (Android's synthetic fetchId; iOS's internal `id`,
|
|
209
|
+
// which already equals screenId there) never leaves the private `_raw` field
|
|
210
|
+
// kept on the request -- it is not part of the presentation object handed back
|
|
211
|
+
// to callers.
|
|
212
|
+
//
|
|
213
|
+
// Modifier parity note: .backgroundColor(hex) is the ONLY presentation-style
|
|
214
|
+
// modifier the Cordova native layer actually supports -- it is wired to
|
|
215
|
+
// presentPresentation's native backgroundColor argument (preload -> display
|
|
216
|
+
// re-display path) and merged into the transition object for the direct present*
|
|
217
|
+
// paths (iOS reads transition.backgroundColor). It sets the loading/background
|
|
218
|
+
// color and takes effect on iOS; on Android it only applies through drawer/popin
|
|
219
|
+
// transitions (native limitation). The RN/Flutter builder's progressColor,
|
|
220
|
+
// displayCloseButton and displayBackButton are intentionally NOT exposed here: no
|
|
221
|
+
// Cordova native present action accepts them.
|
|
222
|
+
|
|
223
|
+
function normalizeError(error) {
|
|
224
|
+
if (error === undefined || error === null) return null;
|
|
225
|
+
if (typeof error === 'object' && error.message) return error;
|
|
226
|
+
return { message: String(error) };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function normalizePresentation(raw) {
|
|
230
|
+
if (!raw || typeof raw !== 'object') return null;
|
|
231
|
+
var screenId = raw.screenId != null ? raw.screenId : raw.id;
|
|
232
|
+
if (screenId == null) return null;
|
|
233
|
+
return {
|
|
234
|
+
screenId: screenId,
|
|
235
|
+
placementId: raw.placementId != null ? raw.placementId : null,
|
|
236
|
+
contentId: raw.contentId != null ? raw.contentId : null,
|
|
237
|
+
audienceId: raw.audienceId != null ? raw.audienceId : null,
|
|
238
|
+
abTestId: raw.abTestId != null ? raw.abTestId : null,
|
|
239
|
+
abTestVariantId: raw.abTestVariantId != null ? raw.abTestVariantId : null,
|
|
240
|
+
campaignId: raw.campaignId != null ? raw.campaignId : null,
|
|
241
|
+
flowId: raw.flowId != null ? raw.flowId : null,
|
|
242
|
+
language: raw.language != null ? raw.language : null,
|
|
243
|
+
type: raw.type != null ? raw.type : null,
|
|
244
|
+
plans: raw.plans != null ? raw.plans : null,
|
|
245
|
+
metadata: raw.metadata != null ? raw.metadata : null,
|
|
246
|
+
height: raw.height != null ? raw.height : null
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function normalizeOutcome(raw) {
|
|
251
|
+
raw = raw || {};
|
|
252
|
+
return {
|
|
253
|
+
presentation: normalizePresentation(raw.presentation),
|
|
254
|
+
purchaseResult: raw.purchaseResult != null ? raw.purchaseResult : null,
|
|
255
|
+
plan: raw.plan != null ? raw.plan : null,
|
|
256
|
+
closeReason: raw.closeReason != null ? raw.closeReason : null,
|
|
257
|
+
error: raw.error != null ? raw.error : null
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// A single presentation request: preload it (fetch without display), display it
|
|
262
|
+
// (resolves at dismiss with a 5-field outcome), close it, or navigate back. Calling
|
|
263
|
+
// `display()` after `preload()` re-displays the exact presentation that was fetched
|
|
264
|
+
// (via the native presentPresentation action, carrying its private re-display
|
|
265
|
+
// handle); `display()` alone (no prior preload) fetches and displays directly
|
|
266
|
+
// through the present* action matching this request's source.
|
|
267
|
+
function PLYPresentationRequest(config) {
|
|
268
|
+
this._config = config; // { placementId?, screenId?, contentId?, callbacks }
|
|
269
|
+
this._raw = null; // private: native fetch payload (carries the re-display handle)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
PLYPresentationRequest.prototype.preload = function () {
|
|
273
|
+
var self = this;
|
|
274
|
+
var callbacks = this._config.callbacks;
|
|
275
|
+
return new Promise(function (resolve, reject) {
|
|
276
|
+
exec(function (raw) {
|
|
277
|
+
self._raw = raw;
|
|
278
|
+
var presentation = normalizePresentation(raw);
|
|
279
|
+
// Purchasely 6.0: onLoaded fires once the presentation has loaded
|
|
280
|
+
// (parity with RN/Flutter's onLoaded, which only fires on a
|
|
281
|
+
// successful load -- a failed preload() rejects below instead).
|
|
282
|
+
if (callbacks.onLoaded) callbacks.onLoaded(presentation, null);
|
|
283
|
+
// Resolve a "loaded presentation": the screenId-normalized data plus
|
|
284
|
+
// display()/close()/back() delegating to this request (parity with RN's
|
|
285
|
+
// PLYLoadedPresentation and the native preload()->display() flow).
|
|
286
|
+
resolve(Object.assign({}, presentation, {
|
|
287
|
+
display: function (transition) { return self.display(transition); },
|
|
288
|
+
close: function () { return self.close(); },
|
|
289
|
+
back: function () { return self.back(); }
|
|
290
|
+
}));
|
|
291
|
+
}, function (error) {
|
|
292
|
+
reject(normalizeError(error));
|
|
293
|
+
}, 'Purchasely', 'fetchPresentation', [
|
|
294
|
+
self._config.placementId || null,
|
|
295
|
+
self._config.screenId || null,
|
|
296
|
+
self._config.contentId || null
|
|
297
|
+
]);
|
|
298
|
+
});
|
|
132
299
|
};
|
|
133
300
|
|
|
134
|
-
|
|
135
|
-
|
|
301
|
+
PLYPresentationRequest.prototype.display = function (transition) {
|
|
302
|
+
var self = this;
|
|
303
|
+
var callbacks = this._config.callbacks;
|
|
304
|
+
var normalizedTransition = normalizeTransition(transition);
|
|
305
|
+
// .backgroundColor() sugar: merge into the transition object so the direct
|
|
306
|
+
// present* paths (iOS reads transition.backgroundColor) pick it up. The
|
|
307
|
+
// transition's own backgroundColor, if any, still wins. Keeping no `type`
|
|
308
|
+
// when none was given preserves CDV-W-12 (backend default honored).
|
|
309
|
+
if (self._config.backgroundColor != null) {
|
|
310
|
+
normalizedTransition = Object.assign({ backgroundColor: self._config.backgroundColor }, normalizedTransition || {});
|
|
311
|
+
}
|
|
312
|
+
var backgroundColor = self._config.backgroundColor != null ? self._config.backgroundColor : null;
|
|
313
|
+
|
|
314
|
+
return new Promise(function (resolve) {
|
|
315
|
+
function settle(rawOutcome) {
|
|
316
|
+
var outcome = normalizeOutcome(rawOutcome);
|
|
317
|
+
if (callbacks.onDismissed) callbacks.onDismissed(outcome);
|
|
318
|
+
resolve(outcome);
|
|
319
|
+
}
|
|
320
|
+
var dispatch = presentationDispatcher(settle, {
|
|
321
|
+
onPresented: callbacks.onPresented,
|
|
322
|
+
onCloseRequested: callbacks.onCloseRequested
|
|
323
|
+
});
|
|
324
|
+
function onNativeError(error) {
|
|
325
|
+
var normalized = normalizeError(error);
|
|
326
|
+
settle({ error: normalized ? normalized.message : 'Unable to display presentation' });
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (self._raw) {
|
|
330
|
+
// Re-display the presentation preloaded by preload() -- same native
|
|
331
|
+
// 'presentPresentation' action v5 used, carrying its private handle.
|
|
332
|
+
exec(dispatch, onNativeError, 'Purchasely', 'presentPresentation', [self._raw, normalizedTransition, backgroundColor]);
|
|
333
|
+
} else if (self._config.screenId) {
|
|
334
|
+
exec(dispatch, onNativeError, 'Purchasely', 'presentPresentationWithIdentifier',
|
|
335
|
+
[self._config.screenId, self._config.contentId || null, normalizedTransition]);
|
|
336
|
+
} else if (self._config.placementId) {
|
|
337
|
+
exec(dispatch, onNativeError, 'Purchasely', 'presentPresentationForPlacement',
|
|
338
|
+
[self._config.placementId, self._config.contentId || null, normalizedTransition]);
|
|
339
|
+
} else {
|
|
340
|
+
exec(dispatch, onNativeError, 'Purchasely', 'presentPresentationForDefault',
|
|
341
|
+
[self._config.contentId || null, normalizedTransition]);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
136
344
|
};
|
|
137
345
|
|
|
138
|
-
// Purchasely 6.0:
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
|
|
346
|
+
// Purchasely 6.0: dismisses via the same native action as the top-level
|
|
347
|
+
// Purchasely.closeAllScreens() / closePresentation() (current bridge semantics:
|
|
348
|
+
// closes every displayed screen, not just this request's).
|
|
349
|
+
PLYPresentationRequest.prototype.close = function () {
|
|
350
|
+
exports.closeAllScreens();
|
|
142
351
|
};
|
|
143
352
|
|
|
144
|
-
|
|
145
|
-
|
|
353
|
+
// Purchasely 6.0: navigate back within the displayed presentation (was the
|
|
354
|
+
// standalone Purchasely.backPresentation(), now request-scoped).
|
|
355
|
+
PLYPresentationRequest.prototype.back = function () {
|
|
356
|
+
exec(() => {}, defaultError, 'Purchasely', 'backPresentation', []);
|
|
146
357
|
};
|
|
147
358
|
|
|
148
|
-
|
|
149
|
-
|
|
359
|
+
function PLYPresentationBuilder(config) {
|
|
360
|
+
this._config = config; // { placementId?, screenId?, contentId?, callbacks }
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
PLYPresentationBuilder.prototype.contentId = function (id) {
|
|
364
|
+
this._config.contentId = id;
|
|
365
|
+
return this;
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
// Loading/background color (hex). See the modifier parity note above: this is the
|
|
369
|
+
// only style modifier the Cordova native layer supports; progressColor /
|
|
370
|
+
// displayCloseButton / displayBackButton are intentionally not exposed.
|
|
371
|
+
PLYPresentationBuilder.prototype.backgroundColor = function (hex) {
|
|
372
|
+
this._config.backgroundColor = hex;
|
|
373
|
+
return this;
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// Purchasely 6.0: fires (presentation, error) once preload() loads the
|
|
377
|
+
// presentation. Only fires on a successful load; preload() still rejects on
|
|
378
|
+
// failure (parity with RN/Flutter's onLoaded).
|
|
379
|
+
PLYPresentationBuilder.prototype.onLoaded = function (handler) {
|
|
380
|
+
this._config.callbacks.onLoaded = handler;
|
|
381
|
+
return this;
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
PLYPresentationBuilder.prototype.onPresented = function (handler) {
|
|
385
|
+
this._config.callbacks.onPresented = handler;
|
|
386
|
+
return this;
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
PLYPresentationBuilder.prototype.onCloseRequested = function (handler) {
|
|
390
|
+
this._config.callbacks.onCloseRequested = handler;
|
|
391
|
+
return this;
|
|
150
392
|
};
|
|
151
393
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
394
|
+
PLYPresentationBuilder.prototype.onDismissed = function (handler) {
|
|
395
|
+
this._config.callbacks.onDismissed = handler;
|
|
396
|
+
return this;
|
|
155
397
|
};
|
|
156
398
|
|
|
157
|
-
|
|
158
|
-
|
|
399
|
+
PLYPresentationBuilder.prototype.build = function () {
|
|
400
|
+
return new PLYPresentationRequest(this._config);
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
// Purchasely 6.0: the v6 presentation builder (parity with the React Native /
|
|
404
|
+
// Flutter Purchasely.presentation). Pick exactly one source, chain
|
|
405
|
+
// .contentId() / .onPresented() / .onCloseRequested() / .onDismissed(), then
|
|
406
|
+
// .build().
|
|
407
|
+
exports.presentation = {
|
|
408
|
+
placement: function (placementId) {
|
|
409
|
+
return new PLYPresentationBuilder({ placementId: placementId, callbacks: {} });
|
|
410
|
+
},
|
|
411
|
+
screen: function (screenId) {
|
|
412
|
+
return new PLYPresentationBuilder({ screenId: screenId, callbacks: {} });
|
|
413
|
+
},
|
|
414
|
+
defaultSource: function () {
|
|
415
|
+
return new PLYPresentationBuilder({ callbacks: {} });
|
|
416
|
+
},
|
|
417
|
+
// Alias of defaultSource(), kept for parity with the iOS native API name.
|
|
418
|
+
default: function () {
|
|
419
|
+
return exports.presentation.defaultSource();
|
|
420
|
+
}
|
|
159
421
|
};
|
|
160
422
|
|
|
161
423
|
exports.purchaseWithPlanVendorId = function (planId, offerId, contentId, success, error) {
|
|
@@ -244,26 +506,30 @@ exports.userDidConsumeSubscriptionContent = function () {
|
|
|
244
506
|
exec(() => {}, defaultError, 'Purchasely', 'userDidConsumeSubscriptionContent', []);
|
|
245
507
|
};
|
|
246
508
|
|
|
247
|
-
|
|
248
|
-
|
|
509
|
+
// PAR-29: invalidateCache forces a fresh fetch instead of returning the cached list
|
|
510
|
+
// (native default false on both platforms).
|
|
511
|
+
exports.userSubscriptions = function (success, error, invalidateCache) {
|
|
512
|
+
exec(success, defaultError, 'Purchasely', 'userSubscriptions', [!!invalidateCache]);
|
|
249
513
|
};
|
|
250
514
|
|
|
251
|
-
exports.userSubscriptionsHistory = function (success, error) {
|
|
252
|
-
exec(success, defaultError, 'Purchasely', 'userSubscriptionsHistory', []);
|
|
515
|
+
exports.userSubscriptionsHistory = function (success, error, invalidateCache) {
|
|
516
|
+
exec(success, defaultError, 'Purchasely', 'userSubscriptionsHistory', [!!invalidateCache]);
|
|
253
517
|
};
|
|
254
518
|
|
|
255
519
|
exports.setLanguage = function (language) {
|
|
256
520
|
exec(() => {}, defaultError, 'Purchasely', 'setLanguage', [language]);
|
|
257
521
|
};
|
|
258
522
|
|
|
259
|
-
//
|
|
260
|
-
|
|
261
|
-
|
|
523
|
+
// PAR-19: closeAllScreens is the canonical name (matches the iOS/Android Purchasely-level
|
|
524
|
+
// API). success/error are optional.
|
|
525
|
+
exports.closeAllScreens = function (success, error) {
|
|
526
|
+
exec(success || (() => {}), error || defaultError, 'Purchasely', 'closeAllScreens', []);
|
|
262
527
|
};
|
|
263
528
|
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
|
|
529
|
+
// @deprecated use closeAllScreens instead; kept as an alias (same native action both
|
|
530
|
+
// platforms already call: Purchasely.closeAllScreens()).
|
|
531
|
+
exports.closePresentation = function (success, error) {
|
|
532
|
+
exports.closeAllScreens(success, error);
|
|
267
533
|
};
|
|
268
534
|
|
|
269
535
|
exports.setUserAttributeWithString = function (key, value, processLegalBasis) {
|
|
@@ -306,6 +572,22 @@ exports.userAttribute = function (key, success, error) {
|
|
|
306
572
|
exec(success, error, 'Purchasely', 'userAttribute', [key]);
|
|
307
573
|
};
|
|
308
574
|
|
|
575
|
+
// REC-12 / PAR-03: bulk read of every user attribute currently stored, with the same
|
|
576
|
+
// per-value type conversions as the single-key userAttribute(key) read.
|
|
577
|
+
exports.userAttributes = function (success, error) {
|
|
578
|
+
exec(success, error || defaultError, 'Purchasely', 'userAttributes', []);
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
// REC-12 / PAR-02: increment/decrement a numerical user attribute. value defaults to 1
|
|
582
|
+
// natively when omitted.
|
|
583
|
+
exports.incrementUserAttribute = function (key, value) {
|
|
584
|
+
exec(() => {}, defaultError, 'Purchasely', 'incrementUserAttribute', [key, value]);
|
|
585
|
+
};
|
|
586
|
+
|
|
587
|
+
exports.decrementUserAttribute = function (key, value) {
|
|
588
|
+
exec(() => {}, defaultError, 'Purchasely', 'decrementUserAttribute', [key, value]);
|
|
589
|
+
};
|
|
590
|
+
|
|
309
591
|
exports.clearUserAttribute = function (key) {
|
|
310
592
|
exec(() => {}, defaultError, 'Purchasely', 'clearUserAttribute', [key]);
|
|
311
593
|
};
|
|
@@ -318,10 +600,64 @@ exports.clearBuiltInAttributes = function () {
|
|
|
318
600
|
exec(() => {}, defaultError, 'Purchasely', 'clearBuiltInAttributes', []);
|
|
319
601
|
}
|
|
320
602
|
|
|
603
|
+
// PAR-07: read-only accessors for the built-in (SDK-collected) attributes.
|
|
604
|
+
exports.getBuiltInAttributes = function (success, error) {
|
|
605
|
+
exec(success, error || defaultError, 'Purchasely', 'getBuiltInAttributes', []);
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
exports.getBuiltInAttribute = function (key, success, error) {
|
|
609
|
+
exec(success, error || defaultError, 'Purchasely', 'getBuiltInAttribute', [key]);
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
// REC-12 / PAR-04: whether the current user is anonymous (no userLogin call yet).
|
|
613
|
+
exports.isAnonymous = function (success, error) {
|
|
614
|
+
exec(success, error || defaultError, 'Purchasely', 'isAnonymous', []);
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
// PAR-05: Dynamic Offerings -- force a specific plan (and optionally offer) to be shown
|
|
618
|
+
// in a specific context, keyed by an app-chosen reference.
|
|
619
|
+
// Purchasely 6.0 (iOS 26.4+, Apple only): billing plan type of a subscription with a
|
|
620
|
+
// multi-period commitment (e.g. "monthly subscription with 12-month commitment"). Passed to
|
|
621
|
+
// setDynamicOffering and surfaced on the commitment fields below. Android always reports
|
|
622
|
+
// `unspecified`.
|
|
623
|
+
exports.BillingPlanType = { unspecified: 0, upFront: 1, monthly: 2 };
|
|
624
|
+
|
|
625
|
+
// Purchasely 6.0 commitment fields (iOS 26.4+ only; absent on Android and on plans without a
|
|
626
|
+
// commitment):
|
|
627
|
+
// - A plan object (from allProducts()/planWithIdentifier(), a presentation outcome's `plan`,
|
|
628
|
+
// and the interceptAction('purchase') `parameters.plan`) may carry `commitmentInfo`: an
|
|
629
|
+
// array of { billingPlanType (Number, see Purchasely.BillingPlanType), billingPrice
|
|
630
|
+
// (Number), billingPeriod (ISO 8601 duration string, e.g. "P1M"), totalPrice (Number),
|
|
631
|
+
// totalPeriod (ISO 8601 duration string, e.g. "P1Y"), totalDuration (Number of billing
|
|
632
|
+
// cycles) }.
|
|
633
|
+
// - A subscription object (from userSubscriptions()/userSubscriptionsHistory()) may carry
|
|
634
|
+
// `commitmentProgress`: { billingPeriodNumber (Number), totalBillingPeriods (Number),
|
|
635
|
+
// commitmentExpiresDate (ISO 8601 date string), commitmentPrice (Number) }.
|
|
636
|
+
exports.setDynamicOffering = function (reference, planVendorId, offerVendorId, billingPlanType, success, error) {
|
|
637
|
+
exec(success || (() => {}), error || defaultError, 'Purchasely', 'setDynamicOffering',
|
|
638
|
+
[reference, planVendorId, offerVendorId != null ? offerVendorId : null,
|
|
639
|
+
billingPlanType != null ? billingPlanType : 0]);
|
|
640
|
+
};
|
|
641
|
+
|
|
642
|
+
// Returns a list of { reference, planVendorId, offerVendorId }.
|
|
643
|
+
exports.getDynamicOfferings = function (success, error) {
|
|
644
|
+
exec(success, error || defaultError, 'Purchasely', 'getDynamicOfferings', []);
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
exports.removeDynamicOffering = function (reference) {
|
|
648
|
+
exec(() => {}, defaultError, 'Purchasely', 'removeDynamicOffering', [reference]);
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
exports.clearDynamicOfferings = function () {
|
|
652
|
+
exec(() => {}, defaultError, 'Purchasely', 'clearDynamicOfferings', []);
|
|
653
|
+
};
|
|
654
|
+
|
|
321
655
|
exports.isEligibleForIntroOffer = function (planId, success, error) {
|
|
322
656
|
exec(success, error, 'Purchasely', 'isEligibleForIntroOffer', [planId]);
|
|
323
657
|
};
|
|
324
658
|
|
|
659
|
+
// REC-04: iOS-only (StoreKit promotional offer signing). On Android this is a no-op that
|
|
660
|
+
// resolves success (no signing is required there); no error is raised.
|
|
325
661
|
exports.signPromotionalOffer = function (storeProductId, storeOfferId, success, error) {
|
|
326
662
|
exec(success, error, 'Purchasely', 'signPromotionalOffer', [storeProductId, storeOfferId]);
|
|
327
663
|
};
|
|
@@ -345,6 +681,11 @@ exports.LogLevel = {
|
|
|
345
681
|
ERROR: 3,
|
|
346
682
|
}
|
|
347
683
|
|
|
684
|
+
// WARNING: this list, iOS's CordovaPLYAttribute typedef, and Android's CordovaPLYAttribute
|
|
685
|
+
// enum class must be kept in strictly identical declaration order across all 3. The bridge
|
|
686
|
+
// matches an attribute by ordinal/symbol POSITION (not by the real native SDK's raw value,
|
|
687
|
+
// which does churn -- see the native PLYAttribute/Attribute enums), so appending a new
|
|
688
|
+
// attribute here always requires the matching append, in the same position, on both natives.
|
|
348
689
|
exports.Attribute = {
|
|
349
690
|
FIREBASE_APP_INSTANCE_ID: 0,
|
|
350
691
|
AIRSHIP_CHANNEL_ID: 1,
|
|
@@ -367,6 +708,7 @@ exports.Attribute = {
|
|
|
367
708
|
MOENGAGE_UNIQUE_ID: 18,
|
|
368
709
|
ONESIGNAL_EXTERNAL_ID: 19,
|
|
369
710
|
BATCH_CUSTOM_USER_ID: 20,
|
|
711
|
+
ONESIGNAL_USER_ID: 21, // ENM-02 / REC-11
|
|
370
712
|
}
|
|
371
713
|
|
|
372
714
|
exports.DataProcessingLegalBasis = {
|
|
@@ -413,17 +755,19 @@ exports.RunningMode = {
|
|
|
413
755
|
}
|
|
414
756
|
|
|
415
757
|
// Purchasely 6.0: the paywall action kinds handled by interceptAction.
|
|
758
|
+
// Keys are camelCase (RN/Flutter parity); values are the wire-format
|
|
759
|
+
// snake_case strings the native bridges map/emit -- unchanged.
|
|
416
760
|
exports.PresentationAction = {
|
|
417
761
|
close: 'close',
|
|
418
|
-
|
|
762
|
+
closeAll: 'close_all',
|
|
419
763
|
login: 'login',
|
|
420
764
|
navigate: 'navigate',
|
|
421
765
|
purchase: 'purchase',
|
|
422
766
|
restore: 'restore',
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
767
|
+
openPresentation: 'open_presentation',
|
|
768
|
+
openPlacement: 'open_placement',
|
|
769
|
+
promoCode: 'promo_code',
|
|
770
|
+
webCheckout: 'web_checkout'
|
|
427
771
|
}
|
|
428
772
|
|
|
429
773
|
// Purchasely 6.0: result returned by an interceptAction handler after handling
|