@virex-tech/paywallo-sdk 2.1.0 → 2.2.1
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/dist/index.d.mts +121 -7
- package/dist/index.d.ts +121 -7
- package/dist/index.js +1146 -605
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1131 -596
- package/dist/index.mjs.map +1 -1
- package/ios/PaywalloDevice.swift +29 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -197,6 +197,9 @@ function isAvailable() {
|
|
|
197
197
|
function clearCache() {
|
|
198
198
|
cachedDeviceInfo = null;
|
|
199
199
|
}
|
|
200
|
+
function getCachedDeviceInfo() {
|
|
201
|
+
return cachedDeviceInfo;
|
|
202
|
+
}
|
|
200
203
|
var FALLBACK, _debug, warnedOnce, cachedDeviceInfo, nativeDeviceInfo;
|
|
201
204
|
var init_NativeDeviceInfo = __esm({
|
|
202
205
|
"src/utils/NativeDeviceInfo.ts"() {
|
|
@@ -223,6 +226,7 @@ var init_NativeDeviceInfo = __esm({
|
|
|
223
226
|
cachedDeviceInfo = null;
|
|
224
227
|
nativeDeviceInfo = {
|
|
225
228
|
getDeviceInfo,
|
|
229
|
+
getCachedDeviceInfo,
|
|
226
230
|
getInstallReferrer,
|
|
227
231
|
isAvailable,
|
|
228
232
|
clearCache
|
|
@@ -483,7 +487,7 @@ var init_IdentityStorage = __esm({
|
|
|
483
487
|
});
|
|
484
488
|
|
|
485
489
|
// src/domains/identity/IdentityManager.ts
|
|
486
|
-
var EMAIL_REGEX, IdentityManager, identityManager;
|
|
490
|
+
var USER_PHONE_KEY, USER_FIRST_NAME_KEY, USER_LAST_NAME_KEY, USER_DOB_KEY, USER_GENDER_KEY, EMAIL_REGEX, IdentityManager, identityManager;
|
|
487
491
|
var init_IdentityManager = __esm({
|
|
488
492
|
"src/domains/identity/IdentityManager.ts"() {
|
|
489
493
|
"use strict";
|
|
@@ -493,6 +497,11 @@ var init_IdentityManager = __esm({
|
|
|
493
497
|
init_SecureStorage();
|
|
494
498
|
init_StorageMigration();
|
|
495
499
|
init_IdentityStorage();
|
|
500
|
+
USER_PHONE_KEY = "@panel:user_phone";
|
|
501
|
+
USER_FIRST_NAME_KEY = "@panel:user_first_name";
|
|
502
|
+
USER_LAST_NAME_KEY = "@panel:user_last_name";
|
|
503
|
+
USER_DOB_KEY = "@panel:user_dob";
|
|
504
|
+
USER_GENDER_KEY = "@panel:user_gender";
|
|
496
505
|
EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
497
506
|
IdentityManager = class {
|
|
498
507
|
constructor() {
|
|
@@ -500,6 +509,11 @@ var init_IdentityManager = __esm({
|
|
|
500
509
|
this.anonId = null;
|
|
501
510
|
this.email = null;
|
|
502
511
|
this.properties = {};
|
|
512
|
+
this.phone = null;
|
|
513
|
+
this.firstName = null;
|
|
514
|
+
this.lastName = null;
|
|
515
|
+
this.dateOfBirth = null;
|
|
516
|
+
this.gender = null;
|
|
503
517
|
this.apiClient = null;
|
|
504
518
|
this.secureStorage = null;
|
|
505
519
|
this.debug = false;
|
|
@@ -555,7 +569,7 @@ var init_IdentityManager = __esm({
|
|
|
555
569
|
let email;
|
|
556
570
|
let properties;
|
|
557
571
|
if (options) {
|
|
558
|
-
if ("email" in options || "properties" in options) {
|
|
572
|
+
if ("email" in options || "properties" in options || "phone" in options || "firstName" in options || "lastName" in options || "dateOfBirth" in options || "gender" in options) {
|
|
559
573
|
email = options.email;
|
|
560
574
|
properties = options.properties;
|
|
561
575
|
} else {
|
|
@@ -575,9 +589,36 @@ var init_IdentityManager = __esm({
|
|
|
575
589
|
this.properties = { ...this.properties, ...properties };
|
|
576
590
|
await this.secureStorage.set(USER_PROPERTIES_KEY, JSON.stringify(this.properties));
|
|
577
591
|
}
|
|
592
|
+
const opts = options;
|
|
593
|
+
if (opts?.phone) {
|
|
594
|
+
this.phone = opts.phone;
|
|
595
|
+
await this.secureStorage.set(USER_PHONE_KEY, this.phone);
|
|
596
|
+
}
|
|
597
|
+
if (opts?.firstName) {
|
|
598
|
+
this.firstName = opts.firstName;
|
|
599
|
+
await this.secureStorage.set(USER_FIRST_NAME_KEY, this.firstName);
|
|
600
|
+
}
|
|
601
|
+
if (opts?.lastName) {
|
|
602
|
+
this.lastName = opts.lastName;
|
|
603
|
+
await this.secureStorage.set(USER_LAST_NAME_KEY, this.lastName);
|
|
604
|
+
}
|
|
605
|
+
if (opts?.dateOfBirth) {
|
|
606
|
+
this.dateOfBirth = opts.dateOfBirth;
|
|
607
|
+
await this.secureStorage.set(USER_DOB_KEY, this.dateOfBirth);
|
|
608
|
+
}
|
|
609
|
+
if (opts?.gender) {
|
|
610
|
+
this.gender = opts.gender;
|
|
611
|
+
await this.secureStorage.set(USER_GENDER_KEY, this.gender);
|
|
612
|
+
}
|
|
578
613
|
if (this.apiClient && this.anonId) {
|
|
579
614
|
try {
|
|
580
|
-
await this.apiClient.identify(this.anonId, properties, email, this.deviceId ?? void 0
|
|
615
|
+
await this.apiClient.identify(this.anonId, properties, email, this.deviceId ?? void 0, {
|
|
616
|
+
phone: this.phone ?? void 0,
|
|
617
|
+
firstName: this.firstName ?? void 0,
|
|
618
|
+
lastName: this.lastName ?? void 0,
|
|
619
|
+
dateOfBirth: this.dateOfBirth ?? void 0,
|
|
620
|
+
gender: this.gender ?? void 0
|
|
621
|
+
});
|
|
581
622
|
} catch {
|
|
582
623
|
}
|
|
583
624
|
}
|
|
@@ -612,17 +653,32 @@ var init_IdentityManager = __esm({
|
|
|
612
653
|
this.distinctId = null;
|
|
613
654
|
this.email = null;
|
|
614
655
|
this.properties = {};
|
|
656
|
+
this.phone = null;
|
|
657
|
+
this.firstName = null;
|
|
658
|
+
this.lastName = null;
|
|
659
|
+
this.dateOfBirth = null;
|
|
660
|
+
this.gender = null;
|
|
615
661
|
await Promise.all([
|
|
616
662
|
this.secureStorage?.set(ANON_ID_KEY, newAnonId) ?? Promise.resolve(false),
|
|
617
663
|
this.secureStorage?.remove(USER_EMAIL_KEY) ?? Promise.resolve(false),
|
|
618
|
-
this.secureStorage?.remove(USER_PROPERTIES_KEY) ?? Promise.resolve(false)
|
|
664
|
+
this.secureStorage?.remove(USER_PROPERTIES_KEY) ?? Promise.resolve(false),
|
|
665
|
+
this.secureStorage?.remove(USER_PHONE_KEY) ?? Promise.resolve(false),
|
|
666
|
+
this.secureStorage?.remove(USER_FIRST_NAME_KEY) ?? Promise.resolve(false),
|
|
667
|
+
this.secureStorage?.remove(USER_LAST_NAME_KEY) ?? Promise.resolve(false),
|
|
668
|
+
this.secureStorage?.remove(USER_DOB_KEY) ?? Promise.resolve(false),
|
|
669
|
+
this.secureStorage?.remove(USER_GENDER_KEY) ?? Promise.resolve(false)
|
|
619
670
|
]);
|
|
620
671
|
}
|
|
621
672
|
getState() {
|
|
622
673
|
return {
|
|
623
674
|
deviceId: this.deviceId ?? "",
|
|
624
675
|
email: this.email,
|
|
625
|
-
properties: this.getProperties()
|
|
676
|
+
properties: this.getProperties(),
|
|
677
|
+
phone: this.phone,
|
|
678
|
+
firstName: this.firstName,
|
|
679
|
+
lastName: this.lastName,
|
|
680
|
+
dateOfBirth: this.dateOfBirth,
|
|
681
|
+
gender: this.gender
|
|
626
682
|
};
|
|
627
683
|
}
|
|
628
684
|
isSecureStorageAvailable() {
|
|
@@ -647,6 +703,18 @@ var init_IdentityManager = __esm({
|
|
|
647
703
|
if (state.email) this.email = state.email;
|
|
648
704
|
if (state.propertiesJson) this.properties = parseProperties(state.propertiesJson);
|
|
649
705
|
if (state.distinctId) this.distinctId = state.distinctId;
|
|
706
|
+
const [phone, firstName, lastName, dateOfBirth, gender] = await Promise.all([
|
|
707
|
+
this.secureStorage.get(USER_PHONE_KEY),
|
|
708
|
+
this.secureStorage.get(USER_FIRST_NAME_KEY),
|
|
709
|
+
this.secureStorage.get(USER_LAST_NAME_KEY),
|
|
710
|
+
this.secureStorage.get(USER_DOB_KEY),
|
|
711
|
+
this.secureStorage.get(USER_GENDER_KEY)
|
|
712
|
+
]);
|
|
713
|
+
if (phone) this.phone = phone;
|
|
714
|
+
if (firstName) this.firstName = firstName;
|
|
715
|
+
if (lastName) this.lastName = lastName;
|
|
716
|
+
if (dateOfBirth) this.dateOfBirth = dateOfBirth;
|
|
717
|
+
if (gender) this.gender = gender;
|
|
650
718
|
}
|
|
651
719
|
ensureInitialized() {
|
|
652
720
|
if (!this.initialized) {
|
|
@@ -787,7 +855,8 @@ var init_NativeStoreKit = __esm({
|
|
|
787
855
|
);
|
|
788
856
|
}
|
|
789
857
|
const distinctId = identityManager.getDistinctId();
|
|
790
|
-
const
|
|
858
|
+
const rawUuid = distinctId?.startsWith("$paywallo_anon:") ? distinctId.slice("$paywallo_anon:".length) : distinctId;
|
|
859
|
+
const appAccountToken = isValidUUIDv4(rawUuid) ? rawUuid : null;
|
|
791
860
|
if (distinctId && appAccountToken === null) {
|
|
792
861
|
if (PaywalloClient.getConfig()?.debug) console.log("[Paywallo] distinctId is not a valid UUID v4 \u2014 passing null to appAccountToken:", distinctId);
|
|
793
862
|
}
|
|
@@ -2268,6 +2337,7 @@ import { useCallback as useCallback2, useEffect, useRef, useState } from "react"
|
|
|
2268
2337
|
import { Animated, AppState as AppState2, Dimensions } from "react-native";
|
|
2269
2338
|
function usePaywallActions(placement, paywallConfig, onResult, variantKey, campaignId, openAnim, variantId) {
|
|
2270
2339
|
const [isPurchasing, setIsPurchasing] = useState(false);
|
|
2340
|
+
const isPurchasingRef = useRef(false);
|
|
2271
2341
|
const [isClosing, setIsClosing] = useState(false);
|
|
2272
2342
|
const slideAnim = useRef(new Animated.Value(0)).current;
|
|
2273
2343
|
const presentedAtRef = useRef(Date.now());
|
|
@@ -2299,6 +2369,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
2299
2369
|
}, [isClosing, closeWithReason]);
|
|
2300
2370
|
useEffect(() => {
|
|
2301
2371
|
const sub = AppState2.addEventListener("change", (nextState) => {
|
|
2372
|
+
if (isPurchasingRef.current) return;
|
|
2302
2373
|
if (nextState === "background" || nextState === "inactive") {
|
|
2303
2374
|
closeWithReason("backgrounded");
|
|
2304
2375
|
}
|
|
@@ -2314,6 +2385,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
2314
2385
|
const handlePurchase = useCallback2(async (productId) => {
|
|
2315
2386
|
if (isPurchasing) return;
|
|
2316
2387
|
setIsPurchasing(true);
|
|
2388
|
+
isPurchasingRef.current = true;
|
|
2317
2389
|
try {
|
|
2318
2390
|
if (paywallConfig) trackProductSelected({ placement, paywallId: paywallConfig.id, productId, variantKey, campaignId, variantId });
|
|
2319
2391
|
const result = await getIAPService().purchase(productId, {
|
|
@@ -2336,12 +2408,14 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
2336
2408
|
} catch (error) {
|
|
2337
2409
|
onResult({ presented: true, purchased: false, cancelled: false, restored: false });
|
|
2338
2410
|
} finally {
|
|
2411
|
+
isPurchasingRef.current = false;
|
|
2339
2412
|
setIsPurchasing(false);
|
|
2340
2413
|
}
|
|
2341
2414
|
}, [isPurchasing, onResult, paywallConfig, placement, trackDismissed, trackProductSelected, trackPurchased, variantKey, campaignId, variantId]);
|
|
2342
2415
|
const handleRestore = useCallback2(async () => {
|
|
2343
2416
|
if (isPurchasing) return;
|
|
2344
2417
|
setIsPurchasing(true);
|
|
2418
|
+
isPurchasingRef.current = true;
|
|
2345
2419
|
try {
|
|
2346
2420
|
const transactions = await getIAPService().restore();
|
|
2347
2421
|
if (transactions.length > 0) {
|
|
@@ -2356,6 +2430,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
2356
2430
|
} catch (error) {
|
|
2357
2431
|
onResult({ presented: true, purchased: false, cancelled: false, restored: false });
|
|
2358
2432
|
} finally {
|
|
2433
|
+
isPurchasingRef.current = false;
|
|
2359
2434
|
setIsPurchasing(false);
|
|
2360
2435
|
}
|
|
2361
2436
|
}, [isPurchasing, onResult, paywallConfig, placement, trackDismissed, variantKey, campaignId, variantId]);
|
|
@@ -2457,7 +2532,8 @@ function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts
|
|
|
2457
2532
|
if (!trackingDoneRef.current && !cancelled) {
|
|
2458
2533
|
trackingDoneRef.current = true;
|
|
2459
2534
|
const sessionId = PaywalloClient.getSessionId();
|
|
2460
|
-
|
|
2535
|
+
const distinctId = PaywalloClient.getDistinctId();
|
|
2536
|
+
await apiClient.trackEvent("$paywall_viewed", distinctId, {
|
|
2461
2537
|
placement,
|
|
2462
2538
|
paywallId: config.id,
|
|
2463
2539
|
...sessionId && { sessionId },
|
|
@@ -2465,6 +2541,16 @@ function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts
|
|
|
2465
2541
|
...campaignId && { campaignId },
|
|
2466
2542
|
...variantId && { variant_id: variantId }
|
|
2467
2543
|
});
|
|
2544
|
+
await apiClient.trackEvent("paywall", distinctId, {
|
|
2545
|
+
type: "open",
|
|
2546
|
+
paywall_id: config.id,
|
|
2547
|
+
placement,
|
|
2548
|
+
opened_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2549
|
+
...sessionId && { sessionId },
|
|
2550
|
+
...variantKey && { variant_key: variantKey },
|
|
2551
|
+
...campaignId && { campaign_id: campaignId },
|
|
2552
|
+
...variantId && { variant_id: variantId }
|
|
2553
|
+
});
|
|
2468
2554
|
}
|
|
2469
2555
|
} catch (err) {
|
|
2470
2556
|
if (cancelled) return;
|
|
@@ -2649,15 +2735,21 @@ import {
|
|
|
2649
2735
|
} from "react-native";
|
|
2650
2736
|
import { jsx } from "react/jsx-runtime";
|
|
2651
2737
|
function getNativeWebView() {
|
|
2652
|
-
if (
|
|
2738
|
+
if (NativeWebViewComponent) return NativeWebViewComponent;
|
|
2739
|
+
if (nativeWebViewLookupFailed) return null;
|
|
2740
|
+
try {
|
|
2653
2741
|
NativeWebViewComponent = requireNativeComponent("PaywalloWebView");
|
|
2742
|
+
return NativeWebViewComponent;
|
|
2743
|
+
} catch {
|
|
2744
|
+
nativeWebViewLookupFailed = true;
|
|
2745
|
+
return null;
|
|
2654
2746
|
}
|
|
2655
|
-
return NativeWebViewComponent;
|
|
2656
2747
|
}
|
|
2657
2748
|
function getWebViewEmitter() {
|
|
2658
|
-
if (
|
|
2659
|
-
|
|
2660
|
-
|
|
2749
|
+
if (webViewEmitter) return webViewEmitter;
|
|
2750
|
+
const mod = NativeModules5.PaywalloWebViewModule;
|
|
2751
|
+
if (!mod) return null;
|
|
2752
|
+
webViewEmitter = new NativeEventEmitter2(mod);
|
|
2661
2753
|
return webViewEmitter;
|
|
2662
2754
|
}
|
|
2663
2755
|
function parseErrorEvent(raw) {
|
|
@@ -2689,6 +2781,14 @@ function PaywallWebView({
|
|
|
2689
2781
|
const onReadyRef = useRef3(onReady);
|
|
2690
2782
|
onReadyRef.current = onReady;
|
|
2691
2783
|
const NativeWebView = useMemo(() => getNativeWebView(), []);
|
|
2784
|
+
useEffect3(() => {
|
|
2785
|
+
if (!NativeWebView) {
|
|
2786
|
+
onErrorRef.current?.({
|
|
2787
|
+
code: -1,
|
|
2788
|
+
description: "Paywallo native module not linked. Run `pod install` (iOS) or rebuild the Android app."
|
|
2789
|
+
});
|
|
2790
|
+
}
|
|
2791
|
+
}, [NativeWebView]);
|
|
2692
2792
|
const [resolvedWebUrl, setResolvedWebUrl] = useState3(
|
|
2693
2793
|
() => webUrlProp ?? PaywalloClient.getWebUrl()
|
|
2694
2794
|
);
|
|
@@ -2780,6 +2880,7 @@ function PaywallWebView({
|
|
|
2780
2880
|
);
|
|
2781
2881
|
useEffect3(() => {
|
|
2782
2882
|
const emitter = getWebViewEmitter();
|
|
2883
|
+
if (!emitter) return;
|
|
2783
2884
|
const loadEndSub = emitter.addListener("PaywalloWebViewLoadEnd", () => {
|
|
2784
2885
|
if (!loadEndReceived.current) {
|
|
2785
2886
|
loadEndReceived.current = true;
|
|
@@ -2846,7 +2947,7 @@ function PaywallWebView({
|
|
|
2846
2947
|
if (!paywallDataSent.current) return;
|
|
2847
2948
|
setScriptToInject(buildPurchaseStateScript(isPurchasing));
|
|
2848
2949
|
}, [isPurchasing]);
|
|
2849
|
-
if (!resolvedWebUrl) return null;
|
|
2950
|
+
if (!resolvedWebUrl || !NativeWebView) return null;
|
|
2850
2951
|
const paywallUrl = `${resolvedWebUrl}/paywall/${paywallId}`;
|
|
2851
2952
|
return /* @__PURE__ */ jsx(View, { style: styles.container, children: /* @__PURE__ */ jsx(
|
|
2852
2953
|
NativeWebView,
|
|
@@ -2860,7 +2961,7 @@ function PaywallWebView({
|
|
|
2860
2961
|
}
|
|
2861
2962
|
) });
|
|
2862
2963
|
}
|
|
2863
|
-
var NativeWebViewComponent, webViewEmitter, styles;
|
|
2964
|
+
var NativeWebViewComponent, nativeWebViewLookupFailed, webViewEmitter, styles;
|
|
2864
2965
|
var init_PaywallWebView = __esm({
|
|
2865
2966
|
"src/domains/paywall/PaywallWebView.tsx"() {
|
|
2866
2967
|
"use strict";
|
|
@@ -2868,6 +2969,7 @@ var init_PaywallWebView = __esm({
|
|
|
2868
2969
|
init_parseWebViewMessage();
|
|
2869
2970
|
init_paywallScripts();
|
|
2870
2971
|
NativeWebViewComponent = null;
|
|
2972
|
+
nativeWebViewLookupFailed = false;
|
|
2871
2973
|
webViewEmitter = null;
|
|
2872
2974
|
styles = StyleSheet.create({
|
|
2873
2975
|
container: { flex: 1 },
|
|
@@ -3194,7 +3296,8 @@ function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
|
3194
3296
|
const apiClient = PaywalloClient.getApiClient();
|
|
3195
3297
|
if (apiClient && preloadedWebView) {
|
|
3196
3298
|
const sessionId = PaywalloClient.getSessionId();
|
|
3197
|
-
|
|
3299
|
+
const distinctId = PaywalloClient.getDistinctId();
|
|
3300
|
+
void apiClient.trackEvent("$paywall_viewed", distinctId, {
|
|
3198
3301
|
placement: preloadedWebView.placement,
|
|
3199
3302
|
paywallId: preloadedWebView.paywallId,
|
|
3200
3303
|
preloaded: true,
|
|
@@ -3204,6 +3307,18 @@ function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
|
3204
3307
|
...sessionId && { sessionId }
|
|
3205
3308
|
}).catch(() => {
|
|
3206
3309
|
});
|
|
3310
|
+
void apiClient.trackEvent("paywall", distinctId, {
|
|
3311
|
+
type: "open",
|
|
3312
|
+
paywall_id: preloadedWebView.paywallId,
|
|
3313
|
+
placement: preloadedWebView.placement,
|
|
3314
|
+
opened_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3315
|
+
preloaded: true,
|
|
3316
|
+
...preloadedWebView.variantKey && { variant_key: preloadedWebView.variantKey },
|
|
3317
|
+
...preloadedWebView.campaignId && { campaign_id: preloadedWebView.campaignId },
|
|
3318
|
+
...preloadedWebView.variantId && { variant_id: preloadedWebView.variantId },
|
|
3319
|
+
...sessionId && { sessionId }
|
|
3320
|
+
}).catch(() => {
|
|
3321
|
+
});
|
|
3207
3322
|
}
|
|
3208
3323
|
});
|
|
3209
3324
|
}, [preloadedWebView]);
|
|
@@ -3296,6 +3411,8 @@ var init_CampaignGateService = __esm({
|
|
|
3296
3411
|
constructor() {
|
|
3297
3412
|
this.preloadedCampaigns = /* @__PURE__ */ new Map();
|
|
3298
3413
|
this.pendingPreloads = /* @__PURE__ */ new Set();
|
|
3414
|
+
this.apiClientRef = null;
|
|
3415
|
+
this.STALE_THRESHOLD = 0.8;
|
|
3299
3416
|
this.activePreloadPromises = /* @__PURE__ */ new Map();
|
|
3300
3417
|
}
|
|
3301
3418
|
async getCampaign(apiClient, placement, context) {
|
|
@@ -3378,12 +3495,29 @@ var init_CampaignGateService = __esm({
|
|
|
3378
3495
|
getPreloadedCampaign(placement) {
|
|
3379
3496
|
const cached = this.preloadedCampaigns.get(placement);
|
|
3380
3497
|
if (!cached) return null;
|
|
3381
|
-
|
|
3498
|
+
const age = Date.now() - cached.preloadedAt;
|
|
3499
|
+
if (age >= PRELOAD_CACHE_TTL_MS) {
|
|
3382
3500
|
this.preloadedCampaigns.delete(placement);
|
|
3383
3501
|
return null;
|
|
3384
3502
|
}
|
|
3503
|
+
if (age >= PRELOAD_CACHE_TTL_MS * this.STALE_THRESHOLD && this.apiClientRef) {
|
|
3504
|
+
void this.preloadCampaign(this.apiClientRef, placement).catch(() => {
|
|
3505
|
+
});
|
|
3506
|
+
}
|
|
3385
3507
|
return cached.campaign;
|
|
3386
3508
|
}
|
|
3509
|
+
async preloadAllActive(apiClient, debug) {
|
|
3510
|
+
this.apiClientRef = apiClient;
|
|
3511
|
+
const placements = await apiClient.getActivePlacements();
|
|
3512
|
+
if (placements.length === 0) return;
|
|
3513
|
+
if (debug) console.log(`[Paywallo PRELOAD] auto-preloading ${placements.length} placements`);
|
|
3514
|
+
for (let i = 0; i < placements.length; i++) {
|
|
3515
|
+
if (i > 0) await new Promise((r) => setTimeout(r, 500));
|
|
3516
|
+
void this.preloadCampaign(apiClient, placements[i]).catch((err) => {
|
|
3517
|
+
if (debug) console.log(`[Paywallo PRELOAD] failed ${placements[i]}:`, err);
|
|
3518
|
+
});
|
|
3519
|
+
}
|
|
3520
|
+
}
|
|
3387
3521
|
clearPreloaded() {
|
|
3388
3522
|
this.preloadedCampaigns.clear();
|
|
3389
3523
|
this.pendingPreloads.clear();
|
|
@@ -3404,7 +3538,7 @@ var init_campaign = __esm({
|
|
|
3404
3538
|
|
|
3405
3539
|
// src/domains/identity/AdvertisingIdManager.ts
|
|
3406
3540
|
import { Platform as Platform5 } from "react-native";
|
|
3407
|
-
var ZERO_IDFA, AdvertisingIdManager;
|
|
3541
|
+
var ZERO_IDFA, AdvertisingIdManager, advertisingIdManager;
|
|
3408
3542
|
var init_AdvertisingIdManager = __esm({
|
|
3409
3543
|
"src/domains/identity/AdvertisingIdManager.ts"() {
|
|
3410
3544
|
"use strict";
|
|
@@ -3414,6 +3548,14 @@ var init_AdvertisingIdManager = __esm({
|
|
|
3414
3548
|
constructor() {
|
|
3415
3549
|
this.cached = null;
|
|
3416
3550
|
}
|
|
3551
|
+
/**
|
|
3552
|
+
* Synchronous accessor for the cached collect() result. Returns null until
|
|
3553
|
+
* `collect()` resolves at least once. Used by the V2 envelope context
|
|
3554
|
+
* provider — which is sync — to populate `context.ids` without awaiting.
|
|
3555
|
+
*/
|
|
3556
|
+
getCached() {
|
|
3557
|
+
return this.cached;
|
|
3558
|
+
}
|
|
3417
3559
|
async collect(requestATT = false) {
|
|
3418
3560
|
if (this.cached) return this.cached;
|
|
3419
3561
|
const fallback = { idfv: null, idfa: null, gaid: null, attStatus: "unavailable" };
|
|
@@ -3464,136 +3606,26 @@ var init_AdvertisingIdManager = __esm({
|
|
|
3464
3606
|
return id;
|
|
3465
3607
|
}
|
|
3466
3608
|
};
|
|
3609
|
+
advertisingIdManager = new AdvertisingIdManager();
|
|
3467
3610
|
}
|
|
3468
3611
|
});
|
|
3469
3612
|
|
|
3470
|
-
// src/domains/
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
NativeBridge = NativeModules6.PaywalloFBBridge ?? null;
|
|
3478
|
-
MetaBridge = class {
|
|
3479
|
-
async getAnonymousID() {
|
|
3480
|
-
if (!NativeBridge) return null;
|
|
3481
|
-
try {
|
|
3482
|
-
let timerId;
|
|
3483
|
-
const timeout = new Promise((resolve) => {
|
|
3484
|
-
timerId = setTimeout(() => resolve(null), TIMEOUT_MS);
|
|
3485
|
-
});
|
|
3486
|
-
const result = await Promise.race([NativeBridge.getAnonymousID(), timeout]);
|
|
3487
|
-
clearTimeout(timerId);
|
|
3488
|
-
return result;
|
|
3489
|
-
} catch {
|
|
3490
|
-
return null;
|
|
3491
|
-
}
|
|
3492
|
-
}
|
|
3493
|
-
async logEvent(name, params = {}) {
|
|
3494
|
-
if (!NativeBridge) return;
|
|
3495
|
-
try {
|
|
3496
|
-
await NativeBridge.logEvent(name, params);
|
|
3497
|
-
} catch (error) {
|
|
3498
|
-
console.warn("[Paywallo:MetaBridge] logEvent failed", { name, error });
|
|
3499
|
-
}
|
|
3500
|
-
}
|
|
3501
|
-
async logPurchase(amount, currency, params = {}) {
|
|
3502
|
-
if (!NativeBridge) return;
|
|
3503
|
-
try {
|
|
3504
|
-
await NativeBridge.logPurchase(amount, currency, params);
|
|
3505
|
-
} catch (error) {
|
|
3506
|
-
console.warn("[Paywallo:MetaBridge] logPurchase failed", { amount, currency, error });
|
|
3507
|
-
}
|
|
3508
|
-
}
|
|
3509
|
-
setUserID(userId) {
|
|
3510
|
-
if (!NativeBridge) return;
|
|
3511
|
-
try {
|
|
3512
|
-
NativeBridge.setUserID(userId);
|
|
3513
|
-
} catch (error) {
|
|
3514
|
-
console.warn("[Paywallo:MetaBridge] setUserID failed", { error });
|
|
3515
|
-
}
|
|
3516
|
-
}
|
|
3517
|
-
flush() {
|
|
3518
|
-
if (!NativeBridge) return;
|
|
3519
|
-
try {
|
|
3520
|
-
NativeBridge.flush();
|
|
3521
|
-
} catch (error) {
|
|
3522
|
-
console.warn("[Paywallo:MetaBridge] flush failed", { error });
|
|
3523
|
-
}
|
|
3524
|
-
}
|
|
3525
|
-
};
|
|
3526
|
-
metaBridge = new MetaBridge();
|
|
3613
|
+
// src/domains/session/distinctIdGuard.ts
|
|
3614
|
+
async function waitForDistinctId(provider, retries = DISTINCT_ID_WAIT_RETRIES, intervalMs = DISTINCT_ID_WAIT_INTERVAL_MS) {
|
|
3615
|
+
if (!provider) return true;
|
|
3616
|
+
if (provider()) return true;
|
|
3617
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
3618
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
3619
|
+
if (provider()) return true;
|
|
3527
3620
|
}
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
var init_InstallReferrerManager = __esm({
|
|
3534
|
-
"src/domains/identity/InstallReferrerManager.ts"() {
|
|
3621
|
+
return false;
|
|
3622
|
+
}
|
|
3623
|
+
var DISTINCT_ID_WAIT_RETRIES, DISTINCT_ID_WAIT_INTERVAL_MS;
|
|
3624
|
+
var init_distinctIdGuard = __esm({
|
|
3625
|
+
"src/domains/session/distinctIdGuard.ts"() {
|
|
3535
3626
|
"use strict";
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
InstallReferrerManager = class {
|
|
3539
|
-
async getReferrer() {
|
|
3540
|
-
if (Platform6.OS !== "android") {
|
|
3541
|
-
return this.emptyResult();
|
|
3542
|
-
}
|
|
3543
|
-
let timerId;
|
|
3544
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
3545
|
-
timerId = setTimeout(() => resolve(this.emptyResult()), REFERRER_TIMEOUT_MS);
|
|
3546
|
-
});
|
|
3547
|
-
const fetchPromise = this.fetchReferrer();
|
|
3548
|
-
const result = await Promise.race([fetchPromise, timeoutPromise]);
|
|
3549
|
-
clearTimeout(timerId);
|
|
3550
|
-
return result;
|
|
3551
|
-
}
|
|
3552
|
-
async fetchReferrer() {
|
|
3553
|
-
try {
|
|
3554
|
-
const referrer = await nativeDeviceInfo.getInstallReferrer();
|
|
3555
|
-
if (!referrer) return this.emptyResult();
|
|
3556
|
-
const capped = referrer.slice(0, 2048);
|
|
3557
|
-
const params = this.parseReferrer(capped);
|
|
3558
|
-
return {
|
|
3559
|
-
rawReferrer: capped,
|
|
3560
|
-
trackingId: params["tracking_id"] || null,
|
|
3561
|
-
fbclid: params["fbclid"] || null,
|
|
3562
|
-
utmSource: params["utm_source"] || null,
|
|
3563
|
-
utmMedium: params["utm_medium"] || null,
|
|
3564
|
-
utmCampaign: params["utm_campaign"] || null
|
|
3565
|
-
};
|
|
3566
|
-
} catch {
|
|
3567
|
-
return this.emptyResult();
|
|
3568
|
-
}
|
|
3569
|
-
}
|
|
3570
|
-
parseReferrer(referrer) {
|
|
3571
|
-
const result = {};
|
|
3572
|
-
for (const pair of referrer.split("&")) {
|
|
3573
|
-
const eqIndex = pair.indexOf("=");
|
|
3574
|
-
if (eqIndex === -1) continue;
|
|
3575
|
-
try {
|
|
3576
|
-
const key = decodeURIComponent(pair.slice(0, eqIndex).replace(/\+/g, " "));
|
|
3577
|
-
const raw = pair.slice(eqIndex + 1).replace(/\+/g, " ");
|
|
3578
|
-
const value = decodeURIComponent(raw);
|
|
3579
|
-
if (key) result[key] = value;
|
|
3580
|
-
} catch {
|
|
3581
|
-
}
|
|
3582
|
-
}
|
|
3583
|
-
return result;
|
|
3584
|
-
}
|
|
3585
|
-
emptyResult() {
|
|
3586
|
-
return {
|
|
3587
|
-
rawReferrer: null,
|
|
3588
|
-
trackingId: null,
|
|
3589
|
-
fbclid: null,
|
|
3590
|
-
utmSource: null,
|
|
3591
|
-
utmMedium: null,
|
|
3592
|
-
utmCampaign: null
|
|
3593
|
-
};
|
|
3594
|
-
}
|
|
3595
|
-
};
|
|
3596
|
-
installReferrerManager = new InstallReferrerManager();
|
|
3627
|
+
DISTINCT_ID_WAIT_RETRIES = 10;
|
|
3628
|
+
DISTINCT_ID_WAIT_INTERVAL_MS = 100;
|
|
3597
3629
|
}
|
|
3598
3630
|
});
|
|
3599
3631
|
|
|
@@ -3618,25 +3650,6 @@ var init_SessionError = __esm({
|
|
|
3618
3650
|
}
|
|
3619
3651
|
});
|
|
3620
3652
|
|
|
3621
|
-
// src/domains/session/distinctIdGuard.ts
|
|
3622
|
-
async function waitForDistinctId(provider, retries = DISTINCT_ID_WAIT_RETRIES, intervalMs = DISTINCT_ID_WAIT_INTERVAL_MS) {
|
|
3623
|
-
if (!provider) return true;
|
|
3624
|
-
if (provider()) return true;
|
|
3625
|
-
for (let attempt = 0; attempt < retries; attempt++) {
|
|
3626
|
-
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
3627
|
-
if (provider()) return true;
|
|
3628
|
-
}
|
|
3629
|
-
return false;
|
|
3630
|
-
}
|
|
3631
|
-
var DISTINCT_ID_WAIT_RETRIES, DISTINCT_ID_WAIT_INTERVAL_MS;
|
|
3632
|
-
var init_distinctIdGuard = __esm({
|
|
3633
|
-
"src/domains/session/distinctIdGuard.ts"() {
|
|
3634
|
-
"use strict";
|
|
3635
|
-
DISTINCT_ID_WAIT_RETRIES = 10;
|
|
3636
|
-
DISTINCT_ID_WAIT_INTERVAL_MS = 100;
|
|
3637
|
-
}
|
|
3638
|
-
});
|
|
3639
|
-
|
|
3640
3653
|
// src/utils/deviceInfo.ts
|
|
3641
3654
|
var deviceInfo_exports = {};
|
|
3642
3655
|
__export(deviceInfo_exports, {
|
|
@@ -3647,7 +3660,9 @@ async function collectDeviceInfo() {
|
|
|
3647
3660
|
return {
|
|
3648
3661
|
appVersion: result.appVersion,
|
|
3649
3662
|
deviceModel: result.model,
|
|
3650
|
-
osVersion: result.systemVersion
|
|
3663
|
+
osVersion: result.systemVersion,
|
|
3664
|
+
darwinVersion: result.darwinVersion,
|
|
3665
|
+
webkitVersion: result.webkitVersion
|
|
3651
3666
|
};
|
|
3652
3667
|
}
|
|
3653
3668
|
var init_deviceInfo = __esm({
|
|
@@ -3947,57 +3962,6 @@ var init_SessionManager = __esm({
|
|
|
3947
3962
|
}
|
|
3948
3963
|
});
|
|
3949
3964
|
|
|
3950
|
-
// src/domains/identity/InstallIdempotency.ts
|
|
3951
|
-
async function checkAndArmInstallGuard(storage) {
|
|
3952
|
-
const alreadyTracked = await storage.get(INSTALL_KEYS.INSTALL_TRACKED);
|
|
3953
|
-
if (alreadyTracked) return true;
|
|
3954
|
-
let fallbackTracked = null;
|
|
3955
|
-
try {
|
|
3956
|
-
fallbackTracked = await nativeStorage.get(INSTALL_KEYS.LEGACY_INSTALL_TRACKED);
|
|
3957
|
-
} catch {
|
|
3958
|
-
}
|
|
3959
|
-
if (fallbackTracked) return true;
|
|
3960
|
-
await nativeStorage.set(INSTALL_KEYS.INSTALL_SENT, "1");
|
|
3961
|
-
return false;
|
|
3962
|
-
}
|
|
3963
|
-
async function markInstallTracked(storage, installedAt) {
|
|
3964
|
-
await storage.set(INSTALL_KEYS.INSTALL_TRACKED, String(installedAt));
|
|
3965
|
-
try {
|
|
3966
|
-
await nativeStorage.set(INSTALL_KEYS.LEGACY_INSTALL_TRACKED, String(installedAt));
|
|
3967
|
-
} catch {
|
|
3968
|
-
}
|
|
3969
|
-
}
|
|
3970
|
-
async function getOrCreateInstallEventId() {
|
|
3971
|
-
const existing = await nativeStorage.get(INSTALL_KEYS.INSTALL_EVENT_ID);
|
|
3972
|
-
if (existing) return existing;
|
|
3973
|
-
const { generateUUID: generateUUID2 } = await Promise.resolve().then(() => (init_uuid(), uuid_exports));
|
|
3974
|
-
const id = generateUUID2();
|
|
3975
|
-
await nativeStorage.set(INSTALL_KEYS.INSTALL_EVENT_ID, id).catch(() => {
|
|
3976
|
-
});
|
|
3977
|
-
return id;
|
|
3978
|
-
}
|
|
3979
|
-
var INSTALL_KEYS;
|
|
3980
|
-
var init_InstallIdempotency = __esm({
|
|
3981
|
-
"src/domains/identity/InstallIdempotency.ts"() {
|
|
3982
|
-
"use strict";
|
|
3983
|
-
init_NativeStorage();
|
|
3984
|
-
INSTALL_KEYS = {
|
|
3985
|
-
/** Primary flag — set AFTER a successful $app_installed dispatch. */
|
|
3986
|
-
INSTALL_TRACKED: "@panel:install_tracked",
|
|
3987
|
-
/** Legacy fallback flag written by older SDK versions. */
|
|
3988
|
-
LEGACY_INSTALL_TRACKED: "@paywallo:install_tracked",
|
|
3989
|
-
/** Pre-send guard — set BEFORE dispatching to survive concurrent cold-starts. */
|
|
3990
|
-
INSTALL_SENT: "@paywallo:app_installed_sent",
|
|
3991
|
-
/** Stable event ID for backend dedup — generated once, reused on retries. */
|
|
3992
|
-
INSTALL_EVENT_ID: "@panel:install_event_id",
|
|
3993
|
-
/** Deferred match flag — set once iOS fingerprint match succeeds. */
|
|
3994
|
-
DEFERRED_MATCH_DONE: "@panel:deferred_match_done",
|
|
3995
|
-
/** Anonymous ID fallback when FB SDK not available. */
|
|
3996
|
-
ANON_ID: "@panel:anon_id"
|
|
3997
|
-
};
|
|
3998
|
-
}
|
|
3999
|
-
});
|
|
4000
|
-
|
|
4001
3965
|
// src/domains/identity/AttributionTracker.ts
|
|
4002
3966
|
function hasAnyField(data) {
|
|
4003
3967
|
return Object.values(data).some((v) => v !== void 0 && v !== null && v !== "");
|
|
@@ -4069,21 +4033,212 @@ var init_AttributionTracker = __esm({
|
|
|
4069
4033
|
}
|
|
4070
4034
|
});
|
|
4071
4035
|
|
|
4072
|
-
// src/domains/identity/
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4036
|
+
// src/domains/identity/InstallIdempotency.ts
|
|
4037
|
+
async function checkAndArmInstallGuard(storage) {
|
|
4038
|
+
const alreadyTracked = await storage.get(INSTALL_KEYS.INSTALL_TRACKED);
|
|
4039
|
+
if (alreadyTracked) return true;
|
|
4040
|
+
let fallbackTracked = null;
|
|
4041
|
+
try {
|
|
4042
|
+
fallbackTracked = await nativeStorage.get(INSTALL_KEYS.LEGACY_INSTALL_TRACKED);
|
|
4043
|
+
} catch {
|
|
4044
|
+
}
|
|
4045
|
+
if (fallbackTracked) return true;
|
|
4046
|
+
await nativeStorage.set(INSTALL_KEYS.INSTALL_SENT, "1");
|
|
4047
|
+
return false;
|
|
4048
|
+
}
|
|
4049
|
+
async function markInstallTracked(storage, installedAt) {
|
|
4050
|
+
await storage.set(INSTALL_KEYS.INSTALL_TRACKED, String(installedAt));
|
|
4051
|
+
try {
|
|
4052
|
+
await nativeStorage.set(INSTALL_KEYS.LEGACY_INSTALL_TRACKED, String(installedAt));
|
|
4053
|
+
} catch {
|
|
4054
|
+
}
|
|
4055
|
+
}
|
|
4056
|
+
async function getOrCreateInstallEventId() {
|
|
4057
|
+
const existing = await nativeStorage.get(INSTALL_KEYS.INSTALL_EVENT_ID);
|
|
4058
|
+
if (existing) return existing;
|
|
4059
|
+
const { generateUUID: generateUUID2 } = await Promise.resolve().then(() => (init_uuid(), uuid_exports));
|
|
4060
|
+
const id = generateUUID2();
|
|
4061
|
+
await nativeStorage.set(INSTALL_KEYS.INSTALL_EVENT_ID, id).catch(() => {
|
|
4062
|
+
});
|
|
4063
|
+
return id;
|
|
4064
|
+
}
|
|
4065
|
+
var INSTALL_KEYS;
|
|
4066
|
+
var init_InstallIdempotency = __esm({
|
|
4067
|
+
"src/domains/identity/InstallIdempotency.ts"() {
|
|
4068
|
+
"use strict";
|
|
4069
|
+
init_NativeStorage();
|
|
4070
|
+
INSTALL_KEYS = {
|
|
4071
|
+
/** Primary flag — set AFTER a successful $app_installed dispatch. */
|
|
4072
|
+
INSTALL_TRACKED: "@panel:install_tracked",
|
|
4073
|
+
/** Legacy fallback flag written by older SDK versions. */
|
|
4074
|
+
LEGACY_INSTALL_TRACKED: "@paywallo:install_tracked",
|
|
4075
|
+
/** Pre-send guard — set BEFORE dispatching to survive concurrent cold-starts. */
|
|
4076
|
+
INSTALL_SENT: "@paywallo:app_installed_sent",
|
|
4077
|
+
/** Stable event ID for backend dedup — generated once, reused on retries. */
|
|
4078
|
+
INSTALL_EVENT_ID: "@panel:install_event_id",
|
|
4079
|
+
/** Deferred match flag — set once iOS fingerprint match succeeds. */
|
|
4080
|
+
DEFERRED_MATCH_DONE: "@panel:deferred_match_done",
|
|
4081
|
+
/** Anonymous ID fallback when FB SDK not available. */
|
|
4082
|
+
ANON_ID: "@panel:anon_id"
|
|
4083
|
+
};
|
|
4084
|
+
}
|
|
4085
|
+
});
|
|
4086
|
+
|
|
4087
|
+
// src/domains/identity/InstallReferrerManager.ts
|
|
4088
|
+
import { Platform as Platform6 } from "react-native";
|
|
4089
|
+
var REFERRER_TIMEOUT_MS, InstallReferrerManager, installReferrerManager;
|
|
4090
|
+
var init_InstallReferrerManager = __esm({
|
|
4091
|
+
"src/domains/identity/InstallReferrerManager.ts"() {
|
|
4092
|
+
"use strict";
|
|
4093
|
+
init_NativeDeviceInfo();
|
|
4094
|
+
REFERRER_TIMEOUT_MS = 5e3;
|
|
4095
|
+
InstallReferrerManager = class {
|
|
4096
|
+
async getReferrer() {
|
|
4097
|
+
if (Platform6.OS !== "android") {
|
|
4098
|
+
return this.emptyResult();
|
|
4099
|
+
}
|
|
4100
|
+
let timerId;
|
|
4101
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
4102
|
+
timerId = setTimeout(() => resolve(this.emptyResult()), REFERRER_TIMEOUT_MS);
|
|
4103
|
+
});
|
|
4104
|
+
const fetchPromise = this.fetchReferrer();
|
|
4105
|
+
const result = await Promise.race([fetchPromise, timeoutPromise]);
|
|
4106
|
+
clearTimeout(timerId);
|
|
4107
|
+
return result;
|
|
4108
|
+
}
|
|
4109
|
+
async fetchReferrer() {
|
|
4110
|
+
try {
|
|
4111
|
+
const referrer = await nativeDeviceInfo.getInstallReferrer();
|
|
4112
|
+
if (!referrer) return this.emptyResult();
|
|
4113
|
+
const capped = referrer.slice(0, 2048);
|
|
4114
|
+
const params = this.parseReferrer(capped);
|
|
4115
|
+
return {
|
|
4116
|
+
rawReferrer: capped,
|
|
4117
|
+
trackingId: params["tracking_id"] || null,
|
|
4118
|
+
fbclid: params["fbclid"] || null,
|
|
4119
|
+
utmSource: params["utm_source"] || null,
|
|
4120
|
+
utmMedium: params["utm_medium"] || null,
|
|
4121
|
+
utmCampaign: params["utm_campaign"] || null
|
|
4122
|
+
};
|
|
4123
|
+
} catch {
|
|
4124
|
+
return this.emptyResult();
|
|
4125
|
+
}
|
|
4126
|
+
}
|
|
4127
|
+
parseReferrer(referrer) {
|
|
4128
|
+
const result = {};
|
|
4129
|
+
for (const pair of referrer.split("&")) {
|
|
4130
|
+
const eqIndex = pair.indexOf("=");
|
|
4131
|
+
if (eqIndex === -1) continue;
|
|
4132
|
+
try {
|
|
4133
|
+
const key = decodeURIComponent(pair.slice(0, eqIndex).replace(/\+/g, " "));
|
|
4134
|
+
const raw = pair.slice(eqIndex + 1).replace(/\+/g, " ");
|
|
4135
|
+
const value = decodeURIComponent(raw);
|
|
4136
|
+
if (key) result[key] = value;
|
|
4137
|
+
} catch {
|
|
4138
|
+
}
|
|
4139
|
+
}
|
|
4140
|
+
return result;
|
|
4141
|
+
}
|
|
4142
|
+
emptyResult() {
|
|
4143
|
+
return {
|
|
4144
|
+
rawReferrer: null,
|
|
4145
|
+
trackingId: null,
|
|
4146
|
+
fbclid: null,
|
|
4147
|
+
utmSource: null,
|
|
4148
|
+
utmMedium: null,
|
|
4149
|
+
utmCampaign: null
|
|
4150
|
+
};
|
|
4151
|
+
}
|
|
4152
|
+
};
|
|
4153
|
+
installReferrerManager = new InstallReferrerManager();
|
|
4154
|
+
}
|
|
4155
|
+
});
|
|
4156
|
+
|
|
4157
|
+
// src/domains/identity/MetaBridge.ts
|
|
4158
|
+
import { NativeModules as NativeModules6 } from "react-native";
|
|
4159
|
+
var TIMEOUT_MS, NativeBridge, MetaBridge, metaBridge;
|
|
4160
|
+
var init_MetaBridge = __esm({
|
|
4161
|
+
"src/domains/identity/MetaBridge.ts"() {
|
|
4162
|
+
"use strict";
|
|
4163
|
+
TIMEOUT_MS = 2e3;
|
|
4164
|
+
NativeBridge = NativeModules6.PaywalloFBBridge ?? null;
|
|
4165
|
+
MetaBridge = class {
|
|
4166
|
+
constructor() {
|
|
4167
|
+
this.cachedAnonId = null;
|
|
4168
|
+
}
|
|
4169
|
+
/** Sync read of the cached anonymous ID. Returns null until `getAnonymousID()` resolves once. */
|
|
4170
|
+
getCachedAnonymousID() {
|
|
4171
|
+
return this.cachedAnonId;
|
|
4172
|
+
}
|
|
4173
|
+
async getAnonymousID() {
|
|
4174
|
+
if (this.cachedAnonId) return this.cachedAnonId;
|
|
4175
|
+
if (!NativeBridge) return null;
|
|
4176
|
+
try {
|
|
4177
|
+
let timerId;
|
|
4178
|
+
const timeout = new Promise((resolve) => {
|
|
4179
|
+
timerId = setTimeout(() => resolve(null), TIMEOUT_MS);
|
|
4180
|
+
});
|
|
4181
|
+
const result = await Promise.race([NativeBridge.getAnonymousID(), timeout]);
|
|
4182
|
+
clearTimeout(timerId);
|
|
4183
|
+
if (result) this.cachedAnonId = result;
|
|
4184
|
+
return result;
|
|
4185
|
+
} catch {
|
|
4186
|
+
return null;
|
|
4187
|
+
}
|
|
4188
|
+
}
|
|
4189
|
+
async logEvent(name, params = {}) {
|
|
4190
|
+
if (!NativeBridge) return;
|
|
4191
|
+
try {
|
|
4192
|
+
await NativeBridge.logEvent(name, params);
|
|
4193
|
+
} catch (error) {
|
|
4194
|
+
console.warn("[Paywallo:MetaBridge] logEvent failed", { name, error });
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
async logPurchase(amount, currency, params = {}) {
|
|
4198
|
+
if (!NativeBridge) return;
|
|
4199
|
+
try {
|
|
4200
|
+
await NativeBridge.logPurchase(amount, currency, params);
|
|
4201
|
+
} catch (error) {
|
|
4202
|
+
console.warn("[Paywallo:MetaBridge] logPurchase failed", { amount, currency, error });
|
|
4203
|
+
}
|
|
4204
|
+
}
|
|
4205
|
+
setUserID(userId) {
|
|
4206
|
+
if (!NativeBridge) return;
|
|
4207
|
+
try {
|
|
4208
|
+
NativeBridge.setUserID(userId);
|
|
4209
|
+
} catch (error) {
|
|
4210
|
+
console.warn("[Paywallo:MetaBridge] setUserID failed", { error });
|
|
4211
|
+
}
|
|
4212
|
+
}
|
|
4213
|
+
flush() {
|
|
4214
|
+
if (!NativeBridge) return;
|
|
4215
|
+
try {
|
|
4216
|
+
NativeBridge.flush();
|
|
4217
|
+
} catch (error) {
|
|
4218
|
+
console.warn("[Paywallo:MetaBridge] flush failed", { error });
|
|
4219
|
+
}
|
|
4220
|
+
}
|
|
4221
|
+
};
|
|
4222
|
+
metaBridge = new MetaBridge();
|
|
4223
|
+
}
|
|
4224
|
+
});
|
|
4225
|
+
|
|
4226
|
+
// src/domains/identity/InstallTracker.ts
|
|
4227
|
+
import { Dimensions as Dimensions3, Platform as Platform7, PixelRatio } from "react-native";
|
|
4228
|
+
var InstallTracker;
|
|
4229
|
+
var init_InstallTracker = __esm({
|
|
4230
|
+
"src/domains/identity/InstallTracker.ts"() {
|
|
4231
|
+
"use strict";
|
|
4232
|
+
init_SecureStorage();
|
|
4233
|
+
init_NativeDeviceInfo();
|
|
4085
4234
|
init_distinctIdGuard();
|
|
4235
|
+
init_SessionManager();
|
|
4236
|
+
init_AdvertisingIdManager();
|
|
4237
|
+
init_AttributionTracker();
|
|
4238
|
+
init_IdentityManager();
|
|
4086
4239
|
init_InstallIdempotency();
|
|
4240
|
+
init_InstallReferrerManager();
|
|
4241
|
+
init_MetaBridge();
|
|
4087
4242
|
init_AttributionTracker();
|
|
4088
4243
|
InstallTracker = class {
|
|
4089
4244
|
constructor(debug = false, optionsOrManager) {
|
|
@@ -4094,7 +4249,7 @@ var init_InstallTracker = __esm({
|
|
|
4094
4249
|
this.distinctIdProvider = () => identityManager.getDistinctId();
|
|
4095
4250
|
} else {
|
|
4096
4251
|
const opts = optionsOrManager ?? {};
|
|
4097
|
-
this.advertisingIdManager = opts.advertisingIdManager ??
|
|
4252
|
+
this.advertisingIdManager = opts.advertisingIdManager ?? advertisingIdManager;
|
|
4098
4253
|
this.distinctIdProvider = opts.distinctIdProvider ?? (() => identityManager.getDistinctId());
|
|
4099
4254
|
}
|
|
4100
4255
|
}
|
|
@@ -4132,6 +4287,7 @@ var init_InstallTracker = __esm({
|
|
|
4132
4287
|
const screen = Dimensions3.get("screen");
|
|
4133
4288
|
const screenWidth = Math.round(screen.width ?? 0);
|
|
4134
4289
|
const screenHeight = Math.round(screen.height ?? 0);
|
|
4290
|
+
const screenDensity = PixelRatio.get();
|
|
4135
4291
|
const locale = Intl.DateTimeFormat().resolvedOptions().locale ?? "unknown";
|
|
4136
4292
|
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? "unknown";
|
|
4137
4293
|
const info = await nativeDeviceInfo.getDeviceInfo();
|
|
@@ -4178,6 +4334,7 @@ var init_InstallTracker = __esm({
|
|
|
4178
4334
|
buildNumber,
|
|
4179
4335
|
...screenWidth > 0 && { screenWidth },
|
|
4180
4336
|
...screenHeight > 0 && { screenHeight },
|
|
4337
|
+
...screenDensity > 0 && { screenDensity },
|
|
4181
4338
|
timezone,
|
|
4182
4339
|
locale,
|
|
4183
4340
|
...carrier !== "unknown" && { carrier },
|
|
@@ -4195,6 +4352,16 @@ var init_InstallTracker = __esm({
|
|
|
4195
4352
|
this.advertisingIdManager.collect(requestATT),
|
|
4196
4353
|
getOrCreateInstallEventId()
|
|
4197
4354
|
]);
|
|
4355
|
+
if (referrer.fbclid || referrer.utmSource || referrer.utmMedium || referrer.utmCampaign) {
|
|
4356
|
+
attributionTracker.capture({
|
|
4357
|
+
...referrer.fbclid && { fbclid: referrer.fbclid },
|
|
4358
|
+
...referrer.utmSource && { utmSource: referrer.utmSource },
|
|
4359
|
+
...referrer.utmMedium && { utmMedium: referrer.utmMedium },
|
|
4360
|
+
...referrer.utmCampaign && { utmCampaign: referrer.utmCampaign },
|
|
4361
|
+
...referrer.rawReferrer && { referrer: referrer.rawReferrer }
|
|
4362
|
+
}).catch(() => {
|
|
4363
|
+
});
|
|
4364
|
+
}
|
|
4198
4365
|
let effectiveAnonId = fbAnonId;
|
|
4199
4366
|
if (!effectiveAnonId) {
|
|
4200
4367
|
const stored = await storage.get(INSTALL_KEYS.ANON_ID);
|
|
@@ -4239,7 +4406,7 @@ var init_InstallTracker = __esm({
|
|
|
4239
4406
|
const baseUrl = apiClient.getBaseUrl();
|
|
4240
4407
|
const appKey = apiClient.getAppKey();
|
|
4241
4408
|
const referrer = await installReferrerManager.getReferrer();
|
|
4242
|
-
await fetch(`${baseUrl}/attribution/deferred-match/${appKey}`, {
|
|
4409
|
+
await fetch(`${baseUrl}/sdk/attribution/deferred-match/${appKey}`, {
|
|
4243
4410
|
method: "POST",
|
|
4244
4411
|
headers: { "Content-Type": "application/json", "X-App-Key": appKey },
|
|
4245
4412
|
body: JSON.stringify({
|
|
@@ -4371,6 +4538,9 @@ var init_identity = __esm({
|
|
|
4371
4538
|
|
|
4372
4539
|
// src/domains/notifications/bridges/NativePushBridge.ts
|
|
4373
4540
|
import { NativeModules as NativeModules7, NativeEventEmitter as NativeEventEmitter3, Platform as Platform8 } from "react-native";
|
|
4541
|
+
function isNativePushAvailable() {
|
|
4542
|
+
return !!NativeModules7.PaywalloNotifications;
|
|
4543
|
+
}
|
|
4374
4544
|
function mapStatusToNumber(status) {
|
|
4375
4545
|
switch (status) {
|
|
4376
4546
|
case "granted":
|
|
@@ -5034,8 +5204,8 @@ var init_utils = __esm({
|
|
|
5034
5204
|
// src/core/version.ts
|
|
5035
5205
|
function resolveVersion() {
|
|
5036
5206
|
try {
|
|
5037
|
-
if ("2.1
|
|
5038
|
-
return "2.1
|
|
5207
|
+
if ("2.2.1") {
|
|
5208
|
+
return "2.2.1";
|
|
5039
5209
|
}
|
|
5040
5210
|
} catch {
|
|
5041
5211
|
}
|
|
@@ -5117,7 +5287,7 @@ var init_TokenRegistration = __esm({
|
|
|
5117
5287
|
init_utils();
|
|
5118
5288
|
init_version();
|
|
5119
5289
|
FCM_TOKEN_KEY = "@panel:push_token";
|
|
5120
|
-
TOKEN_ENDPOINT = "/push-tokens";
|
|
5290
|
+
TOKEN_ENDPOINT = "/sdk/push-tokens";
|
|
5121
5291
|
}
|
|
5122
5292
|
});
|
|
5123
5293
|
|
|
@@ -5396,71 +5566,413 @@ var init_NotificationsManager = __esm({
|
|
|
5396
5566
|
registerBackgroundHandler(cb) {
|
|
5397
5567
|
registerBackgroundMessageHandler(cb);
|
|
5398
5568
|
}
|
|
5399
|
-
destroy() {
|
|
5400
|
-
this.tokenRefreshCleanup?.();
|
|
5401
|
-
this.tokenRefreshCleanup = null;
|
|
5402
|
-
this.foregroundCleanup?.();
|
|
5403
|
-
this.foregroundCleanup = null;
|
|
5404
|
-
this.tracker = null;
|
|
5405
|
-
this.receivedCallbacks = [];
|
|
5406
|
-
this.openedCallbacks = [];
|
|
5407
|
-
this.dismissedCallbacks = [];
|
|
5408
|
-
this.isInitialized = false;
|
|
5409
|
-
this.currentToken = null;
|
|
5569
|
+
destroy() {
|
|
5570
|
+
this.tokenRefreshCleanup?.();
|
|
5571
|
+
this.tokenRefreshCleanup = null;
|
|
5572
|
+
this.foregroundCleanup?.();
|
|
5573
|
+
this.foregroundCleanup = null;
|
|
5574
|
+
this.tracker = null;
|
|
5575
|
+
this.receivedCallbacks = [];
|
|
5576
|
+
this.openedCallbacks = [];
|
|
5577
|
+
this.dismissedCallbacks = [];
|
|
5578
|
+
this.isInitialized = false;
|
|
5579
|
+
this.currentToken = null;
|
|
5580
|
+
}
|
|
5581
|
+
};
|
|
5582
|
+
notificationsManager = new NotificationsManager();
|
|
5583
|
+
}
|
|
5584
|
+
});
|
|
5585
|
+
|
|
5586
|
+
// src/domains/notifications/index.ts
|
|
5587
|
+
var init_notifications = __esm({
|
|
5588
|
+
"src/domains/notifications/index.ts"() {
|
|
5589
|
+
"use strict";
|
|
5590
|
+
init_NotificationsManager();
|
|
5591
|
+
init_NativePushBridge();
|
|
5592
|
+
init_NotificationsError();
|
|
5593
|
+
}
|
|
5594
|
+
});
|
|
5595
|
+
|
|
5596
|
+
// src/domains/session/index.ts
|
|
5597
|
+
var init_session = __esm({
|
|
5598
|
+
"src/domains/session/index.ts"() {
|
|
5599
|
+
"use strict";
|
|
5600
|
+
init_SessionManager();
|
|
5601
|
+
init_SessionError();
|
|
5602
|
+
}
|
|
5603
|
+
});
|
|
5604
|
+
|
|
5605
|
+
// src/core/PaywalloState.ts
|
|
5606
|
+
function createPaywalloState() {
|
|
5607
|
+
return {
|
|
5608
|
+
config: null,
|
|
5609
|
+
apiClient: null,
|
|
5610
|
+
initPromise: null,
|
|
5611
|
+
readyPromise: null,
|
|
5612
|
+
resolveReady: null,
|
|
5613
|
+
paywallPresenter: null,
|
|
5614
|
+
campaignPresenter: null,
|
|
5615
|
+
subscriptionGetter: null,
|
|
5616
|
+
activeChecker: null,
|
|
5617
|
+
restoreHandler: null,
|
|
5618
|
+
lastOnboardingStepTimestamp: null,
|
|
5619
|
+
pendingConfig: null,
|
|
5620
|
+
networkCleanup: null,
|
|
5621
|
+
initAttempts: 0,
|
|
5622
|
+
autoPreloadedPlacement: null,
|
|
5623
|
+
autoPreloadPlacementPromise: null,
|
|
5624
|
+
sessionFlagsMap: /* @__PURE__ */ new Map(),
|
|
5625
|
+
pendingIdentifies: []
|
|
5626
|
+
};
|
|
5627
|
+
}
|
|
5628
|
+
var MAX_INIT_RETRIES, RETRY_DELAYS;
|
|
5629
|
+
var init_PaywalloState = __esm({
|
|
5630
|
+
"src/core/PaywalloState.ts"() {
|
|
5631
|
+
"use strict";
|
|
5632
|
+
MAX_INIT_RETRIES = 3;
|
|
5633
|
+
RETRY_DELAYS = [2e3, 5e3, 1e4];
|
|
5634
|
+
}
|
|
5635
|
+
});
|
|
5636
|
+
|
|
5637
|
+
// src/domains/plan/PlanCache.ts
|
|
5638
|
+
var DEFAULT_TTL, PlanCache, planCache;
|
|
5639
|
+
var init_PlanCache = __esm({
|
|
5640
|
+
"src/domains/plan/PlanCache.ts"() {
|
|
5641
|
+
"use strict";
|
|
5642
|
+
DEFAULT_TTL = 5 * 60 * 1e3;
|
|
5643
|
+
PlanCache = class {
|
|
5644
|
+
constructor() {
|
|
5645
|
+
this.cache = null;
|
|
5646
|
+
this.ttl = DEFAULT_TTL;
|
|
5647
|
+
}
|
|
5648
|
+
get() {
|
|
5649
|
+
if (!this.cache) return null;
|
|
5650
|
+
const isStale = Date.now() - this.cache.cachedAt > this.ttl;
|
|
5651
|
+
return { ...this.cache, isStale };
|
|
5652
|
+
}
|
|
5653
|
+
set(data) {
|
|
5654
|
+
this.cache = { data, cachedAt: Date.now(), isStale: false };
|
|
5655
|
+
}
|
|
5656
|
+
invalidate() {
|
|
5657
|
+
this.cache = null;
|
|
5658
|
+
}
|
|
5659
|
+
setTTL(ttl) {
|
|
5660
|
+
this.ttl = ttl;
|
|
5661
|
+
}
|
|
5662
|
+
};
|
|
5663
|
+
planCache = new PlanCache();
|
|
5664
|
+
}
|
|
5665
|
+
});
|
|
5666
|
+
|
|
5667
|
+
// src/domains/plan/PlanError.ts
|
|
5668
|
+
var PlanError, PLAN_ERROR_CODES;
|
|
5669
|
+
var init_PlanError = __esm({
|
|
5670
|
+
"src/domains/plan/PlanError.ts"() {
|
|
5671
|
+
"use strict";
|
|
5672
|
+
init_PaywalloError();
|
|
5673
|
+
PlanError = class extends PaywalloError {
|
|
5674
|
+
constructor(code, message) {
|
|
5675
|
+
super("plan", code, message);
|
|
5676
|
+
this.name = "PlanError";
|
|
5677
|
+
}
|
|
5678
|
+
};
|
|
5679
|
+
PLAN_ERROR_CODES = {
|
|
5680
|
+
NOT_INITIALIZED: "PLAN_NOT_INITIALIZED",
|
|
5681
|
+
FETCH_FAILED: "PLAN_FETCH_FAILED"
|
|
5682
|
+
};
|
|
5683
|
+
}
|
|
5684
|
+
});
|
|
5685
|
+
|
|
5686
|
+
// src/domains/plan/PlanService.ts
|
|
5687
|
+
var PlanService_exports = {};
|
|
5688
|
+
__export(PlanService_exports, {
|
|
5689
|
+
PlanService: () => PlanService,
|
|
5690
|
+
planService: () => planService
|
|
5691
|
+
});
|
|
5692
|
+
function mapProduct(raw) {
|
|
5693
|
+
return {
|
|
5694
|
+
id: raw.id,
|
|
5695
|
+
name: raw.name,
|
|
5696
|
+
description: raw.description,
|
|
5697
|
+
type: raw.type,
|
|
5698
|
+
appleProductId: raw.apple_product_id,
|
|
5699
|
+
googleProductId: raw.google_product_id,
|
|
5700
|
+
billingPeriod: raw.billing_period,
|
|
5701
|
+
trialDays: raw.trial_days,
|
|
5702
|
+
priceUsd: raw.price_usd,
|
|
5703
|
+
regionalPrices: raw.regional_prices,
|
|
5704
|
+
displayOrder: raw.display_order,
|
|
5705
|
+
isActive: raw.is_active
|
|
5706
|
+
};
|
|
5707
|
+
}
|
|
5708
|
+
function mapPlan(raw) {
|
|
5709
|
+
return {
|
|
5710
|
+
id: raw.id,
|
|
5711
|
+
identifier: raw.identifier,
|
|
5712
|
+
name: raw.name,
|
|
5713
|
+
description: raw.description,
|
|
5714
|
+
metadata: raw.metadata,
|
|
5715
|
+
products: raw.products.map(mapProduct)
|
|
5716
|
+
};
|
|
5717
|
+
}
|
|
5718
|
+
var PlanService, planService;
|
|
5719
|
+
var init_PlanService = __esm({
|
|
5720
|
+
"src/domains/plan/PlanService.ts"() {
|
|
5721
|
+
"use strict";
|
|
5722
|
+
init_PlanCache();
|
|
5723
|
+
init_PlanError();
|
|
5724
|
+
PlanService = class {
|
|
5725
|
+
constructor() {
|
|
5726
|
+
this.config = null;
|
|
5727
|
+
this.cache = planCache;
|
|
5728
|
+
}
|
|
5729
|
+
init(config) {
|
|
5730
|
+
this.config = config;
|
|
5731
|
+
}
|
|
5732
|
+
async getCurrentPlan(forceRefresh = false) {
|
|
5733
|
+
if (!forceRefresh) {
|
|
5734
|
+
const cached = this.cache.get();
|
|
5735
|
+
if (cached && !cached.isStale) {
|
|
5736
|
+
const current = cached.data.plans.find(
|
|
5737
|
+
(p) => p.identifier === cached.data.currentIdentifier
|
|
5738
|
+
);
|
|
5739
|
+
return current ?? null;
|
|
5740
|
+
}
|
|
5741
|
+
}
|
|
5742
|
+
return this.fetchCurrentPlan();
|
|
5743
|
+
}
|
|
5744
|
+
async getAllPlans(forceRefresh = false) {
|
|
5745
|
+
if (!forceRefresh) {
|
|
5746
|
+
const cached = this.cache.get();
|
|
5747
|
+
if (cached && !cached.isStale) return cached.data;
|
|
5748
|
+
}
|
|
5749
|
+
return this.fetchAllPlans();
|
|
5750
|
+
}
|
|
5751
|
+
invalidateCache() {
|
|
5752
|
+
this.cache.invalidate();
|
|
5753
|
+
}
|
|
5754
|
+
getApiClient() {
|
|
5755
|
+
if (!this.config) {
|
|
5756
|
+
throw new PlanError(PLAN_ERROR_CODES.NOT_INITIALIZED, "PlanService not initialized. Call Paywallo.init() first");
|
|
5757
|
+
}
|
|
5758
|
+
return this.config.apiClient;
|
|
5759
|
+
}
|
|
5760
|
+
async fetchCurrentPlan() {
|
|
5761
|
+
try {
|
|
5762
|
+
const res = await this.getApiClient().get("/sdk/plans");
|
|
5763
|
+
if (!res.ok) {
|
|
5764
|
+
this.log("fetchCurrentPlan failed", res.status);
|
|
5765
|
+
return null;
|
|
5766
|
+
}
|
|
5767
|
+
const raw = res.data.data.plan;
|
|
5768
|
+
return raw ? mapPlan(raw) : null;
|
|
5769
|
+
} catch (err) {
|
|
5770
|
+
this.log("fetchCurrentPlan error", err);
|
|
5771
|
+
return null;
|
|
5772
|
+
}
|
|
5773
|
+
}
|
|
5774
|
+
async fetchAllPlans() {
|
|
5775
|
+
try {
|
|
5776
|
+
const res = await this.getApiClient().get("/sdk/plans/all");
|
|
5777
|
+
if (!res.ok) {
|
|
5778
|
+
this.log("fetchAllPlans failed", res.status);
|
|
5779
|
+
return { plans: [], currentIdentifier: null };
|
|
5780
|
+
}
|
|
5781
|
+
const result = {
|
|
5782
|
+
plans: res.data.data.plans.map(mapPlan),
|
|
5783
|
+
currentIdentifier: res.data.data.current_identifier
|
|
5784
|
+
};
|
|
5785
|
+
this.cache.set(result);
|
|
5786
|
+
return result;
|
|
5787
|
+
} catch (err) {
|
|
5788
|
+
this.log("fetchAllPlans error", err);
|
|
5789
|
+
return { plans: [], currentIdentifier: null };
|
|
5790
|
+
}
|
|
5791
|
+
}
|
|
5792
|
+
log(...args) {
|
|
5793
|
+
if (this.config?.debug) console.log("[Paywallo Plans]", ...args);
|
|
5794
|
+
}
|
|
5795
|
+
};
|
|
5796
|
+
planService = new PlanService();
|
|
5797
|
+
}
|
|
5798
|
+
});
|
|
5799
|
+
|
|
5800
|
+
// src/domains/plan/index.ts
|
|
5801
|
+
var init_plan = __esm({
|
|
5802
|
+
"src/domains/plan/index.ts"() {
|
|
5803
|
+
"use strict";
|
|
5804
|
+
init_PlanCache();
|
|
5805
|
+
init_PlanService();
|
|
5806
|
+
}
|
|
5807
|
+
});
|
|
5808
|
+
|
|
5809
|
+
// src/domains/onboarding/OnboardingError.ts
|
|
5810
|
+
var OnboardingError, ONBOARDING_ERROR_CODES;
|
|
5811
|
+
var init_OnboardingError = __esm({
|
|
5812
|
+
"src/domains/onboarding/OnboardingError.ts"() {
|
|
5813
|
+
"use strict";
|
|
5814
|
+
init_PaywalloError();
|
|
5815
|
+
OnboardingError = class extends PaywalloError {
|
|
5816
|
+
constructor(code, message) {
|
|
5817
|
+
super("onboarding", code, message);
|
|
5818
|
+
this.name = "OnboardingError";
|
|
5819
|
+
}
|
|
5820
|
+
};
|
|
5821
|
+
ONBOARDING_ERROR_CODES = {
|
|
5822
|
+
NOT_INITIALIZED: "ONBOARDING_NOT_INITIALIZED",
|
|
5823
|
+
INVALID_STEP_NAME: "ONBOARDING_INVALID_STEP_NAME"
|
|
5824
|
+
};
|
|
5825
|
+
}
|
|
5826
|
+
});
|
|
5827
|
+
|
|
5828
|
+
// src/domains/onboarding/OnboardingManager.ts
|
|
5829
|
+
var OnboardingManager, onboardingManager;
|
|
5830
|
+
var init_OnboardingManager = __esm({
|
|
5831
|
+
"src/domains/onboarding/OnboardingManager.ts"() {
|
|
5832
|
+
"use strict";
|
|
5833
|
+
init_OnboardingError();
|
|
5834
|
+
OnboardingManager = class {
|
|
5835
|
+
constructor() {
|
|
5836
|
+
this.pipeline = null;
|
|
5837
|
+
this.debug = false;
|
|
5838
|
+
this.lastStep = null;
|
|
5839
|
+
this.finished = false;
|
|
5840
|
+
}
|
|
5841
|
+
/**
|
|
5842
|
+
* Injects runtime dependencies. Called by PaywalloClient during init.
|
|
5843
|
+
*/
|
|
5844
|
+
injectDeps(config) {
|
|
5845
|
+
this.pipeline = config.pipeline;
|
|
5846
|
+
this.debug = config.debug ?? false;
|
|
5847
|
+
}
|
|
5848
|
+
/**
|
|
5849
|
+
* Tracks an onboarding step view.
|
|
5850
|
+
* Saves the step name internally for implicit drop detection on the backend.
|
|
5851
|
+
*
|
|
5852
|
+
* @param stepName - Unique name for this onboarding step.
|
|
5853
|
+
*/
|
|
5854
|
+
async step(stepName) {
|
|
5855
|
+
this.assertConfig();
|
|
5856
|
+
this.validateStepName(stepName, "step");
|
|
5857
|
+
this.lastStep = stepName;
|
|
5858
|
+
const payload = {
|
|
5859
|
+
family: "onboarding",
|
|
5860
|
+
type: "step",
|
|
5861
|
+
...{ step_name: stepName }
|
|
5862
|
+
};
|
|
5863
|
+
return this.emit("onboarding", payload, "step");
|
|
5864
|
+
}
|
|
5865
|
+
/**
|
|
5866
|
+
* Tracks successful completion of the onboarding flow.
|
|
5867
|
+
* Marks the flow as finished.
|
|
5868
|
+
*/
|
|
5869
|
+
async complete() {
|
|
5870
|
+
this.assertConfig();
|
|
5871
|
+
this.finished = true;
|
|
5872
|
+
return this.emit("onboarding", { family: "onboarding", type: "complete" }, "complete");
|
|
5873
|
+
}
|
|
5874
|
+
/**
|
|
5875
|
+
* Tracks an explicit drop (abandonment) at the given step.
|
|
5876
|
+
* Marks the flow as finished.
|
|
5877
|
+
*
|
|
5878
|
+
* @param stepName - The step name where the user dropped off.
|
|
5879
|
+
*/
|
|
5880
|
+
async drop(stepName) {
|
|
5881
|
+
this.assertConfig();
|
|
5882
|
+
this.validateStepName(stepName, "drop");
|
|
5883
|
+
this.finished = true;
|
|
5884
|
+
const payload = {
|
|
5885
|
+
family: "onboarding",
|
|
5886
|
+
type: "drop",
|
|
5887
|
+
...{ step_name: stepName }
|
|
5888
|
+
};
|
|
5889
|
+
return this.emit("onboarding", payload, "drop");
|
|
5890
|
+
}
|
|
5891
|
+
/** Returns the last step name seen, or null if no step was tracked yet. */
|
|
5892
|
+
getLastStep() {
|
|
5893
|
+
return this.lastStep;
|
|
5894
|
+
}
|
|
5895
|
+
/** Returns whether the flow has been marked as finished (complete or drop). */
|
|
5896
|
+
isFinished() {
|
|
5897
|
+
return this.finished;
|
|
5898
|
+
}
|
|
5899
|
+
async emit(eventName, properties, logLabel) {
|
|
5900
|
+
const pipeline = this.pipeline;
|
|
5901
|
+
const distinctId = pipeline.getDistinctId();
|
|
5902
|
+
if (!distinctId) {
|
|
5903
|
+
if (this.debug) console.log(`[Paywallo:Onboarding] skipped (no distinctId): ${logLabel}`);
|
|
5904
|
+
return;
|
|
5905
|
+
}
|
|
5906
|
+
await pipeline.trackEvent(eventName, distinctId, properties);
|
|
5907
|
+
if (this.debug) {
|
|
5908
|
+
console.log(`[Paywallo:Onboarding] event emitted: ${eventName}.${logLabel}`, properties);
|
|
5909
|
+
}
|
|
5910
|
+
}
|
|
5911
|
+
assertConfig() {
|
|
5912
|
+
if (!this.pipeline) {
|
|
5913
|
+
throw new OnboardingError(
|
|
5914
|
+
ONBOARDING_ERROR_CODES.NOT_INITIALIZED,
|
|
5915
|
+
"OnboardingManager not initialized. Call Paywallo.init() first."
|
|
5916
|
+
);
|
|
5917
|
+
}
|
|
5918
|
+
}
|
|
5919
|
+
validateStepName(stepName, method) {
|
|
5920
|
+
if (typeof stepName !== "string" || stepName.trim().length === 0) {
|
|
5921
|
+
throw new OnboardingError(
|
|
5922
|
+
ONBOARDING_ERROR_CODES.INVALID_STEP_NAME,
|
|
5923
|
+
`OnboardingManager.${method}(): stepName must be a non-empty string.`
|
|
5924
|
+
);
|
|
5925
|
+
}
|
|
5410
5926
|
}
|
|
5411
5927
|
};
|
|
5412
|
-
|
|
5928
|
+
onboardingManager = new OnboardingManager();
|
|
5413
5929
|
}
|
|
5414
5930
|
});
|
|
5415
5931
|
|
|
5416
|
-
// src/domains/
|
|
5417
|
-
var
|
|
5418
|
-
"src/domains/
|
|
5932
|
+
// src/domains/onboarding/index.ts
|
|
5933
|
+
var init_onboarding = __esm({
|
|
5934
|
+
"src/domains/onboarding/index.ts"() {
|
|
5419
5935
|
"use strict";
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
init_NotificationsError();
|
|
5936
|
+
init_OnboardingManager();
|
|
5937
|
+
init_OnboardingError();
|
|
5423
5938
|
}
|
|
5424
5939
|
});
|
|
5425
5940
|
|
|
5426
|
-
// src/domains/
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5941
|
+
// src/domains/paywall/paywallHeartbeatRecovery.ts
|
|
5942
|
+
async function recoverPaywallHeartbeat(apiClient, distinctId, sessionId, debug) {
|
|
5943
|
+
const snapshot = await readPersistedHeartbeat();
|
|
5944
|
+
if (!snapshot) return false;
|
|
5945
|
+
try {
|
|
5946
|
+
const closedAt = new Date(snapshot.lastSeen);
|
|
5947
|
+
const durationS = Math.max(0, Math.round((snapshot.lastSeen - snapshot.presentedAt) / 1e3));
|
|
5948
|
+
await apiClient.trackEvent("paywall", distinctId, {
|
|
5949
|
+
type: "closed",
|
|
5950
|
+
paywall_id: snapshot.paywallId,
|
|
5951
|
+
placement: snapshot.placement,
|
|
5952
|
+
closed_at: closedAt.toISOString(),
|
|
5953
|
+
duration_s: durationS,
|
|
5954
|
+
close_reason: "error",
|
|
5955
|
+
...snapshot.variantId && { variant_id: snapshot.variantId },
|
|
5956
|
+
...snapshot.variantKey && { variant_key: snapshot.variantKey },
|
|
5957
|
+
...snapshot.campaignId && { campaign_id: snapshot.campaignId },
|
|
5958
|
+
...sessionId && { sessionId }
|
|
5959
|
+
});
|
|
5960
|
+
if (debug) console.log("[Paywallo HEARTBEAT] recovered orphan paywall close", {
|
|
5961
|
+
paywallId: snapshot.paywallId,
|
|
5962
|
+
durationS
|
|
5963
|
+
});
|
|
5964
|
+
return true;
|
|
5965
|
+
} catch (err) {
|
|
5966
|
+
if (debug) console.log("[Paywallo HEARTBEAT] recovery failed", err);
|
|
5967
|
+
return false;
|
|
5968
|
+
} finally {
|
|
5969
|
+
await clearPersistedHeartbeat();
|
|
5432
5970
|
}
|
|
5433
|
-
});
|
|
5434
|
-
|
|
5435
|
-
// src/core/PaywalloState.ts
|
|
5436
|
-
function createPaywalloState() {
|
|
5437
|
-
return {
|
|
5438
|
-
config: null,
|
|
5439
|
-
apiClient: null,
|
|
5440
|
-
initPromise: null,
|
|
5441
|
-
readyPromise: null,
|
|
5442
|
-
resolveReady: null,
|
|
5443
|
-
paywallPresenter: null,
|
|
5444
|
-
campaignPresenter: null,
|
|
5445
|
-
subscriptionGetter: null,
|
|
5446
|
-
activeChecker: null,
|
|
5447
|
-
restoreHandler: null,
|
|
5448
|
-
lastOnboardingStepTimestamp: null,
|
|
5449
|
-
pendingConfig: null,
|
|
5450
|
-
networkCleanup: null,
|
|
5451
|
-
initAttempts: 0,
|
|
5452
|
-
autoPreloadedPlacement: null,
|
|
5453
|
-
autoPreloadPlacementPromise: null,
|
|
5454
|
-
sessionFlagsMap: /* @__PURE__ */ new Map(),
|
|
5455
|
-
pendingIdentifies: []
|
|
5456
|
-
};
|
|
5457
5971
|
}
|
|
5458
|
-
var
|
|
5459
|
-
|
|
5460
|
-
"src/core/PaywalloState.ts"() {
|
|
5972
|
+
var init_paywallHeartbeatRecovery = __esm({
|
|
5973
|
+
"src/domains/paywall/paywallHeartbeatRecovery.ts"() {
|
|
5461
5974
|
"use strict";
|
|
5462
|
-
|
|
5463
|
-
RETRY_DELAYS = [2e3, 5e3, 1e4];
|
|
5975
|
+
init_paywallHeartbeat();
|
|
5464
5976
|
}
|
|
5465
5977
|
});
|
|
5466
5978
|
|
|
@@ -5468,7 +5980,7 @@ var init_PaywalloState = __esm({
|
|
|
5468
5980
|
function keyFor(distinctId) {
|
|
5469
5981
|
return `${CACHE_KEY_PREFIX}${distinctId}`;
|
|
5470
5982
|
}
|
|
5471
|
-
var LEGACY_CACHE_KEY, CACHE_KEY_PREFIX, CACHE_INDEX_KEY,
|
|
5983
|
+
var LEGACY_CACHE_KEY, CACHE_KEY_PREFIX, CACHE_INDEX_KEY, DEFAULT_TTL2, SubscriptionCache, subscriptionCache;
|
|
5472
5984
|
var init_SubscriptionCache = __esm({
|
|
5473
5985
|
"src/domains/subscription/SubscriptionCache.ts"() {
|
|
5474
5986
|
"use strict";
|
|
@@ -5476,9 +5988,9 @@ var init_SubscriptionCache = __esm({
|
|
|
5476
5988
|
LEGACY_CACHE_KEY = "@panel:subscription_cache";
|
|
5477
5989
|
CACHE_KEY_PREFIX = "subscription_cache:";
|
|
5478
5990
|
CACHE_INDEX_KEY = "subscription_cache:__index__";
|
|
5479
|
-
|
|
5991
|
+
DEFAULT_TTL2 = 24 * 60 * 60 * 1e3;
|
|
5480
5992
|
SubscriptionCache = class {
|
|
5481
|
-
constructor(ttl =
|
|
5993
|
+
constructor(ttl = DEFAULT_TTL2) {
|
|
5482
5994
|
this.memoryCache = /* @__PURE__ */ new Map();
|
|
5483
5995
|
this.legacyCleanupDone = false;
|
|
5484
5996
|
this.ttl = ttl;
|
|
@@ -5685,7 +6197,7 @@ var init_SubscriptionManager = __esm({
|
|
|
5685
6197
|
if (!this.config) {
|
|
5686
6198
|
return this.getEmptyStatus();
|
|
5687
6199
|
}
|
|
5688
|
-
const url = new URL(`${this.config.serverUrl}/purchases/status/${this.config.appKey}`);
|
|
6200
|
+
const url = new URL(`${this.config.serverUrl}/sdk/purchases/status/${this.config.appKey}`);
|
|
5689
6201
|
if (this.userId) {
|
|
5690
6202
|
url.searchParams.set("distinctId", this.userId);
|
|
5691
6203
|
}
|
|
@@ -5925,7 +6437,7 @@ async function getSubscriptionStatus(client, baseUrl, appKey, distinctId) {
|
|
|
5925
6437
|
}
|
|
5926
6438
|
async function getEmergencyPaywall(client) {
|
|
5927
6439
|
try {
|
|
5928
|
-
const response = await client.get("/emergency-paywall");
|
|
6440
|
+
const response = await client.get("/sdk/emergency-paywall");
|
|
5929
6441
|
if (response.status === 404) return { enabled: false };
|
|
5930
6442
|
return response.data;
|
|
5931
6443
|
} catch {
|
|
@@ -6542,7 +7054,7 @@ var init_EventBatcher = __esm({
|
|
|
6542
7054
|
BATCH_MAX_SIZE = 25;
|
|
6543
7055
|
BATCH_FLUSH_MS = 1e4;
|
|
6544
7056
|
EVENT_NAME_REGEX = /^(\$[a-zA-Z0-9_]+|[a-z][a-z0-9_]*)$/;
|
|
6545
|
-
V2_BATCH_ENDPOINT = "/ingest/batch";
|
|
7057
|
+
V2_BATCH_ENDPOINT = "/sdk/ingest/batch";
|
|
6546
7058
|
V1_BATCH_ENDPOINT = "/sdk/events/batch";
|
|
6547
7059
|
V1_SINGLE_ENDPOINT = "/sdk/events";
|
|
6548
7060
|
EventBatcher = class {
|
|
@@ -6906,7 +7418,7 @@ var init_ApiClient = __esm({
|
|
|
6906
7418
|
dispose() {
|
|
6907
7419
|
this.batcher.dispose();
|
|
6908
7420
|
}
|
|
6909
|
-
async identify(distinctId, properties, email, deviceId) {
|
|
7421
|
+
async identify(distinctId, properties, email, deviceId, pii) {
|
|
6910
7422
|
await postWithQueue(
|
|
6911
7423
|
{
|
|
6912
7424
|
isOfflineQueueEnabled: () => this.offlineQueueEnabled,
|
|
@@ -6914,8 +7426,19 @@ var init_ApiClient = __esm({
|
|
|
6914
7426
|
isDebug: () => this.debug,
|
|
6915
7427
|
post: (path, body, skipRetry) => this.post(path, body, skipRetry)
|
|
6916
7428
|
},
|
|
6917
|
-
"/identify",
|
|
6918
|
-
{
|
|
7429
|
+
"/sdk/identify",
|
|
7430
|
+
{
|
|
7431
|
+
distinctId,
|
|
7432
|
+
properties: properties ?? {},
|
|
7433
|
+
email,
|
|
7434
|
+
platform: Platform14.OS,
|
|
7435
|
+
...deviceId && { deviceId },
|
|
7436
|
+
...pii?.phone && { phone: pii.phone },
|
|
7437
|
+
...pii?.firstName && { firstName: pii.firstName },
|
|
7438
|
+
...pii?.lastName && { lastName: pii.lastName },
|
|
7439
|
+
...pii?.dateOfBirth && { dateOfBirth: pii.dateOfBirth },
|
|
7440
|
+
...pii?.gender && { gender: pii.gender }
|
|
7441
|
+
},
|
|
6919
7442
|
"identify"
|
|
6920
7443
|
);
|
|
6921
7444
|
}
|
|
@@ -6946,242 +7469,81 @@ var init_ApiClient = __esm({
|
|
|
6946
7469
|
return stale !== void 0 ? stale : null;
|
|
6947
7470
|
}
|
|
6948
7471
|
}
|
|
6949
|
-
async getEmergencyPaywall() {
|
|
6950
|
-
return getEmergencyPaywall(this);
|
|
6951
|
-
}
|
|
6952
|
-
async getCampaign(placement, distinctId, context) {
|
|
6953
|
-
const key = `${placement}:${distinctId}`;
|
|
6954
|
-
const hit = this.cache.getCampaign(key);
|
|
6955
|
-
if (hit !== void 0) return hit;
|
|
6956
|
-
try {
|
|
6957
|
-
const result = await getCampaignData(this, this.baseUrl, placement, distinctId, context);
|
|
6958
|
-
if (!result) {
|
|
6959
|
-
this.cache.setCampaign(key, null, this.cache.nullTTL);
|
|
6960
|
-
return null;
|
|
6961
|
-
}
|
|
6962
|
-
this.cache.setCampaign(key, result);
|
|
6963
|
-
return result;
|
|
6964
|
-
} catch {
|
|
6965
|
-
const stale = this.cache.getStaleCampaign(key);
|
|
6966
|
-
return stale !== void 0 ? stale : null;
|
|
6967
|
-
}
|
|
6968
|
-
}
|
|
6969
|
-
async getPrimaryCampaign(distinctId) {
|
|
6970
|
-
const key = `primary:${distinctId}`;
|
|
6971
|
-
const hit = this.cache.getCampaign(key);
|
|
6972
|
-
if (hit !== void 0) return hit;
|
|
6973
|
-
try {
|
|
6974
|
-
const res = await this.get(`/campaigns/public/primary?distinctId=${encodeURIComponent(distinctId)}`);
|
|
6975
|
-
if (res.status === 404) {
|
|
6976
|
-
this.cache.setCampaign(key, null, this.cache.nullTTL);
|
|
6977
|
-
return null;
|
|
6978
|
-
}
|
|
6979
|
-
if (!res.ok) {
|
|
6980
|
-
const stale = this.cache.getStaleCampaign(key);
|
|
6981
|
-
return stale !== void 0 ? stale : null;
|
|
6982
|
-
}
|
|
6983
|
-
this.cache.setCampaign(key, res.data);
|
|
6984
|
-
return res.data;
|
|
6985
|
-
} catch {
|
|
6986
|
-
const stale = this.cache.getStaleCampaign(key);
|
|
6987
|
-
return stale !== void 0 ? stale : null;
|
|
6988
|
-
}
|
|
6989
|
-
}
|
|
6990
|
-
async validatePurchase(platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey) {
|
|
6991
|
-
return validatePurchase(this, this.appKey, platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey);
|
|
6992
|
-
}
|
|
6993
|
-
async getSubscriptionStatus(distinctId) {
|
|
6994
|
-
return getSubscriptionStatus(this, this.baseUrl, this.appKey, distinctId);
|
|
6995
|
-
}
|
|
6996
|
-
async evaluateFlags(keys, distinctId) {
|
|
6997
|
-
return evaluateFlags(this.flagDeps(), keys, distinctId);
|
|
6998
|
-
}
|
|
6999
|
-
async getConditionalFlag(flagKey, context) {
|
|
7000
|
-
return getConditionalFlag(this.flagDeps(), flagKey, context);
|
|
7001
|
-
}
|
|
7002
|
-
async getVariantFromCache(flagKey, distinctId) {
|
|
7003
|
-
return getVariantFromCache(this.flagDeps(), flagKey, distinctId);
|
|
7004
|
-
}
|
|
7005
|
-
flagDeps() {
|
|
7006
|
-
return {
|
|
7007
|
-
get: (path) => this.get(path),
|
|
7008
|
-
httpClient: this.httpClient,
|
|
7009
|
-
cache: this.cache,
|
|
7010
|
-
appKey: this.appKey,
|
|
7011
|
-
baseUrl: this.baseUrl
|
|
7012
|
-
};
|
|
7013
|
-
}
|
|
7014
|
-
};
|
|
7015
|
-
}
|
|
7016
|
-
});
|
|
7017
|
-
|
|
7018
|
-
// src/domains/onboarding/OnboardingError.ts
|
|
7019
|
-
var OnboardingError, ONBOARDING_ERROR_CODES;
|
|
7020
|
-
var init_OnboardingError = __esm({
|
|
7021
|
-
"src/domains/onboarding/OnboardingError.ts"() {
|
|
7022
|
-
"use strict";
|
|
7023
|
-
init_PaywalloError();
|
|
7024
|
-
OnboardingError = class extends PaywalloError {
|
|
7025
|
-
constructor(code, message) {
|
|
7026
|
-
super("onboarding", code, message);
|
|
7027
|
-
this.name = "OnboardingError";
|
|
7028
|
-
}
|
|
7029
|
-
};
|
|
7030
|
-
ONBOARDING_ERROR_CODES = {
|
|
7031
|
-
NOT_INITIALIZED: "ONBOARDING_NOT_INITIALIZED",
|
|
7032
|
-
INVALID_STEP_NAME: "ONBOARDING_INVALID_STEP_NAME"
|
|
7033
|
-
};
|
|
7034
|
-
}
|
|
7035
|
-
});
|
|
7036
|
-
|
|
7037
|
-
// src/domains/onboarding/OnboardingManager.ts
|
|
7038
|
-
var OnboardingManager, onboardingManager;
|
|
7039
|
-
var init_OnboardingManager = __esm({
|
|
7040
|
-
"src/domains/onboarding/OnboardingManager.ts"() {
|
|
7041
|
-
"use strict";
|
|
7042
|
-
init_OnboardingError();
|
|
7043
|
-
OnboardingManager = class {
|
|
7044
|
-
constructor() {
|
|
7045
|
-
this.pipeline = null;
|
|
7046
|
-
this.debug = false;
|
|
7047
|
-
this.lastStep = null;
|
|
7048
|
-
this.finished = false;
|
|
7049
|
-
}
|
|
7050
|
-
/**
|
|
7051
|
-
* Injects runtime dependencies. Called by PaywalloClient during init.
|
|
7052
|
-
*/
|
|
7053
|
-
injectDeps(config) {
|
|
7054
|
-
this.pipeline = config.pipeline;
|
|
7055
|
-
this.debug = config.debug ?? false;
|
|
7056
|
-
}
|
|
7057
|
-
/**
|
|
7058
|
-
* Tracks an onboarding step view.
|
|
7059
|
-
* Saves the step name internally for implicit drop detection on the backend.
|
|
7060
|
-
*
|
|
7061
|
-
* @param stepName - Unique name for this onboarding step.
|
|
7062
|
-
*/
|
|
7063
|
-
async step(stepName) {
|
|
7064
|
-
this.assertConfig();
|
|
7065
|
-
this.validateStepName(stepName, "step");
|
|
7066
|
-
this.lastStep = stepName;
|
|
7067
|
-
const payload = {
|
|
7068
|
-
family: "onboarding",
|
|
7069
|
-
type: "step",
|
|
7070
|
-
...{ step_name: stepName }
|
|
7071
|
-
};
|
|
7072
|
-
return this.emit("onboarding", payload, "step");
|
|
7073
|
-
}
|
|
7074
|
-
/**
|
|
7075
|
-
* Tracks successful completion of the onboarding flow.
|
|
7076
|
-
* Marks the flow as finished.
|
|
7077
|
-
*/
|
|
7078
|
-
async complete() {
|
|
7079
|
-
this.assertConfig();
|
|
7080
|
-
this.finished = true;
|
|
7081
|
-
return this.emit("onboarding", { family: "onboarding", type: "complete" }, "complete");
|
|
7082
|
-
}
|
|
7083
|
-
/**
|
|
7084
|
-
* Tracks an explicit drop (abandonment) at the given step.
|
|
7085
|
-
* Marks the flow as finished.
|
|
7086
|
-
*
|
|
7087
|
-
* @param stepName - The step name where the user dropped off.
|
|
7088
|
-
*/
|
|
7089
|
-
async drop(stepName) {
|
|
7090
|
-
this.assertConfig();
|
|
7091
|
-
this.validateStepName(stepName, "drop");
|
|
7092
|
-
this.finished = true;
|
|
7093
|
-
const payload = {
|
|
7094
|
-
family: "onboarding",
|
|
7095
|
-
type: "drop",
|
|
7096
|
-
...{ step_name: stepName }
|
|
7097
|
-
};
|
|
7098
|
-
return this.emit("onboarding", payload, "drop");
|
|
7099
|
-
}
|
|
7100
|
-
/** Returns the last step name seen, or null if no step was tracked yet. */
|
|
7101
|
-
getLastStep() {
|
|
7102
|
-
return this.lastStep;
|
|
7103
|
-
}
|
|
7104
|
-
/** Returns whether the flow has been marked as finished (complete or drop). */
|
|
7105
|
-
isFinished() {
|
|
7106
|
-
return this.finished;
|
|
7472
|
+
async getEmergencyPaywall() {
|
|
7473
|
+
return getEmergencyPaywall(this);
|
|
7107
7474
|
}
|
|
7108
|
-
async
|
|
7109
|
-
const
|
|
7110
|
-
const
|
|
7111
|
-
if (
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7475
|
+
async getCampaign(placement, distinctId, context) {
|
|
7476
|
+
const key = `${placement}:${distinctId}`;
|
|
7477
|
+
const hit = this.cache.getCampaign(key);
|
|
7478
|
+
if (hit !== void 0) return hit;
|
|
7479
|
+
try {
|
|
7480
|
+
const result = await getCampaignData(this, this.baseUrl, placement, distinctId, context);
|
|
7481
|
+
if (!result) {
|
|
7482
|
+
this.cache.setCampaign(key, null, this.cache.nullTTL);
|
|
7483
|
+
return null;
|
|
7484
|
+
}
|
|
7485
|
+
this.cache.setCampaign(key, result);
|
|
7486
|
+
return result;
|
|
7487
|
+
} catch {
|
|
7488
|
+
const stale = this.cache.getStaleCampaign(key);
|
|
7489
|
+
return stale !== void 0 ? stale : null;
|
|
7118
7490
|
}
|
|
7119
7491
|
}
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7492
|
+
async getActivePlacements() {
|
|
7493
|
+
try {
|
|
7494
|
+
const res = await this.get("/sdk/campaigns/placements");
|
|
7495
|
+
if (!res.ok || !Array.isArray(res.data?.data)) return [];
|
|
7496
|
+
return res.data.data;
|
|
7497
|
+
} catch {
|
|
7498
|
+
return [];
|
|
7126
7499
|
}
|
|
7127
7500
|
}
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
);
|
|
7501
|
+
async getPrimaryCampaign(distinctId) {
|
|
7502
|
+
const key = `primary:${distinctId}`;
|
|
7503
|
+
const hit = this.cache.getCampaign(key);
|
|
7504
|
+
if (hit !== void 0) return hit;
|
|
7505
|
+
try {
|
|
7506
|
+
const res = await this.get(`/sdk/campaigns/public/primary?distinctId=${encodeURIComponent(distinctId)}`);
|
|
7507
|
+
if (res.status === 404) {
|
|
7508
|
+
this.cache.setCampaign(key, null, this.cache.nullTTL);
|
|
7509
|
+
return null;
|
|
7510
|
+
}
|
|
7511
|
+
if (!res.ok) {
|
|
7512
|
+
const stale = this.cache.getStaleCampaign(key);
|
|
7513
|
+
return stale !== void 0 ? stale : null;
|
|
7514
|
+
}
|
|
7515
|
+
this.cache.setCampaign(key, res.data);
|
|
7516
|
+
return res.data;
|
|
7517
|
+
} catch {
|
|
7518
|
+
const stale = this.cache.getStaleCampaign(key);
|
|
7519
|
+
return stale !== void 0 ? stale : null;
|
|
7134
7520
|
}
|
|
7135
7521
|
}
|
|
7522
|
+
async validatePurchase(platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey) {
|
|
7523
|
+
return validatePurchase(this, this.appKey, platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey);
|
|
7524
|
+
}
|
|
7525
|
+
async getSubscriptionStatus(distinctId) {
|
|
7526
|
+
return getSubscriptionStatus(this, this.baseUrl, this.appKey, distinctId);
|
|
7527
|
+
}
|
|
7528
|
+
async evaluateFlags(keys, distinctId) {
|
|
7529
|
+
return evaluateFlags(this.flagDeps(), keys, distinctId);
|
|
7530
|
+
}
|
|
7531
|
+
async getConditionalFlag(flagKey, context) {
|
|
7532
|
+
return getConditionalFlag(this.flagDeps(), flagKey, context);
|
|
7533
|
+
}
|
|
7534
|
+
async getVariantFromCache(flagKey, distinctId) {
|
|
7535
|
+
return getVariantFromCache(this.flagDeps(), flagKey, distinctId);
|
|
7536
|
+
}
|
|
7537
|
+
flagDeps() {
|
|
7538
|
+
return {
|
|
7539
|
+
get: (path) => this.get(path),
|
|
7540
|
+
httpClient: this.httpClient,
|
|
7541
|
+
cache: this.cache,
|
|
7542
|
+
appKey: this.appKey,
|
|
7543
|
+
baseUrl: this.baseUrl
|
|
7544
|
+
};
|
|
7545
|
+
}
|
|
7136
7546
|
};
|
|
7137
|
-
onboardingManager = new OnboardingManager();
|
|
7138
|
-
}
|
|
7139
|
-
});
|
|
7140
|
-
|
|
7141
|
-
// src/domains/onboarding/index.ts
|
|
7142
|
-
var init_onboarding = __esm({
|
|
7143
|
-
"src/domains/onboarding/index.ts"() {
|
|
7144
|
-
"use strict";
|
|
7145
|
-
init_OnboardingManager();
|
|
7146
|
-
init_OnboardingError();
|
|
7147
|
-
}
|
|
7148
|
-
});
|
|
7149
|
-
|
|
7150
|
-
// src/domains/paywall/paywallHeartbeatRecovery.ts
|
|
7151
|
-
async function recoverPaywallHeartbeat(apiClient, distinctId, sessionId, debug) {
|
|
7152
|
-
const snapshot = await readPersistedHeartbeat();
|
|
7153
|
-
if (!snapshot) return false;
|
|
7154
|
-
try {
|
|
7155
|
-
const closedAt = new Date(snapshot.lastSeen);
|
|
7156
|
-
const durationS = Math.max(0, Math.round((snapshot.lastSeen - snapshot.presentedAt) / 1e3));
|
|
7157
|
-
await apiClient.trackEvent("paywall", distinctId, {
|
|
7158
|
-
type: "closed",
|
|
7159
|
-
paywall_id: snapshot.paywallId,
|
|
7160
|
-
placement: snapshot.placement,
|
|
7161
|
-
closed_at: closedAt.toISOString(),
|
|
7162
|
-
duration_s: durationS,
|
|
7163
|
-
close_reason: "error",
|
|
7164
|
-
...snapshot.variantId && { variant_id: snapshot.variantId },
|
|
7165
|
-
...snapshot.variantKey && { variant_key: snapshot.variantKey },
|
|
7166
|
-
...snapshot.campaignId && { campaign_id: snapshot.campaignId },
|
|
7167
|
-
...sessionId && { sessionId }
|
|
7168
|
-
});
|
|
7169
|
-
if (debug) console.log("[Paywallo HEARTBEAT] recovered orphan paywall close", {
|
|
7170
|
-
paywallId: snapshot.paywallId,
|
|
7171
|
-
durationS
|
|
7172
|
-
});
|
|
7173
|
-
return true;
|
|
7174
|
-
} catch (err) {
|
|
7175
|
-
if (debug) console.log("[Paywallo HEARTBEAT] recovery failed", err);
|
|
7176
|
-
return false;
|
|
7177
|
-
} finally {
|
|
7178
|
-
await clearPersistedHeartbeat();
|
|
7179
|
-
}
|
|
7180
|
-
}
|
|
7181
|
-
var init_paywallHeartbeatRecovery = __esm({
|
|
7182
|
-
"src/domains/paywall/paywallHeartbeatRecovery.ts"() {
|
|
7183
|
-
"use strict";
|
|
7184
|
-
init_paywallHeartbeat();
|
|
7185
7547
|
}
|
|
7186
7548
|
});
|
|
7187
7549
|
|
|
@@ -7225,6 +7587,8 @@ var init_eventPipelineBridge = __esm({
|
|
|
7225
7587
|
|
|
7226
7588
|
// src/core/PaywalloInitHelpers.ts
|
|
7227
7589
|
function setupNotifications(apiClient, config, environment, eventPipeline) {
|
|
7590
|
+
if (config.notifications === false) return;
|
|
7591
|
+
if (config.notifications === void 0 && !isNativePushAvailable()) return;
|
|
7228
7592
|
try {
|
|
7229
7593
|
notificationsManager.injectDeps({
|
|
7230
7594
|
httpClient: apiClient.getHttpClient(),
|
|
@@ -7266,6 +7630,10 @@ function setupAutoPreload(state, apiClient, config, distinctId) {
|
|
|
7266
7630
|
return null;
|
|
7267
7631
|
}).catch(() => null);
|
|
7268
7632
|
}
|
|
7633
|
+
function startBatchPreload(apiClient, debug) {
|
|
7634
|
+
void campaignGateService.preloadAllActive(apiClient, debug).catch(() => {
|
|
7635
|
+
});
|
|
7636
|
+
}
|
|
7269
7637
|
var init_PaywalloInitHelpers = __esm({
|
|
7270
7638
|
"src/core/PaywalloInitHelpers.ts"() {
|
|
7271
7639
|
"use strict";
|
|
@@ -7273,6 +7641,7 @@ var init_PaywalloInitHelpers = __esm({
|
|
|
7273
7641
|
init_identity();
|
|
7274
7642
|
init_notifications();
|
|
7275
7643
|
init_SecureStorage();
|
|
7644
|
+
init_NativePushBridge();
|
|
7276
7645
|
init_constants();
|
|
7277
7646
|
}
|
|
7278
7647
|
});
|
|
@@ -7386,6 +7755,7 @@ async function doInit(state, config) {
|
|
|
7386
7755
|
cacheTTL: config.subscriptionCacheTTL,
|
|
7387
7756
|
debug: config.debug
|
|
7388
7757
|
});
|
|
7758
|
+
planService.init({ apiClient, debug: config.debug ?? false });
|
|
7389
7759
|
await identityManager.initialize(apiClient, config.debug);
|
|
7390
7760
|
if (state.pendingIdentifies.length > 0) {
|
|
7391
7761
|
for (const pending of state.pendingIdentifies) {
|
|
@@ -7408,6 +7778,9 @@ async function doInit(state, config) {
|
|
|
7408
7778
|
} catch (err) {
|
|
7409
7779
|
if (config.debug) console.log("[Paywallo ATTR] start error", err);
|
|
7410
7780
|
}
|
|
7781
|
+
void nativeDeviceInfo.getDeviceInfo().catch(() => null);
|
|
7782
|
+
void advertisingIdManager.collect(false).catch(() => null);
|
|
7783
|
+
void metaBridge.getAnonymousID().catch(() => null);
|
|
7411
7784
|
apiClient.setEventContextProvider(() => {
|
|
7412
7785
|
const attr = attributionTracker.get();
|
|
7413
7786
|
const attrEntries = attr ? [
|
|
@@ -7422,11 +7795,35 @@ async function doInit(state, config) {
|
|
|
7422
7795
|
["referrer", attr.referrer]
|
|
7423
7796
|
].filter((pair) => pair[1] !== void 0 && pair[1] !== "") : [];
|
|
7424
7797
|
const attribution = attrEntries.length > 0 ? Object.fromEntries(attrEntries) : void 0;
|
|
7798
|
+
const adIds = advertisingIdManager.getCached();
|
|
7799
|
+
const fbAnonId = metaBridge.getCachedAnonymousID();
|
|
7800
|
+
const idsEntries = [
|
|
7801
|
+
["idfa", adIds?.idfa ?? null],
|
|
7802
|
+
["idfv", adIds?.idfv ?? null],
|
|
7803
|
+
["gaid", adIds?.gaid ?? null],
|
|
7804
|
+
["fb_anon_id", fbAnonId]
|
|
7805
|
+
].filter((pair) => pair[1] !== null && pair[1] !== "");
|
|
7806
|
+
const ids = idsEntries.length > 0 ? Object.fromEntries(idsEntries) : void 0;
|
|
7807
|
+
const device = nativeDeviceInfo.getCachedDeviceInfo();
|
|
7808
|
+
let locale;
|
|
7809
|
+
let timezone;
|
|
7810
|
+
try {
|
|
7811
|
+
const opts = Intl.DateTimeFormat().resolvedOptions();
|
|
7812
|
+
locale = opts.locale || void 0;
|
|
7813
|
+
timezone = opts.timeZone || void 0;
|
|
7814
|
+
} catch {
|
|
7815
|
+
}
|
|
7425
7816
|
return {
|
|
7426
7817
|
distinct_id: identityManager.getDistinctId() || void 0,
|
|
7427
7818
|
device_id: identityManager.getDeviceId() ?? void 0,
|
|
7428
7819
|
session_id: sessionManager.getSessionId() ?? void 0,
|
|
7429
|
-
|
|
7820
|
+
app_version: device?.appVersion && device.appVersion !== "0.0.0" ? device.appVersion : void 0,
|
|
7821
|
+
os_version: device?.systemVersion && device.systemVersion !== "0.0.0" ? device.systemVersion : void 0,
|
|
7822
|
+
device_model: device?.modelId || device?.model || void 0,
|
|
7823
|
+
timezone,
|
|
7824
|
+
locale,
|
|
7825
|
+
...attribution && Object.keys(attribution).length > 0 && { attribution },
|
|
7826
|
+
...ids && Object.keys(ids).length > 0 && { ids }
|
|
7430
7827
|
};
|
|
7431
7828
|
});
|
|
7432
7829
|
await sessionManager.initialize(
|
|
@@ -7460,7 +7857,7 @@ async function doInit(state, config) {
|
|
|
7460
7857
|
state.resolveReady();
|
|
7461
7858
|
state.resolveReady = null;
|
|
7462
7859
|
}
|
|
7463
|
-
|
|
7860
|
+
console.warn("[Paywallo] initialized successfully");
|
|
7464
7861
|
if (distinctId) {
|
|
7465
7862
|
apiClient.getSubscriptionStatus(distinctId).then(() => {
|
|
7466
7863
|
if (config.debug) console.log("[Paywallo SUB] preloaded on boot");
|
|
@@ -7471,26 +7868,30 @@ async function doInit(state, config) {
|
|
|
7471
7868
|
});
|
|
7472
7869
|
}
|
|
7473
7870
|
setupAutoPreload(state, apiClient, config, distinctId);
|
|
7871
|
+
startBatchPreload(apiClient, config.debug);
|
|
7474
7872
|
}
|
|
7475
7873
|
var init_PaywalloInitializer = __esm({
|
|
7476
7874
|
"src/core/PaywalloInitializer.ts"() {
|
|
7477
7875
|
"use strict";
|
|
7478
|
-
init_SubscriptionManager();
|
|
7479
|
-
init_ApiClient();
|
|
7480
7876
|
init_identity();
|
|
7877
|
+
init_plan();
|
|
7878
|
+
init_AdvertisingIdManager();
|
|
7481
7879
|
init_DeepLinkAttributionCapture();
|
|
7482
7880
|
init_InstallTracker();
|
|
7483
|
-
|
|
7484
|
-
init_queue();
|
|
7485
|
-
init_session();
|
|
7881
|
+
init_MetaBridge();
|
|
7486
7882
|
init_onboarding();
|
|
7487
|
-
init_NativeStorage();
|
|
7488
|
-
init_NativeDeviceInfo();
|
|
7489
7883
|
init_paywallHeartbeatRecovery();
|
|
7884
|
+
init_session();
|
|
7885
|
+
init_SubscriptionManager();
|
|
7886
|
+
init_NativeDeviceInfo();
|
|
7887
|
+
init_ApiClient();
|
|
7888
|
+
init_constants();
|
|
7490
7889
|
init_eventPipelineBridge();
|
|
7491
|
-
|
|
7890
|
+
init_network();
|
|
7492
7891
|
init_PaywalloInitHelpers();
|
|
7493
|
-
|
|
7892
|
+
init_PaywalloState();
|
|
7893
|
+
init_queue();
|
|
7894
|
+
init_NativeStorage();
|
|
7494
7895
|
}
|
|
7495
7896
|
});
|
|
7496
7897
|
|
|
@@ -7744,6 +8145,7 @@ var init_PaywalloClient = __esm({
|
|
|
7744
8145
|
init_PaywalloAnalytics();
|
|
7745
8146
|
init_PaywalloSubscription();
|
|
7746
8147
|
init_PaywalloFlags();
|
|
8148
|
+
init_plan();
|
|
7747
8149
|
PaywalloClientClass = class {
|
|
7748
8150
|
constructor() {
|
|
7749
8151
|
this.state = createPaywalloState();
|
|
@@ -7995,6 +8397,14 @@ var init_PaywalloClient = __esm({
|
|
|
7995
8397
|
async processOfflineQueue() {
|
|
7996
8398
|
return queueProcessor.processQueue();
|
|
7997
8399
|
}
|
|
8400
|
+
async getPlans() {
|
|
8401
|
+
this.ensureInitialized();
|
|
8402
|
+
return planService.getAllPlans();
|
|
8403
|
+
}
|
|
8404
|
+
async getCurrentPlan() {
|
|
8405
|
+
this.ensureInitialized();
|
|
8406
|
+
return planService.getCurrentPlan();
|
|
8407
|
+
}
|
|
7998
8408
|
getApiClientOrThrow() {
|
|
7999
8409
|
if (!this.state.config || !this.state.apiClient) throw new ClientError(CLIENT_ERROR_CODES.NOT_INITIALIZED, "SDK not initialized. Call Paywallo.init() first");
|
|
8000
8410
|
return this.state.apiClient;
|
|
@@ -8077,8 +8487,124 @@ function usePaywallo() {
|
|
|
8077
8487
|
return context;
|
|
8078
8488
|
}
|
|
8079
8489
|
|
|
8080
|
-
// src/hooks/
|
|
8490
|
+
// src/hooks/usePlans.ts
|
|
8081
8491
|
import { useCallback as useCallback8, useEffect as useEffect7, useState as useState6 } from "react";
|
|
8492
|
+
async function getPlanService() {
|
|
8493
|
+
try {
|
|
8494
|
+
const mod = await Promise.resolve().then(() => (init_PlanService(), PlanService_exports));
|
|
8495
|
+
return mod.planService ?? null;
|
|
8496
|
+
} catch {
|
|
8497
|
+
return null;
|
|
8498
|
+
}
|
|
8499
|
+
}
|
|
8500
|
+
function usePlans() {
|
|
8501
|
+
const [allPlans, setAllPlans] = useState6([]);
|
|
8502
|
+
const [currentPlan, setCurrentPlan] = useState6(null);
|
|
8503
|
+
const [isLoading, setIsLoading] = useState6(true);
|
|
8504
|
+
const [error, setError] = useState6(null);
|
|
8505
|
+
const fetchPlans = useCallback8(async (forceRefresh = false) => {
|
|
8506
|
+
setIsLoading(true);
|
|
8507
|
+
setError(null);
|
|
8508
|
+
try {
|
|
8509
|
+
const service = await getPlanService();
|
|
8510
|
+
if (!service) {
|
|
8511
|
+
throw new PurchaseError(PURCHASE_ERROR_CODES.PURCHASE_FAILED, "PlanService not available");
|
|
8512
|
+
}
|
|
8513
|
+
const response = await service.getAllPlans(forceRefresh);
|
|
8514
|
+
const { plans, currentIdentifier } = response;
|
|
8515
|
+
setAllPlans(plans);
|
|
8516
|
+
setCurrentPlan(
|
|
8517
|
+
currentIdentifier != null ? plans.find((p) => p.identifier === currentIdentifier) ?? null : null
|
|
8518
|
+
);
|
|
8519
|
+
} catch (err) {
|
|
8520
|
+
const e = err instanceof PurchaseError ? err : new PurchaseError(PURCHASE_ERROR_CODES.PURCHASE_FAILED, String(err));
|
|
8521
|
+
setError(e);
|
|
8522
|
+
} finally {
|
|
8523
|
+
setIsLoading(false);
|
|
8524
|
+
}
|
|
8525
|
+
}, []);
|
|
8526
|
+
const refresh = useCallback8(() => {
|
|
8527
|
+
return fetchPlans(true);
|
|
8528
|
+
}, [fetchPlans]);
|
|
8529
|
+
useEffect7(() => {
|
|
8530
|
+
void fetchPlans(false);
|
|
8531
|
+
}, [fetchPlans]);
|
|
8532
|
+
return { currentPlan, allPlans, isLoading, error, refresh };
|
|
8533
|
+
}
|
|
8534
|
+
|
|
8535
|
+
// src/hooks/usePlanPurchase.ts
|
|
8536
|
+
import { useCallback as useCallback9, useState as useState7 } from "react";
|
|
8537
|
+
async function invalidatePlanCache() {
|
|
8538
|
+
try {
|
|
8539
|
+
const mod = await Promise.resolve().then(() => (init_PlanService(), PlanService_exports));
|
|
8540
|
+
mod.planService?.invalidateCache();
|
|
8541
|
+
} catch {
|
|
8542
|
+
}
|
|
8543
|
+
}
|
|
8544
|
+
function usePlanPurchase() {
|
|
8545
|
+
const [state, setState] = useState7("idle");
|
|
8546
|
+
const [error, setError] = useState7(null);
|
|
8547
|
+
const purchase = useCallback9(async (productId) => {
|
|
8548
|
+
setState("purchasing");
|
|
8549
|
+
setError(null);
|
|
8550
|
+
try {
|
|
8551
|
+
const iapService = getIAPService();
|
|
8552
|
+
const result = await iapService.purchase(productId);
|
|
8553
|
+
setState("idle");
|
|
8554
|
+
if (result.success) {
|
|
8555
|
+
await invalidatePlanCache();
|
|
8556
|
+
}
|
|
8557
|
+
return result.success ? {
|
|
8558
|
+
success: true,
|
|
8559
|
+
purchase: result.purchase ? {
|
|
8560
|
+
productId: result.purchase.productId,
|
|
8561
|
+
transactionId: result.purchase.transactionId ?? "",
|
|
8562
|
+
transactionDate: result.purchase.transactionDate,
|
|
8563
|
+
receipt: result.purchase.receipt,
|
|
8564
|
+
platform: "ios"
|
|
8565
|
+
} : void 0
|
|
8566
|
+
} : { success: false, error: result.error };
|
|
8567
|
+
} catch (err) {
|
|
8568
|
+
const purchaseError = err instanceof PurchaseError ? err : createPurchaseError("PURCHASE_FAILED", err instanceof Error ? err.message : String(err));
|
|
8569
|
+
if (purchaseError.userCancelled) {
|
|
8570
|
+
setState("idle");
|
|
8571
|
+
return null;
|
|
8572
|
+
}
|
|
8573
|
+
setError(purchaseError);
|
|
8574
|
+
setState("error");
|
|
8575
|
+
return { success: false, error: purchaseError };
|
|
8576
|
+
}
|
|
8577
|
+
}, []);
|
|
8578
|
+
const restore = useCallback9(async () => {
|
|
8579
|
+
setState("restoring");
|
|
8580
|
+
setError(null);
|
|
8581
|
+
try {
|
|
8582
|
+
const iapService = getIAPService();
|
|
8583
|
+
const transactions = await iapService.restore();
|
|
8584
|
+
setState("idle");
|
|
8585
|
+
await invalidatePlanCache();
|
|
8586
|
+
return {
|
|
8587
|
+
restoredCount: transactions.length,
|
|
8588
|
+
productIds: transactions.map((tx) => tx.productId)
|
|
8589
|
+
};
|
|
8590
|
+
} catch (err) {
|
|
8591
|
+
const e = err instanceof PurchaseError ? err : createPurchaseError("RESTORE_FAILED", String(err));
|
|
8592
|
+
setError(e);
|
|
8593
|
+
setState("error");
|
|
8594
|
+
return null;
|
|
8595
|
+
}
|
|
8596
|
+
}, []);
|
|
8597
|
+
return {
|
|
8598
|
+
purchase,
|
|
8599
|
+
restore,
|
|
8600
|
+
isPurchasing: state === "purchasing",
|
|
8601
|
+
isRestoring: state === "restoring",
|
|
8602
|
+
error
|
|
8603
|
+
};
|
|
8604
|
+
}
|
|
8605
|
+
|
|
8606
|
+
// src/hooks/useProducts.ts
|
|
8607
|
+
import { useCallback as useCallback10, useEffect as useEffect8, useState as useState8 } from "react";
|
|
8082
8608
|
|
|
8083
8609
|
// src/utils/productMappers.ts
|
|
8084
8610
|
function mapToIAPProduct(product) {
|
|
@@ -8117,11 +8643,11 @@ function mapToFormattedProduct(product) {
|
|
|
8117
8643
|
|
|
8118
8644
|
// src/hooks/useProducts.ts
|
|
8119
8645
|
function useProducts(initialProductIds) {
|
|
8120
|
-
const [products, setProducts] =
|
|
8121
|
-
const [formattedProducts, setFormattedProducts] =
|
|
8122
|
-
const [isLoading, setIsLoading] =
|
|
8123
|
-
const [error, setError] =
|
|
8124
|
-
const loadProducts =
|
|
8646
|
+
const [products, setProducts] = useState8([]);
|
|
8647
|
+
const [formattedProducts, setFormattedProducts] = useState8([]);
|
|
8648
|
+
const [isLoading, setIsLoading] = useState8(false);
|
|
8649
|
+
const [error, setError] = useState8(null);
|
|
8650
|
+
const loadProducts = useCallback10(async (productIds) => {
|
|
8125
8651
|
setIsLoading(true);
|
|
8126
8652
|
setError(null);
|
|
8127
8653
|
try {
|
|
@@ -8135,24 +8661,24 @@ function useProducts(initialProductIds) {
|
|
|
8135
8661
|
setIsLoading(false);
|
|
8136
8662
|
}
|
|
8137
8663
|
}, []);
|
|
8138
|
-
|
|
8664
|
+
useEffect8(() => {
|
|
8139
8665
|
if (initialProductIds && initialProductIds.length > 0) {
|
|
8140
8666
|
void loadProducts(initialProductIds);
|
|
8141
8667
|
}
|
|
8142
8668
|
}, []);
|
|
8143
|
-
const getProduct =
|
|
8669
|
+
const getProduct = useCallback10(
|
|
8144
8670
|
(productId) => {
|
|
8145
8671
|
return products.find((p) => p.productId === productId);
|
|
8146
8672
|
},
|
|
8147
8673
|
[products]
|
|
8148
8674
|
);
|
|
8149
|
-
const getFormattedProduct =
|
|
8675
|
+
const getFormattedProduct = useCallback10(
|
|
8150
8676
|
(productId) => {
|
|
8151
8677
|
return formattedProducts.find((p) => p.productId === productId);
|
|
8152
8678
|
},
|
|
8153
8679
|
[formattedProducts]
|
|
8154
8680
|
);
|
|
8155
|
-
const getPriceInfo =
|
|
8681
|
+
const getPriceInfo = useCallback10(
|
|
8156
8682
|
(productId) => {
|
|
8157
8683
|
const p = formattedProducts.find((fp) => fp.productId === productId);
|
|
8158
8684
|
if (!p) return void 0;
|
|
@@ -8181,11 +8707,11 @@ function useProducts(initialProductIds) {
|
|
|
8181
8707
|
}
|
|
8182
8708
|
|
|
8183
8709
|
// src/hooks/usePurchase.ts
|
|
8184
|
-
import { useCallback as
|
|
8710
|
+
import { useCallback as useCallback11, useState as useState9 } from "react";
|
|
8185
8711
|
function usePurchase() {
|
|
8186
|
-
const [state, setState] =
|
|
8187
|
-
const [error, setError] =
|
|
8188
|
-
const purchase =
|
|
8712
|
+
const [state, setState] = useState9("idle");
|
|
8713
|
+
const [error, setError] = useState9(null);
|
|
8714
|
+
const purchase = useCallback11(async (productId) => {
|
|
8189
8715
|
setState("purchasing");
|
|
8190
8716
|
setError(null);
|
|
8191
8717
|
try {
|
|
@@ -8221,7 +8747,7 @@ function usePurchase() {
|
|
|
8221
8747
|
return { status: "failed", error: purchaseError };
|
|
8222
8748
|
}
|
|
8223
8749
|
}, []);
|
|
8224
|
-
const restore =
|
|
8750
|
+
const restore = useCallback11(async () => {
|
|
8225
8751
|
setState("restoring");
|
|
8226
8752
|
setError(null);
|
|
8227
8753
|
try {
|
|
@@ -8252,14 +8778,14 @@ function usePurchase() {
|
|
|
8252
8778
|
}
|
|
8253
8779
|
|
|
8254
8780
|
// src/hooks/useSubscription.ts
|
|
8255
|
-
import { useCallback as
|
|
8781
|
+
import { useCallback as useCallback12, useEffect as useEffect9, useState as useState10 } from "react";
|
|
8256
8782
|
init_SubscriptionManager();
|
|
8257
8783
|
var EMPTY_ENTITLEMENTS = [];
|
|
8258
8784
|
function useSubscription() {
|
|
8259
|
-
const [status, setStatus] =
|
|
8260
|
-
const [isLoading, setIsLoading] =
|
|
8261
|
-
const [error, setError] =
|
|
8262
|
-
const refresh =
|
|
8785
|
+
const [status, setStatus] = useState10(null);
|
|
8786
|
+
const [isLoading, setIsLoading] = useState10(true);
|
|
8787
|
+
const [error, setError] = useState10(null);
|
|
8788
|
+
const refresh = useCallback12(async () => {
|
|
8263
8789
|
setIsLoading(true);
|
|
8264
8790
|
setError(null);
|
|
8265
8791
|
try {
|
|
@@ -8272,7 +8798,7 @@ function useSubscription() {
|
|
|
8272
8798
|
setIsLoading(false);
|
|
8273
8799
|
}
|
|
8274
8800
|
}, []);
|
|
8275
|
-
const restore =
|
|
8801
|
+
const restore = useCallback12(async () => {
|
|
8276
8802
|
setIsLoading(true);
|
|
8277
8803
|
setError(null);
|
|
8278
8804
|
try {
|
|
@@ -8285,7 +8811,7 @@ function useSubscription() {
|
|
|
8285
8811
|
setIsLoading(false);
|
|
8286
8812
|
}
|
|
8287
8813
|
}, []);
|
|
8288
|
-
|
|
8814
|
+
useEffect9(() => {
|
|
8289
8815
|
void subscriptionManager.getSubscriptionStatus().then((s) => {
|
|
8290
8816
|
setStatus(s);
|
|
8291
8817
|
setIsLoading(false);
|
|
@@ -8312,16 +8838,19 @@ function useSubscription() {
|
|
|
8312
8838
|
};
|
|
8313
8839
|
}
|
|
8314
8840
|
|
|
8841
|
+
// src/index.ts
|
|
8842
|
+
init_plan();
|
|
8843
|
+
|
|
8315
8844
|
// src/PaywalloProvider.tsx
|
|
8316
8845
|
init_paywall();
|
|
8317
8846
|
init_paywall();
|
|
8318
8847
|
init_paywall();
|
|
8319
|
-
import { useCallback as
|
|
8848
|
+
import { useCallback as useCallback17, useEffect as useEffect11, useLayoutEffect, useMemo as useMemo2, useRef as useRef10, useState as useState14 } from "react";
|
|
8320
8849
|
import { Animated as Animated3, Dimensions as Dimensions4, Easing as Easing2, StyleSheet as StyleSheet3 } from "react-native";
|
|
8321
8850
|
init_PaywalloClient();
|
|
8322
8851
|
|
|
8323
8852
|
// src/hooks/useAppAutoEvents.ts
|
|
8324
|
-
import { useEffect as
|
|
8853
|
+
import { useEffect as useEffect10, useRef as useRef7 } from "react";
|
|
8325
8854
|
var FIRST_SEEN_KEY = "@panel:firstSeen";
|
|
8326
8855
|
var DEBOUNCE_MS = 1e3;
|
|
8327
8856
|
async function detectPlatform3() {
|
|
@@ -8352,7 +8881,7 @@ function useAppAutoEvents(config) {
|
|
|
8352
8881
|
debug
|
|
8353
8882
|
} = config;
|
|
8354
8883
|
const didRunRef = useRef7(false);
|
|
8355
|
-
|
|
8884
|
+
useEffect10(() => {
|
|
8356
8885
|
if (!isInitialized || didRunRef.current) return;
|
|
8357
8886
|
const timer = setTimeout(() => {
|
|
8358
8887
|
if (didRunRef.current) return;
|
|
@@ -8399,7 +8928,7 @@ function useAppAutoEvents(config) {
|
|
|
8399
8928
|
// src/hooks/useCampaignPreload.ts
|
|
8400
8929
|
init_PaywalloClient();
|
|
8401
8930
|
init_CampaignError();
|
|
8402
|
-
import { useCallback as
|
|
8931
|
+
import { useCallback as useCallback13, useRef as useRef8, useState as useState11 } from "react";
|
|
8403
8932
|
|
|
8404
8933
|
// src/utils/loadCampaignProducts.ts
|
|
8405
8934
|
init_IAPService();
|
|
@@ -8468,17 +8997,17 @@ function getCacheEntry(cache, placement) {
|
|
|
8468
8997
|
|
|
8469
8998
|
// src/hooks/useCampaignPreload.ts
|
|
8470
8999
|
function useCampaignPreload() {
|
|
8471
|
-
const [preloadedWebView, setPreloadedWebView] =
|
|
9000
|
+
const [preloadedWebView, setPreloadedWebView] = useState11(null);
|
|
8472
9001
|
const preloadedCampaignsRef = useRef8(/* @__PURE__ */ new Map());
|
|
8473
|
-
const isPreloadValid =
|
|
9002
|
+
const isPreloadValid = useCallback13(
|
|
8474
9003
|
(placement) => isCacheEntryValid(preloadedCampaignsRef.current.get(placement)),
|
|
8475
9004
|
[]
|
|
8476
9005
|
);
|
|
8477
|
-
const consumePreloadedCampaign =
|
|
9006
|
+
const consumePreloadedCampaign = useCallback13(
|
|
8478
9007
|
(placement) => getCacheEntry(preloadedCampaignsRef.current, placement),
|
|
8479
9008
|
[]
|
|
8480
9009
|
);
|
|
8481
|
-
const preloadCampaign =
|
|
9010
|
+
const preloadCampaign = useCallback13(
|
|
8482
9011
|
async (placement, context) => {
|
|
8483
9012
|
try {
|
|
8484
9013
|
const campaign = await PaywalloClient.getCampaign(placement, context);
|
|
@@ -8552,12 +9081,12 @@ init_SecureStorage();
|
|
|
8552
9081
|
init_paywall();
|
|
8553
9082
|
|
|
8554
9083
|
// src/hooks/useProductLoader.ts
|
|
8555
|
-
import { useCallback as
|
|
9084
|
+
import { useCallback as useCallback14, useState as useState12 } from "react";
|
|
8556
9085
|
init_PaywalloClient();
|
|
8557
9086
|
function useProductLoader() {
|
|
8558
|
-
const [products, setProducts] =
|
|
8559
|
-
const [isLoadingProducts, setIsLoadingProducts] =
|
|
8560
|
-
const refreshProducts =
|
|
9087
|
+
const [products, setProducts] = useState12(/* @__PURE__ */ new Map());
|
|
9088
|
+
const [isLoadingProducts, setIsLoadingProducts] = useState12(false);
|
|
9089
|
+
const refreshProducts = useCallback14(async (productIds) => {
|
|
8561
9090
|
setIsLoadingProducts(true);
|
|
8562
9091
|
try {
|
|
8563
9092
|
const iapService = getIAPService();
|
|
@@ -8575,12 +9104,12 @@ function useProductLoader() {
|
|
|
8575
9104
|
}
|
|
8576
9105
|
|
|
8577
9106
|
// src/hooks/usePurchaseOrchestrator.ts
|
|
8578
|
-
import { useCallback as
|
|
9107
|
+
import { useCallback as useCallback15 } from "react";
|
|
8579
9108
|
init_PaywalloClient();
|
|
8580
9109
|
init_paywall();
|
|
8581
9110
|
function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clearPreloadedWebView, setShowingPreloadedWebView, presentedAtRef, invalidateSubscriptionCache) {
|
|
8582
9111
|
const { trackDismissed, trackProductSelected, trackPurchased } = usePaywallTracking();
|
|
8583
|
-
const handlePreloadedPurchase =
|
|
9112
|
+
const handlePreloadedPurchase = useCallback15(
|
|
8584
9113
|
async (productId) => {
|
|
8585
9114
|
try {
|
|
8586
9115
|
if (preloadedWebView) {
|
|
@@ -8618,7 +9147,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
|
|
|
8618
9147
|
},
|
|
8619
9148
|
[preloadedWebView, resolvePreloadedPaywall, clearPreloadedWebView, setShowingPreloadedWebView, presentedAtRef, trackDismissed, trackProductSelected, trackPurchased, invalidateSubscriptionCache]
|
|
8620
9149
|
);
|
|
8621
|
-
const handlePreloadedRestore =
|
|
9150
|
+
const handlePreloadedRestore = useCallback15(async () => {
|
|
8622
9151
|
try {
|
|
8623
9152
|
const transactions = await getIAPService().restore();
|
|
8624
9153
|
if (transactions.length === 0) return;
|
|
@@ -8643,7 +9172,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
|
|
|
8643
9172
|
// src/hooks/useSubscriptionSync.ts
|
|
8644
9173
|
init_PaywalloClient();
|
|
8645
9174
|
init_SubscriptionCache();
|
|
8646
|
-
import { useCallback as
|
|
9175
|
+
import { useCallback as useCallback16, useRef as useRef9, useState as useState13 } from "react";
|
|
8647
9176
|
var CACHE_TTL_MS2 = 5 * 60 * 1e3;
|
|
8648
9177
|
var ACTIVE_STATUSES = ["active", "in_grace_period"];
|
|
8649
9178
|
var PUBLIC_TO_DOMAIN_STATUS = {
|
|
@@ -8708,14 +9237,14 @@ function isActiveCacheEntry(entry) {
|
|
|
8708
9237
|
return isSubscriptionStillActive(entry.data);
|
|
8709
9238
|
}
|
|
8710
9239
|
function useSubscriptionSync() {
|
|
8711
|
-
const [subscription, setSubscription] =
|
|
9240
|
+
const [subscription, setSubscription] = useState13(null);
|
|
8712
9241
|
const cacheRef = useRef9(null);
|
|
8713
|
-
const invalidateCache =
|
|
9242
|
+
const invalidateCache = useCallback16(() => {
|
|
8714
9243
|
cacheRef.current = null;
|
|
8715
9244
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8716
9245
|
if (distinctId) void subscriptionCache.invalidate(distinctId);
|
|
8717
9246
|
}, []);
|
|
8718
|
-
const fetchAndCache =
|
|
9247
|
+
const fetchAndCache = useCallback16(async () => {
|
|
8719
9248
|
const apiClient = PaywalloClient.getApiClient();
|
|
8720
9249
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8721
9250
|
if (!apiClient || !distinctId) return null;
|
|
@@ -8729,7 +9258,7 @@ function useSubscriptionSync() {
|
|
|
8729
9258
|
void subscriptionCache.set(distinctId, toDomainResponse(status));
|
|
8730
9259
|
return sub;
|
|
8731
9260
|
}, []);
|
|
8732
|
-
const hasActiveSubscription =
|
|
9261
|
+
const hasActiveSubscription = useCallback16(async () => {
|
|
8733
9262
|
const apiClient = PaywalloClient.getApiClient();
|
|
8734
9263
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8735
9264
|
if (!apiClient || !distinctId) return false;
|
|
@@ -8772,7 +9301,7 @@ function useSubscriptionSync() {
|
|
|
8772
9301
|
return resolveOfflineFromCache(distinctId);
|
|
8773
9302
|
}
|
|
8774
9303
|
}, []);
|
|
8775
|
-
const getSubscription =
|
|
9304
|
+
const getSubscription = useCallback16(async () => {
|
|
8776
9305
|
const apiClient = PaywalloClient.getApiClient();
|
|
8777
9306
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8778
9307
|
if (!apiClient || !distinctId) return null;
|
|
@@ -8799,20 +9328,20 @@ init_ClientError();
|
|
|
8799
9328
|
init_localization();
|
|
8800
9329
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
8801
9330
|
function PaywalloProvider({ children, config }) {
|
|
8802
|
-
const [isInitialized, setIsInitialized] =
|
|
8803
|
-
const [initError, setInitError] =
|
|
8804
|
-
const [distinctId, setDistinctId] =
|
|
8805
|
-
const [activePaywall, setActivePaywall] =
|
|
9331
|
+
const [isInitialized, setIsInitialized] = useState14(false);
|
|
9332
|
+
const [initError, setInitError] = useState14(null);
|
|
9333
|
+
const [distinctId, setDistinctId] = useState14(null);
|
|
9334
|
+
const [activePaywall, setActivePaywall] = useState14(null);
|
|
8806
9335
|
const { products, isLoadingProducts, refreshProducts } = useProductLoader();
|
|
8807
9336
|
const { subscription, hasActiveSubscription, getSubscription, invalidateCache } = useSubscriptionSync();
|
|
8808
9337
|
const { preloadedWebView, setPreloadedWebView, preloadCampaign, consumePreloadedCampaign, isPreloadValid } = useCampaignPreload();
|
|
8809
|
-
const clearPreloadedWebView =
|
|
9338
|
+
const clearPreloadedWebView = useCallback17(() => setPreloadedWebView(null), [setPreloadedWebView]);
|
|
8810
9339
|
const autoPreloadTriggeredRef = useRef10(false);
|
|
8811
9340
|
const preloadedWebViewRef = useRef10(preloadedWebView);
|
|
8812
9341
|
const pollTimerRef = useRef10(null);
|
|
8813
9342
|
const pollCancelledRef = useRef10(false);
|
|
8814
9343
|
const secureStorageRef = useRef10(new SecureStorage(config.debug));
|
|
8815
|
-
|
|
9344
|
+
useEffect11(() => {
|
|
8816
9345
|
preloadedWebViewRef.current = preloadedWebView;
|
|
8817
9346
|
}, [preloadedWebView]);
|
|
8818
9347
|
useAppAutoEvents({
|
|
@@ -8828,20 +9357,20 @@ function PaywalloProvider({ children, config }) {
|
|
|
8828
9357
|
storageSet: (key, value) => secureStorageRef.current.set(key, value),
|
|
8829
9358
|
debug: config.debug
|
|
8830
9359
|
});
|
|
8831
|
-
const triggerRepreload =
|
|
9360
|
+
const triggerRepreload = useCallback17((placement) => {
|
|
8832
9361
|
void PaywalloClient.preloadCampaign(placement).catch(() => {
|
|
8833
9362
|
});
|
|
8834
9363
|
}, []);
|
|
8835
9364
|
const { showingPreloadedWebView, presentPreloadedWebView, resolvePreloadedPaywall, handlePreloadedWebViewReady: baseHandlePreloadedWebViewReady, handlePreloadedClose: baseHandlePreloadedClose, setShowingPreloadedWebView, presentedAtRef } = usePaywallPresenter(preloadedWebView, setPreloadedWebView);
|
|
8836
9365
|
const SCREEN_HEIGHT = useMemo2(() => Dimensions4.get("window").height, []);
|
|
8837
9366
|
const slideAnim = useRef10(new Animated3.Value(SCREEN_HEIGHT)).current;
|
|
8838
|
-
const handlePreloadedWebViewReady =
|
|
9367
|
+
const handlePreloadedWebViewReady = useCallback17(() => {
|
|
8839
9368
|
if (PaywalloClient.getConfig()?.debug) {
|
|
8840
9369
|
console.log(`[Paywallo WEBVIEW] loaded \u2014 placement: ${preloadedWebView?.placement}`);
|
|
8841
9370
|
}
|
|
8842
9371
|
baseHandlePreloadedWebViewReady();
|
|
8843
9372
|
}, [preloadedWebView?.placement, baseHandlePreloadedWebViewReady]);
|
|
8844
|
-
const handlePreloadedClose =
|
|
9373
|
+
const handlePreloadedClose = useCallback17(() => {
|
|
8845
9374
|
const placement = preloadedWebView?.placement;
|
|
8846
9375
|
Animated3.timing(slideAnim, { toValue: SCREEN_HEIGHT, duration: 200, easing: Easing2.in(Easing2.cubic), useNativeDriver: true }).start(() => {
|
|
8847
9376
|
baseHandlePreloadedClose();
|
|
@@ -8856,8 +9385,8 @@ function PaywalloProvider({ children, config }) {
|
|
|
8856
9385
|
presentedAtRef,
|
|
8857
9386
|
invalidateCache
|
|
8858
9387
|
);
|
|
8859
|
-
const [isPreloadPurchasing, setIsPreloadPurchasing] =
|
|
8860
|
-
const handlePreloadedPurchase =
|
|
9388
|
+
const [isPreloadPurchasing, setIsPreloadPurchasing] = useState14(false);
|
|
9389
|
+
const handlePreloadedPurchase = useCallback17(async (productId) => {
|
|
8861
9390
|
setIsPreloadPurchasing(true);
|
|
8862
9391
|
try {
|
|
8863
9392
|
await rawPreloadedPurchase(productId);
|
|
@@ -8866,7 +9395,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
8866
9395
|
}
|
|
8867
9396
|
}, [rawPreloadedPurchase]);
|
|
8868
9397
|
const configRef = useRef10(config);
|
|
8869
|
-
|
|
9398
|
+
useEffect11(() => {
|
|
8870
9399
|
let mounted = true;
|
|
8871
9400
|
initLocalization({ detectDevice: true });
|
|
8872
9401
|
PaywalloClient.init(configRef.current).then(async () => {
|
|
@@ -8887,14 +9416,14 @@ function PaywalloProvider({ children, config }) {
|
|
|
8887
9416
|
mounted = false;
|
|
8888
9417
|
};
|
|
8889
9418
|
}, [preloadCampaign]);
|
|
8890
|
-
const getPaywallConfig =
|
|
9419
|
+
const getPaywallConfig = useCallback17(async (p) => {
|
|
8891
9420
|
const api = PaywalloClient.getApiClient();
|
|
8892
9421
|
return api ? api.getPaywall(p) : null;
|
|
8893
9422
|
}, []);
|
|
8894
|
-
const presentPaywall =
|
|
9423
|
+
const presentPaywall = useCallback17((placement) => {
|
|
8895
9424
|
return new Promise((resolve) => setActivePaywall({ placement, resolver: resolve }));
|
|
8896
9425
|
}, []);
|
|
8897
|
-
const trackCampaignImpression =
|
|
9426
|
+
const trackCampaignImpression = useCallback17((placement, variantKey, campaignId) => {
|
|
8898
9427
|
const api = PaywalloClient.getApiClient();
|
|
8899
9428
|
if (!api) return;
|
|
8900
9429
|
const sessionId = PaywalloClient.getSessionId();
|
|
@@ -8908,7 +9437,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
8908
9437
|
}).catch(() => {
|
|
8909
9438
|
});
|
|
8910
9439
|
}, []);
|
|
8911
|
-
const presentCampaign =
|
|
9440
|
+
const presentCampaign = useCallback17(
|
|
8912
9441
|
async (placement, context) => {
|
|
8913
9442
|
try {
|
|
8914
9443
|
if (preloadedWebView?.placement === placement && preloadedWebView.loaded && isPreloadValid(placement)) {
|
|
@@ -8982,7 +9511,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
8982
9511
|
},
|
|
8983
9512
|
[preloadedWebView, isPreloadValid, consumePreloadedCampaign, presentPreloadedWebView, trackCampaignImpression]
|
|
8984
9513
|
);
|
|
8985
|
-
const restorePurchases =
|
|
9514
|
+
const restorePurchases = useCallback17(async () => {
|
|
8986
9515
|
invalidateCache();
|
|
8987
9516
|
try {
|
|
8988
9517
|
const txs = await getIAPService().restore();
|
|
@@ -8991,13 +9520,13 @@ function PaywalloProvider({ children, config }) {
|
|
|
8991
9520
|
return { success: false, restoredProducts: [], error: error instanceof Error ? error : new PurchaseError(PURCHASE_ERROR_CODES.RESTORE_FAILED, String(error)) };
|
|
8992
9521
|
}
|
|
8993
9522
|
}, [invalidateCache]);
|
|
8994
|
-
const handlePaywallResult =
|
|
9523
|
+
const handlePaywallResult = useCallback17((result) => {
|
|
8995
9524
|
if (activePaywall) {
|
|
8996
9525
|
activePaywall.resolver(result);
|
|
8997
9526
|
setActivePaywall(null);
|
|
8998
9527
|
}
|
|
8999
9528
|
}, [activePaywall]);
|
|
9000
|
-
const bridgePaywallPresenter =
|
|
9529
|
+
const bridgePaywallPresenter = useCallback17((placement) => {
|
|
9001
9530
|
if (PaywalloClient.getConfig()?.debug) {
|
|
9002
9531
|
console.log(`[Paywallo PRESENT] called \u2014 preloaded: ${preloadedWebViewRef.current?.loaded === true} placement: ${placement}`);
|
|
9003
9532
|
}
|
|
@@ -9026,7 +9555,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
9026
9555
|
}
|
|
9027
9556
|
return presentCampaign(placement);
|
|
9028
9557
|
}, [presentPreloadedWebView, presentCampaign]);
|
|
9029
|
-
|
|
9558
|
+
useEffect11(() => {
|
|
9030
9559
|
if (!isInitialized) return;
|
|
9031
9560
|
const onEmergency = async (id) => {
|
|
9032
9561
|
try {
|
|
@@ -9053,7 +9582,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
9053
9582
|
};
|
|
9054
9583
|
}, [isInitialized, bridgePaywallPresenter, getSubscription, hasActiveSubscription, restorePurchases]);
|
|
9055
9584
|
const isReady = isInitialized && !isLoadingProducts;
|
|
9056
|
-
const noOp =
|
|
9585
|
+
const noOp = useCallback17(() => {
|
|
9057
9586
|
}, []);
|
|
9058
9587
|
const contextValue = useMemo2(() => ({
|
|
9059
9588
|
config: PaywalloClient.getConfig(),
|
|
@@ -9295,6 +9824,8 @@ export {
|
|
|
9295
9824
|
PaywalloContext,
|
|
9296
9825
|
PaywalloError,
|
|
9297
9826
|
PaywalloProvider,
|
|
9827
|
+
PlanCache,
|
|
9828
|
+
PlanService,
|
|
9298
9829
|
PurchaseError,
|
|
9299
9830
|
SESSION_ERROR_CODES,
|
|
9300
9831
|
SessionError,
|
|
@@ -9317,6 +9848,8 @@ export {
|
|
|
9317
9848
|
offlineQueue,
|
|
9318
9849
|
onboardingManager,
|
|
9319
9850
|
parseVariables,
|
|
9851
|
+
planCache,
|
|
9852
|
+
planService,
|
|
9320
9853
|
queueProcessor,
|
|
9321
9854
|
resolveText,
|
|
9322
9855
|
sessionManager,
|
|
@@ -9326,6 +9859,8 @@ export {
|
|
|
9326
9859
|
useOnboarding,
|
|
9327
9860
|
usePaywallContext,
|
|
9328
9861
|
usePaywallo,
|
|
9862
|
+
usePlanPurchase,
|
|
9863
|
+
usePlans,
|
|
9329
9864
|
useProducts,
|
|
9330
9865
|
usePurchase,
|
|
9331
9866
|
useSubscription
|