@virex-tech/paywallo-sdk 2.0.2 → 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 +122 -7
- package/dist/index.d.ts +122 -7
- package/dist/index.js +1170 -617
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1144 -597
- 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":
|
|
@@ -4887,6 +5057,16 @@ var init_PermissionManager = __esm({
|
|
|
4887
5057
|
}
|
|
4888
5058
|
});
|
|
4889
5059
|
|
|
5060
|
+
// src/core/constants.ts
|
|
5061
|
+
var DEFAULT_API_URL, DEFAULT_WEB_URL;
|
|
5062
|
+
var init_constants = __esm({
|
|
5063
|
+
"src/core/constants.ts"() {
|
|
5064
|
+
"use strict";
|
|
5065
|
+
DEFAULT_API_URL = "https://panel.lucasqueiroga.shop";
|
|
5066
|
+
DEFAULT_WEB_URL = "https://paywallo.com.br";
|
|
5067
|
+
}
|
|
5068
|
+
});
|
|
5069
|
+
|
|
4890
5070
|
// src/domains/notifications/config.ts
|
|
4891
5071
|
function resolveApiBaseUrl(config) {
|
|
4892
5072
|
if (config.apiBaseUrl) return config.apiBaseUrl;
|
|
@@ -4897,8 +5077,9 @@ var DEFAULT_API_BASE_URL, SANDBOX_API_BASE_URL;
|
|
|
4897
5077
|
var init_config = __esm({
|
|
4898
5078
|
"src/domains/notifications/config.ts"() {
|
|
4899
5079
|
"use strict";
|
|
4900
|
-
|
|
4901
|
-
|
|
5080
|
+
init_constants();
|
|
5081
|
+
DEFAULT_API_BASE_URL = DEFAULT_API_URL;
|
|
5082
|
+
SANDBOX_API_BASE_URL = DEFAULT_API_URL;
|
|
4902
5083
|
}
|
|
4903
5084
|
});
|
|
4904
5085
|
|
|
@@ -4993,6 +5174,9 @@ function mapPermissionStatus2(status) {
|
|
|
4993
5174
|
function detectPlatform2() {
|
|
4994
5175
|
return Platform11.OS === "ios" ? "ios" : "android";
|
|
4995
5176
|
}
|
|
5177
|
+
function detectEnvironment() {
|
|
5178
|
+
return typeof __DEV__ !== "undefined" && __DEV__ ? "sandbox" : "production";
|
|
5179
|
+
}
|
|
4996
5180
|
async function getAppVersion() {
|
|
4997
5181
|
try {
|
|
4998
5182
|
const { collectDeviceInfo: collectDeviceInfo2 } = await Promise.resolve().then(() => (init_deviceInfo(), deviceInfo_exports));
|
|
@@ -5020,8 +5204,8 @@ var init_utils = __esm({
|
|
|
5020
5204
|
// src/core/version.ts
|
|
5021
5205
|
function resolveVersion() {
|
|
5022
5206
|
try {
|
|
5023
|
-
if ("2.
|
|
5024
|
-
return "2.
|
|
5207
|
+
if ("2.2.1") {
|
|
5208
|
+
return "2.2.1";
|
|
5025
5209
|
}
|
|
5026
5210
|
} catch {
|
|
5027
5211
|
}
|
|
@@ -5060,7 +5244,8 @@ async function buildRegistration(token, getDeviceId, getDistinctId) {
|
|
|
5060
5244
|
sdk_version: SDK_VERSION,
|
|
5061
5245
|
deviceId: getDeviceId?.() ?? void 0,
|
|
5062
5246
|
locale: getLocale(),
|
|
5063
|
-
timezone: getTimezone2()
|
|
5247
|
+
timezone: getTimezone2(),
|
|
5248
|
+
environment: detectEnvironment()
|
|
5064
5249
|
};
|
|
5065
5250
|
}
|
|
5066
5251
|
async function registerToken(deps, token) {
|
|
@@ -5102,7 +5287,7 @@ var init_TokenRegistration = __esm({
|
|
|
5102
5287
|
init_utils();
|
|
5103
5288
|
init_version();
|
|
5104
5289
|
FCM_TOKEN_KEY = "@panel:push_token";
|
|
5105
|
-
TOKEN_ENDPOINT = "/push-tokens";
|
|
5290
|
+
TOKEN_ENDPOINT = "/sdk/push-tokens";
|
|
5106
5291
|
}
|
|
5107
5292
|
});
|
|
5108
5293
|
|
|
@@ -5394,58 +5579,400 @@ var init_NotificationsManager = __esm({
|
|
|
5394
5579
|
this.currentToken = null;
|
|
5395
5580
|
}
|
|
5396
5581
|
};
|
|
5397
|
-
notificationsManager = new NotificationsManager();
|
|
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
|
+
}
|
|
5926
|
+
}
|
|
5927
|
+
};
|
|
5928
|
+
onboardingManager = new OnboardingManager();
|
|
5398
5929
|
}
|
|
5399
5930
|
});
|
|
5400
5931
|
|
|
5401
|
-
// src/domains/
|
|
5402
|
-
var
|
|
5403
|
-
"src/domains/
|
|
5932
|
+
// src/domains/onboarding/index.ts
|
|
5933
|
+
var init_onboarding = __esm({
|
|
5934
|
+
"src/domains/onboarding/index.ts"() {
|
|
5404
5935
|
"use strict";
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
init_NotificationsError();
|
|
5936
|
+
init_OnboardingManager();
|
|
5937
|
+
init_OnboardingError();
|
|
5408
5938
|
}
|
|
5409
5939
|
});
|
|
5410
5940
|
|
|
5411
|
-
// src/domains/
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
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();
|
|
5417
5970
|
}
|
|
5418
|
-
});
|
|
5419
|
-
|
|
5420
|
-
// src/core/PaywalloState.ts
|
|
5421
|
-
function createPaywalloState() {
|
|
5422
|
-
return {
|
|
5423
|
-
config: null,
|
|
5424
|
-
apiClient: null,
|
|
5425
|
-
initPromise: null,
|
|
5426
|
-
readyPromise: null,
|
|
5427
|
-
resolveReady: null,
|
|
5428
|
-
paywallPresenter: null,
|
|
5429
|
-
campaignPresenter: null,
|
|
5430
|
-
subscriptionGetter: null,
|
|
5431
|
-
activeChecker: null,
|
|
5432
|
-
restoreHandler: null,
|
|
5433
|
-
lastOnboardingStepTimestamp: null,
|
|
5434
|
-
pendingConfig: null,
|
|
5435
|
-
networkCleanup: null,
|
|
5436
|
-
initAttempts: 0,
|
|
5437
|
-
autoPreloadedPlacement: null,
|
|
5438
|
-
autoPreloadPlacementPromise: null,
|
|
5439
|
-
sessionFlagsMap: /* @__PURE__ */ new Map(),
|
|
5440
|
-
pendingIdentifies: []
|
|
5441
|
-
};
|
|
5442
5971
|
}
|
|
5443
|
-
var
|
|
5444
|
-
|
|
5445
|
-
"src/core/PaywalloState.ts"() {
|
|
5972
|
+
var init_paywallHeartbeatRecovery = __esm({
|
|
5973
|
+
"src/domains/paywall/paywallHeartbeatRecovery.ts"() {
|
|
5446
5974
|
"use strict";
|
|
5447
|
-
|
|
5448
|
-
RETRY_DELAYS = [2e3, 5e3, 1e4];
|
|
5975
|
+
init_paywallHeartbeat();
|
|
5449
5976
|
}
|
|
5450
5977
|
});
|
|
5451
5978
|
|
|
@@ -5453,7 +5980,7 @@ var init_PaywalloState = __esm({
|
|
|
5453
5980
|
function keyFor(distinctId) {
|
|
5454
5981
|
return `${CACHE_KEY_PREFIX}${distinctId}`;
|
|
5455
5982
|
}
|
|
5456
|
-
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;
|
|
5457
5984
|
var init_SubscriptionCache = __esm({
|
|
5458
5985
|
"src/domains/subscription/SubscriptionCache.ts"() {
|
|
5459
5986
|
"use strict";
|
|
@@ -5461,9 +5988,9 @@ var init_SubscriptionCache = __esm({
|
|
|
5461
5988
|
LEGACY_CACHE_KEY = "@panel:subscription_cache";
|
|
5462
5989
|
CACHE_KEY_PREFIX = "subscription_cache:";
|
|
5463
5990
|
CACHE_INDEX_KEY = "subscription_cache:__index__";
|
|
5464
|
-
|
|
5991
|
+
DEFAULT_TTL2 = 24 * 60 * 60 * 1e3;
|
|
5465
5992
|
SubscriptionCache = class {
|
|
5466
|
-
constructor(ttl =
|
|
5993
|
+
constructor(ttl = DEFAULT_TTL2) {
|
|
5467
5994
|
this.memoryCache = /* @__PURE__ */ new Map();
|
|
5468
5995
|
this.legacyCleanupDone = false;
|
|
5469
5996
|
this.ttl = ttl;
|
|
@@ -5670,7 +6197,7 @@ var init_SubscriptionManager = __esm({
|
|
|
5670
6197
|
if (!this.config) {
|
|
5671
6198
|
return this.getEmptyStatus();
|
|
5672
6199
|
}
|
|
5673
|
-
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}`);
|
|
5674
6201
|
if (this.userId) {
|
|
5675
6202
|
url.searchParams.set("distinctId", this.userId);
|
|
5676
6203
|
}
|
|
@@ -5754,11 +6281,10 @@ function buildConditionalFlagUrl(baseUrl, flagKey, context) {
|
|
|
5754
6281
|
if (context.distinctId) url.searchParams.set("distinctId", context.distinctId);
|
|
5755
6282
|
return url.toString();
|
|
5756
6283
|
}
|
|
5757
|
-
var DEFAULT_WEB_URL;
|
|
5758
6284
|
var init_apiUrlUtils = __esm({
|
|
5759
6285
|
"src/core/apiUrlUtils.ts"() {
|
|
5760
6286
|
"use strict";
|
|
5761
|
-
|
|
6287
|
+
init_constants();
|
|
5762
6288
|
}
|
|
5763
6289
|
});
|
|
5764
6290
|
|
|
@@ -5911,7 +6437,7 @@ async function getSubscriptionStatus(client, baseUrl, appKey, distinctId) {
|
|
|
5911
6437
|
}
|
|
5912
6438
|
async function getEmergencyPaywall(client) {
|
|
5913
6439
|
try {
|
|
5914
|
-
const response = await client.get("/emergency-paywall");
|
|
6440
|
+
const response = await client.get("/sdk/emergency-paywall");
|
|
5915
6441
|
if (response.status === 404) return { enabled: false };
|
|
5916
6442
|
return response.data;
|
|
5917
6443
|
} catch {
|
|
@@ -6528,7 +7054,7 @@ var init_EventBatcher = __esm({
|
|
|
6528
7054
|
BATCH_MAX_SIZE = 25;
|
|
6529
7055
|
BATCH_FLUSH_MS = 1e4;
|
|
6530
7056
|
EVENT_NAME_REGEX = /^(\$[a-zA-Z0-9_]+|[a-z][a-z0-9_]*)$/;
|
|
6531
|
-
V2_BATCH_ENDPOINT = "/ingest/batch";
|
|
7057
|
+
V2_BATCH_ENDPOINT = "/sdk/ingest/batch";
|
|
6532
7058
|
V1_BATCH_ENDPOINT = "/sdk/events/batch";
|
|
6533
7059
|
V1_SINGLE_ENDPOINT = "/sdk/events";
|
|
6534
7060
|
EventBatcher = class {
|
|
@@ -6892,7 +7418,7 @@ var init_ApiClient = __esm({
|
|
|
6892
7418
|
dispose() {
|
|
6893
7419
|
this.batcher.dispose();
|
|
6894
7420
|
}
|
|
6895
|
-
async identify(distinctId, properties, email, deviceId) {
|
|
7421
|
+
async identify(distinctId, properties, email, deviceId, pii) {
|
|
6896
7422
|
await postWithQueue(
|
|
6897
7423
|
{
|
|
6898
7424
|
isOfflineQueueEnabled: () => this.offlineQueueEnabled,
|
|
@@ -6900,8 +7426,19 @@ var init_ApiClient = __esm({
|
|
|
6900
7426
|
isDebug: () => this.debug,
|
|
6901
7427
|
post: (path, body, skipRetry) => this.post(path, body, skipRetry)
|
|
6902
7428
|
},
|
|
6903
|
-
"/identify",
|
|
6904
|
-
{
|
|
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
|
+
},
|
|
6905
7442
|
"identify"
|
|
6906
7443
|
);
|
|
6907
7444
|
}
|
|
@@ -6929,245 +7466,84 @@ var init_ApiClient = __esm({
|
|
|
6929
7466
|
return res.data;
|
|
6930
7467
|
} catch {
|
|
6931
7468
|
const stale = this.cache.getStalePaywall(placement);
|
|
6932
|
-
return stale !== void 0 ? stale : null;
|
|
6933
|
-
}
|
|
6934
|
-
}
|
|
6935
|
-
async getEmergencyPaywall() {
|
|
6936
|
-
return getEmergencyPaywall(this);
|
|
6937
|
-
}
|
|
6938
|
-
async getCampaign(placement, distinctId, context) {
|
|
6939
|
-
const key = `${placement}:${distinctId}`;
|
|
6940
|
-
const hit = this.cache.getCampaign(key);
|
|
6941
|
-
if (hit !== void 0) return hit;
|
|
6942
|
-
try {
|
|
6943
|
-
const result = await getCampaignData(this, this.baseUrl, placement, distinctId, context);
|
|
6944
|
-
if (!result) {
|
|
6945
|
-
this.cache.setCampaign(key, null, this.cache.nullTTL);
|
|
6946
|
-
return null;
|
|
6947
|
-
}
|
|
6948
|
-
this.cache.setCampaign(key, result);
|
|
6949
|
-
return result;
|
|
6950
|
-
} catch {
|
|
6951
|
-
const stale = this.cache.getStaleCampaign(key);
|
|
6952
|
-
return stale !== void 0 ? stale : null;
|
|
6953
|
-
}
|
|
6954
|
-
}
|
|
6955
|
-
async getPrimaryCampaign(distinctId) {
|
|
6956
|
-
const key = `primary:${distinctId}`;
|
|
6957
|
-
const hit = this.cache.getCampaign(key);
|
|
6958
|
-
if (hit !== void 0) return hit;
|
|
6959
|
-
try {
|
|
6960
|
-
const res = await this.get(`/campaigns/public/primary?distinctId=${encodeURIComponent(distinctId)}`);
|
|
6961
|
-
if (res.status === 404) {
|
|
6962
|
-
this.cache.setCampaign(key, null, this.cache.nullTTL);
|
|
6963
|
-
return null;
|
|
6964
|
-
}
|
|
6965
|
-
if (!res.ok) {
|
|
6966
|
-
const stale = this.cache.getStaleCampaign(key);
|
|
6967
|
-
return stale !== void 0 ? stale : null;
|
|
6968
|
-
}
|
|
6969
|
-
this.cache.setCampaign(key, res.data);
|
|
6970
|
-
return res.data;
|
|
6971
|
-
} catch {
|
|
6972
|
-
const stale = this.cache.getStaleCampaign(key);
|
|
6973
|
-
return stale !== void 0 ? stale : null;
|
|
6974
|
-
}
|
|
6975
|
-
}
|
|
6976
|
-
async validatePurchase(platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey) {
|
|
6977
|
-
return validatePurchase(this, this.appKey, platform, receipt, productId, transactionId, priceLocal, currency, country, distinctId, paywallPlacement, variantKey);
|
|
6978
|
-
}
|
|
6979
|
-
async getSubscriptionStatus(distinctId) {
|
|
6980
|
-
return getSubscriptionStatus(this, this.baseUrl, this.appKey, distinctId);
|
|
6981
|
-
}
|
|
6982
|
-
async evaluateFlags(keys, distinctId) {
|
|
6983
|
-
return evaluateFlags(this.flagDeps(), keys, distinctId);
|
|
6984
|
-
}
|
|
6985
|
-
async getConditionalFlag(flagKey, context) {
|
|
6986
|
-
return getConditionalFlag(this.flagDeps(), flagKey, context);
|
|
6987
|
-
}
|
|
6988
|
-
async getVariantFromCache(flagKey, distinctId) {
|
|
6989
|
-
return getVariantFromCache(this.flagDeps(), flagKey, distinctId);
|
|
6990
|
-
}
|
|
6991
|
-
flagDeps() {
|
|
6992
|
-
return {
|
|
6993
|
-
get: (path) => this.get(path),
|
|
6994
|
-
httpClient: this.httpClient,
|
|
6995
|
-
cache: this.cache,
|
|
6996
|
-
appKey: this.appKey,
|
|
6997
|
-
baseUrl: this.baseUrl
|
|
6998
|
-
};
|
|
6999
|
-
}
|
|
7000
|
-
};
|
|
7001
|
-
}
|
|
7002
|
-
});
|
|
7003
|
-
|
|
7004
|
-
// src/domains/onboarding/OnboardingError.ts
|
|
7005
|
-
var OnboardingError, ONBOARDING_ERROR_CODES;
|
|
7006
|
-
var init_OnboardingError = __esm({
|
|
7007
|
-
"src/domains/onboarding/OnboardingError.ts"() {
|
|
7008
|
-
"use strict";
|
|
7009
|
-
init_PaywalloError();
|
|
7010
|
-
OnboardingError = class extends PaywalloError {
|
|
7011
|
-
constructor(code, message) {
|
|
7012
|
-
super("onboarding", code, message);
|
|
7013
|
-
this.name = "OnboardingError";
|
|
7014
|
-
}
|
|
7015
|
-
};
|
|
7016
|
-
ONBOARDING_ERROR_CODES = {
|
|
7017
|
-
NOT_INITIALIZED: "ONBOARDING_NOT_INITIALIZED",
|
|
7018
|
-
INVALID_STEP_NAME: "ONBOARDING_INVALID_STEP_NAME"
|
|
7019
|
-
};
|
|
7020
|
-
}
|
|
7021
|
-
});
|
|
7022
|
-
|
|
7023
|
-
// src/domains/onboarding/OnboardingManager.ts
|
|
7024
|
-
var OnboardingManager, onboardingManager;
|
|
7025
|
-
var init_OnboardingManager = __esm({
|
|
7026
|
-
"src/domains/onboarding/OnboardingManager.ts"() {
|
|
7027
|
-
"use strict";
|
|
7028
|
-
init_OnboardingError();
|
|
7029
|
-
OnboardingManager = class {
|
|
7030
|
-
constructor() {
|
|
7031
|
-
this.pipeline = null;
|
|
7032
|
-
this.debug = false;
|
|
7033
|
-
this.lastStep = null;
|
|
7034
|
-
this.finished = false;
|
|
7035
|
-
}
|
|
7036
|
-
/**
|
|
7037
|
-
* Injects runtime dependencies. Called by PaywalloClient during init.
|
|
7038
|
-
*/
|
|
7039
|
-
injectDeps(config) {
|
|
7040
|
-
this.pipeline = config.pipeline;
|
|
7041
|
-
this.debug = config.debug ?? false;
|
|
7042
|
-
}
|
|
7043
|
-
/**
|
|
7044
|
-
* Tracks an onboarding step view.
|
|
7045
|
-
* Saves the step name internally for implicit drop detection on the backend.
|
|
7046
|
-
*
|
|
7047
|
-
* @param stepName - Unique name for this onboarding step.
|
|
7048
|
-
*/
|
|
7049
|
-
async step(stepName) {
|
|
7050
|
-
this.assertConfig();
|
|
7051
|
-
this.validateStepName(stepName, "step");
|
|
7052
|
-
this.lastStep = stepName;
|
|
7053
|
-
const payload = {
|
|
7054
|
-
family: "onboarding",
|
|
7055
|
-
type: "step",
|
|
7056
|
-
...{ step_name: stepName }
|
|
7057
|
-
};
|
|
7058
|
-
return this.emit("onboarding", payload, "step");
|
|
7059
|
-
}
|
|
7060
|
-
/**
|
|
7061
|
-
* Tracks successful completion of the onboarding flow.
|
|
7062
|
-
* Marks the flow as finished.
|
|
7063
|
-
*/
|
|
7064
|
-
async complete() {
|
|
7065
|
-
this.assertConfig();
|
|
7066
|
-
this.finished = true;
|
|
7067
|
-
return this.emit("onboarding", { family: "onboarding", type: "complete" }, "complete");
|
|
7068
|
-
}
|
|
7069
|
-
/**
|
|
7070
|
-
* Tracks an explicit drop (abandonment) at the given step.
|
|
7071
|
-
* Marks the flow as finished.
|
|
7072
|
-
*
|
|
7073
|
-
* @param stepName - The step name where the user dropped off.
|
|
7074
|
-
*/
|
|
7075
|
-
async drop(stepName) {
|
|
7076
|
-
this.assertConfig();
|
|
7077
|
-
this.validateStepName(stepName, "drop");
|
|
7078
|
-
this.finished = true;
|
|
7079
|
-
const payload = {
|
|
7080
|
-
family: "onboarding",
|
|
7081
|
-
type: "drop",
|
|
7082
|
-
...{ step_name: stepName }
|
|
7083
|
-
};
|
|
7084
|
-
return this.emit("onboarding", payload, "drop");
|
|
7085
|
-
}
|
|
7086
|
-
/** Returns the last step name seen, or null if no step was tracked yet. */
|
|
7087
|
-
getLastStep() {
|
|
7088
|
-
return this.lastStep;
|
|
7469
|
+
return stale !== void 0 ? stale : null;
|
|
7470
|
+
}
|
|
7089
7471
|
}
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
return this.finished;
|
|
7472
|
+
async getEmergencyPaywall() {
|
|
7473
|
+
return getEmergencyPaywall(this);
|
|
7093
7474
|
}
|
|
7094
|
-
async
|
|
7095
|
-
const
|
|
7096
|
-
const
|
|
7097
|
-
if (
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
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;
|
|
7104
7490
|
}
|
|
7105
7491
|
}
|
|
7106
|
-
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
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 [];
|
|
7112
7499
|
}
|
|
7113
7500
|
}
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
);
|
|
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;
|
|
7120
7520
|
}
|
|
7121
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
|
+
}
|
|
7122
7546
|
};
|
|
7123
|
-
onboardingManager = new OnboardingManager();
|
|
7124
|
-
}
|
|
7125
|
-
});
|
|
7126
|
-
|
|
7127
|
-
// src/domains/onboarding/index.ts
|
|
7128
|
-
var init_onboarding = __esm({
|
|
7129
|
-
"src/domains/onboarding/index.ts"() {
|
|
7130
|
-
"use strict";
|
|
7131
|
-
init_OnboardingManager();
|
|
7132
|
-
init_OnboardingError();
|
|
7133
|
-
}
|
|
7134
|
-
});
|
|
7135
|
-
|
|
7136
|
-
// src/domains/paywall/paywallHeartbeatRecovery.ts
|
|
7137
|
-
async function recoverPaywallHeartbeat(apiClient, distinctId, sessionId, debug) {
|
|
7138
|
-
const snapshot = await readPersistedHeartbeat();
|
|
7139
|
-
if (!snapshot) return false;
|
|
7140
|
-
try {
|
|
7141
|
-
const closedAt = new Date(snapshot.lastSeen);
|
|
7142
|
-
const durationS = Math.max(0, Math.round((snapshot.lastSeen - snapshot.presentedAt) / 1e3));
|
|
7143
|
-
await apiClient.trackEvent("paywall", distinctId, {
|
|
7144
|
-
type: "closed",
|
|
7145
|
-
paywall_id: snapshot.paywallId,
|
|
7146
|
-
placement: snapshot.placement,
|
|
7147
|
-
closed_at: closedAt.toISOString(),
|
|
7148
|
-
duration_s: durationS,
|
|
7149
|
-
close_reason: "error",
|
|
7150
|
-
...snapshot.variantId && { variant_id: snapshot.variantId },
|
|
7151
|
-
...snapshot.variantKey && { variant_key: snapshot.variantKey },
|
|
7152
|
-
...snapshot.campaignId && { campaign_id: snapshot.campaignId },
|
|
7153
|
-
...sessionId && { sessionId }
|
|
7154
|
-
});
|
|
7155
|
-
if (debug) console.log("[Paywallo HEARTBEAT] recovered orphan paywall close", {
|
|
7156
|
-
paywallId: snapshot.paywallId,
|
|
7157
|
-
durationS
|
|
7158
|
-
});
|
|
7159
|
-
return true;
|
|
7160
|
-
} catch (err) {
|
|
7161
|
-
if (debug) console.log("[Paywallo HEARTBEAT] recovery failed", err);
|
|
7162
|
-
return false;
|
|
7163
|
-
} finally {
|
|
7164
|
-
await clearPersistedHeartbeat();
|
|
7165
|
-
}
|
|
7166
|
-
}
|
|
7167
|
-
var init_paywallHeartbeatRecovery = __esm({
|
|
7168
|
-
"src/domains/paywall/paywallHeartbeatRecovery.ts"() {
|
|
7169
|
-
"use strict";
|
|
7170
|
-
init_paywallHeartbeat();
|
|
7171
7547
|
}
|
|
7172
7548
|
});
|
|
7173
7549
|
|
|
@@ -7211,6 +7587,8 @@ var init_eventPipelineBridge = __esm({
|
|
|
7211
7587
|
|
|
7212
7588
|
// src/core/PaywalloInitHelpers.ts
|
|
7213
7589
|
function setupNotifications(apiClient, config, environment, eventPipeline) {
|
|
7590
|
+
if (config.notifications === false) return;
|
|
7591
|
+
if (config.notifications === void 0 && !isNativePushAvailable()) return;
|
|
7214
7592
|
try {
|
|
7215
7593
|
notificationsManager.injectDeps({
|
|
7216
7594
|
httpClient: apiClient.getHttpClient(),
|
|
@@ -7252,7 +7630,10 @@ function setupAutoPreload(state, apiClient, config, distinctId) {
|
|
|
7252
7630
|
return null;
|
|
7253
7631
|
}).catch(() => null);
|
|
7254
7632
|
}
|
|
7255
|
-
|
|
7633
|
+
function startBatchPreload(apiClient, debug) {
|
|
7634
|
+
void campaignGateService.preloadAllActive(apiClient, debug).catch(() => {
|
|
7635
|
+
});
|
|
7636
|
+
}
|
|
7256
7637
|
var init_PaywalloInitHelpers = __esm({
|
|
7257
7638
|
"src/core/PaywalloInitHelpers.ts"() {
|
|
7258
7639
|
"use strict";
|
|
@@ -7260,7 +7641,8 @@ var init_PaywalloInitHelpers = __esm({
|
|
|
7260
7641
|
init_identity();
|
|
7261
7642
|
init_notifications();
|
|
7262
7643
|
init_SecureStorage();
|
|
7263
|
-
|
|
7644
|
+
init_NativePushBridge();
|
|
7645
|
+
init_constants();
|
|
7264
7646
|
}
|
|
7265
7647
|
});
|
|
7266
7648
|
|
|
@@ -7309,7 +7691,7 @@ function reportInitFailure(state, config, error, reason) {
|
|
|
7309
7691
|
try {
|
|
7310
7692
|
const tempClient = new ApiClient(
|
|
7311
7693
|
config.appKey,
|
|
7312
|
-
config.apiUrl ??
|
|
7694
|
+
config.apiUrl ?? DEFAULT_API_URL,
|
|
7313
7695
|
config.debug
|
|
7314
7696
|
);
|
|
7315
7697
|
void tempClient.reportError("INIT_FAILED", reason, {
|
|
@@ -7353,7 +7735,7 @@ async function doInit(state, config) {
|
|
|
7353
7735
|
]);
|
|
7354
7736
|
const apiClient = new ApiClient(
|
|
7355
7737
|
config.appKey,
|
|
7356
|
-
config.apiUrl ??
|
|
7738
|
+
config.apiUrl ?? DEFAULT_API_URL,
|
|
7357
7739
|
config.debug,
|
|
7358
7740
|
environment,
|
|
7359
7741
|
offlineQueueEnabled,
|
|
@@ -7373,6 +7755,7 @@ async function doInit(state, config) {
|
|
|
7373
7755
|
cacheTTL: config.subscriptionCacheTTL,
|
|
7374
7756
|
debug: config.debug
|
|
7375
7757
|
});
|
|
7758
|
+
planService.init({ apiClient, debug: config.debug ?? false });
|
|
7376
7759
|
await identityManager.initialize(apiClient, config.debug);
|
|
7377
7760
|
if (state.pendingIdentifies.length > 0) {
|
|
7378
7761
|
for (const pending of state.pendingIdentifies) {
|
|
@@ -7395,6 +7778,9 @@ async function doInit(state, config) {
|
|
|
7395
7778
|
} catch (err) {
|
|
7396
7779
|
if (config.debug) console.log("[Paywallo ATTR] start error", err);
|
|
7397
7780
|
}
|
|
7781
|
+
void nativeDeviceInfo.getDeviceInfo().catch(() => null);
|
|
7782
|
+
void advertisingIdManager.collect(false).catch(() => null);
|
|
7783
|
+
void metaBridge.getAnonymousID().catch(() => null);
|
|
7398
7784
|
apiClient.setEventContextProvider(() => {
|
|
7399
7785
|
const attr = attributionTracker.get();
|
|
7400
7786
|
const attrEntries = attr ? [
|
|
@@ -7409,11 +7795,35 @@ async function doInit(state, config) {
|
|
|
7409
7795
|
["referrer", attr.referrer]
|
|
7410
7796
|
].filter((pair) => pair[1] !== void 0 && pair[1] !== "") : [];
|
|
7411
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
|
+
}
|
|
7412
7816
|
return {
|
|
7413
7817
|
distinct_id: identityManager.getDistinctId() || void 0,
|
|
7414
7818
|
device_id: identityManager.getDeviceId() ?? void 0,
|
|
7415
7819
|
session_id: sessionManager.getSessionId() ?? void 0,
|
|
7416
|
-
|
|
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 }
|
|
7417
7827
|
};
|
|
7418
7828
|
});
|
|
7419
7829
|
await sessionManager.initialize(
|
|
@@ -7447,7 +7857,7 @@ async function doInit(state, config) {
|
|
|
7447
7857
|
state.resolveReady();
|
|
7448
7858
|
state.resolveReady = null;
|
|
7449
7859
|
}
|
|
7450
|
-
|
|
7860
|
+
console.warn("[Paywallo] initialized successfully");
|
|
7451
7861
|
if (distinctId) {
|
|
7452
7862
|
apiClient.getSubscriptionStatus(distinctId).then(() => {
|
|
7453
7863
|
if (config.debug) console.log("[Paywallo SUB] preloaded on boot");
|
|
@@ -7458,27 +7868,30 @@ async function doInit(state, config) {
|
|
|
7458
7868
|
});
|
|
7459
7869
|
}
|
|
7460
7870
|
setupAutoPreload(state, apiClient, config, distinctId);
|
|
7871
|
+
startBatchPreload(apiClient, config.debug);
|
|
7461
7872
|
}
|
|
7462
|
-
var DEFAULT_API_URL2;
|
|
7463
7873
|
var init_PaywalloInitializer = __esm({
|
|
7464
7874
|
"src/core/PaywalloInitializer.ts"() {
|
|
7465
7875
|
"use strict";
|
|
7466
|
-
init_SubscriptionManager();
|
|
7467
|
-
init_ApiClient();
|
|
7468
7876
|
init_identity();
|
|
7877
|
+
init_plan();
|
|
7878
|
+
init_AdvertisingIdManager();
|
|
7469
7879
|
init_DeepLinkAttributionCapture();
|
|
7470
7880
|
init_InstallTracker();
|
|
7471
|
-
|
|
7472
|
-
init_queue();
|
|
7473
|
-
init_session();
|
|
7881
|
+
init_MetaBridge();
|
|
7474
7882
|
init_onboarding();
|
|
7475
|
-
init_NativeStorage();
|
|
7476
|
-
init_NativeDeviceInfo();
|
|
7477
7883
|
init_paywallHeartbeatRecovery();
|
|
7884
|
+
init_session();
|
|
7885
|
+
init_SubscriptionManager();
|
|
7886
|
+
init_NativeDeviceInfo();
|
|
7887
|
+
init_ApiClient();
|
|
7888
|
+
init_constants();
|
|
7478
7889
|
init_eventPipelineBridge();
|
|
7479
|
-
|
|
7890
|
+
init_network();
|
|
7480
7891
|
init_PaywalloInitHelpers();
|
|
7481
|
-
|
|
7892
|
+
init_PaywalloState();
|
|
7893
|
+
init_queue();
|
|
7894
|
+
init_NativeStorage();
|
|
7482
7895
|
}
|
|
7483
7896
|
});
|
|
7484
7897
|
|
|
@@ -7732,6 +8145,7 @@ var init_PaywalloClient = __esm({
|
|
|
7732
8145
|
init_PaywalloAnalytics();
|
|
7733
8146
|
init_PaywalloSubscription();
|
|
7734
8147
|
init_PaywalloFlags();
|
|
8148
|
+
init_plan();
|
|
7735
8149
|
PaywalloClientClass = class {
|
|
7736
8150
|
constructor() {
|
|
7737
8151
|
this.state = createPaywalloState();
|
|
@@ -7983,6 +8397,14 @@ var init_PaywalloClient = __esm({
|
|
|
7983
8397
|
async processOfflineQueue() {
|
|
7984
8398
|
return queueProcessor.processQueue();
|
|
7985
8399
|
}
|
|
8400
|
+
async getPlans() {
|
|
8401
|
+
this.ensureInitialized();
|
|
8402
|
+
return planService.getAllPlans();
|
|
8403
|
+
}
|
|
8404
|
+
async getCurrentPlan() {
|
|
8405
|
+
this.ensureInitialized();
|
|
8406
|
+
return planService.getCurrentPlan();
|
|
8407
|
+
}
|
|
7986
8408
|
getApiClientOrThrow() {
|
|
7987
8409
|
if (!this.state.config || !this.state.apiClient) throw new ClientError(CLIENT_ERROR_CODES.NOT_INITIALIZED, "SDK not initialized. Call Paywallo.init() first");
|
|
7988
8410
|
return this.state.apiClient;
|
|
@@ -8065,8 +8487,124 @@ function usePaywallo() {
|
|
|
8065
8487
|
return context;
|
|
8066
8488
|
}
|
|
8067
8489
|
|
|
8068
|
-
// src/hooks/
|
|
8490
|
+
// src/hooks/usePlans.ts
|
|
8069
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";
|
|
8070
8608
|
|
|
8071
8609
|
// src/utils/productMappers.ts
|
|
8072
8610
|
function mapToIAPProduct(product) {
|
|
@@ -8105,11 +8643,11 @@ function mapToFormattedProduct(product) {
|
|
|
8105
8643
|
|
|
8106
8644
|
// src/hooks/useProducts.ts
|
|
8107
8645
|
function useProducts(initialProductIds) {
|
|
8108
|
-
const [products, setProducts] =
|
|
8109
|
-
const [formattedProducts, setFormattedProducts] =
|
|
8110
|
-
const [isLoading, setIsLoading] =
|
|
8111
|
-
const [error, setError] =
|
|
8112
|
-
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) => {
|
|
8113
8651
|
setIsLoading(true);
|
|
8114
8652
|
setError(null);
|
|
8115
8653
|
try {
|
|
@@ -8123,24 +8661,24 @@ function useProducts(initialProductIds) {
|
|
|
8123
8661
|
setIsLoading(false);
|
|
8124
8662
|
}
|
|
8125
8663
|
}, []);
|
|
8126
|
-
|
|
8664
|
+
useEffect8(() => {
|
|
8127
8665
|
if (initialProductIds && initialProductIds.length > 0) {
|
|
8128
8666
|
void loadProducts(initialProductIds);
|
|
8129
8667
|
}
|
|
8130
8668
|
}, []);
|
|
8131
|
-
const getProduct =
|
|
8669
|
+
const getProduct = useCallback10(
|
|
8132
8670
|
(productId) => {
|
|
8133
8671
|
return products.find((p) => p.productId === productId);
|
|
8134
8672
|
},
|
|
8135
8673
|
[products]
|
|
8136
8674
|
);
|
|
8137
|
-
const getFormattedProduct =
|
|
8675
|
+
const getFormattedProduct = useCallback10(
|
|
8138
8676
|
(productId) => {
|
|
8139
8677
|
return formattedProducts.find((p) => p.productId === productId);
|
|
8140
8678
|
},
|
|
8141
8679
|
[formattedProducts]
|
|
8142
8680
|
);
|
|
8143
|
-
const getPriceInfo =
|
|
8681
|
+
const getPriceInfo = useCallback10(
|
|
8144
8682
|
(productId) => {
|
|
8145
8683
|
const p = formattedProducts.find((fp) => fp.productId === productId);
|
|
8146
8684
|
if (!p) return void 0;
|
|
@@ -8169,11 +8707,11 @@ function useProducts(initialProductIds) {
|
|
|
8169
8707
|
}
|
|
8170
8708
|
|
|
8171
8709
|
// src/hooks/usePurchase.ts
|
|
8172
|
-
import { useCallback as
|
|
8710
|
+
import { useCallback as useCallback11, useState as useState9 } from "react";
|
|
8173
8711
|
function usePurchase() {
|
|
8174
|
-
const [state, setState] =
|
|
8175
|
-
const [error, setError] =
|
|
8176
|
-
const purchase =
|
|
8712
|
+
const [state, setState] = useState9("idle");
|
|
8713
|
+
const [error, setError] = useState9(null);
|
|
8714
|
+
const purchase = useCallback11(async (productId) => {
|
|
8177
8715
|
setState("purchasing");
|
|
8178
8716
|
setError(null);
|
|
8179
8717
|
try {
|
|
@@ -8209,7 +8747,7 @@ function usePurchase() {
|
|
|
8209
8747
|
return { status: "failed", error: purchaseError };
|
|
8210
8748
|
}
|
|
8211
8749
|
}, []);
|
|
8212
|
-
const restore =
|
|
8750
|
+
const restore = useCallback11(async () => {
|
|
8213
8751
|
setState("restoring");
|
|
8214
8752
|
setError(null);
|
|
8215
8753
|
try {
|
|
@@ -8240,14 +8778,14 @@ function usePurchase() {
|
|
|
8240
8778
|
}
|
|
8241
8779
|
|
|
8242
8780
|
// src/hooks/useSubscription.ts
|
|
8243
|
-
import { useCallback as
|
|
8781
|
+
import { useCallback as useCallback12, useEffect as useEffect9, useState as useState10 } from "react";
|
|
8244
8782
|
init_SubscriptionManager();
|
|
8245
8783
|
var EMPTY_ENTITLEMENTS = [];
|
|
8246
8784
|
function useSubscription() {
|
|
8247
|
-
const [status, setStatus] =
|
|
8248
|
-
const [isLoading, setIsLoading] =
|
|
8249
|
-
const [error, setError] =
|
|
8250
|
-
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 () => {
|
|
8251
8789
|
setIsLoading(true);
|
|
8252
8790
|
setError(null);
|
|
8253
8791
|
try {
|
|
@@ -8260,7 +8798,7 @@ function useSubscription() {
|
|
|
8260
8798
|
setIsLoading(false);
|
|
8261
8799
|
}
|
|
8262
8800
|
}, []);
|
|
8263
|
-
const restore =
|
|
8801
|
+
const restore = useCallback12(async () => {
|
|
8264
8802
|
setIsLoading(true);
|
|
8265
8803
|
setError(null);
|
|
8266
8804
|
try {
|
|
@@ -8273,7 +8811,7 @@ function useSubscription() {
|
|
|
8273
8811
|
setIsLoading(false);
|
|
8274
8812
|
}
|
|
8275
8813
|
}, []);
|
|
8276
|
-
|
|
8814
|
+
useEffect9(() => {
|
|
8277
8815
|
void subscriptionManager.getSubscriptionStatus().then((s) => {
|
|
8278
8816
|
setStatus(s);
|
|
8279
8817
|
setIsLoading(false);
|
|
@@ -8300,16 +8838,19 @@ function useSubscription() {
|
|
|
8300
8838
|
};
|
|
8301
8839
|
}
|
|
8302
8840
|
|
|
8841
|
+
// src/index.ts
|
|
8842
|
+
init_plan();
|
|
8843
|
+
|
|
8303
8844
|
// src/PaywalloProvider.tsx
|
|
8304
8845
|
init_paywall();
|
|
8305
8846
|
init_paywall();
|
|
8306
8847
|
init_paywall();
|
|
8307
|
-
import { useCallback as
|
|
8848
|
+
import { useCallback as useCallback17, useEffect as useEffect11, useLayoutEffect, useMemo as useMemo2, useRef as useRef10, useState as useState14 } from "react";
|
|
8308
8849
|
import { Animated as Animated3, Dimensions as Dimensions4, Easing as Easing2, StyleSheet as StyleSheet3 } from "react-native";
|
|
8309
8850
|
init_PaywalloClient();
|
|
8310
8851
|
|
|
8311
8852
|
// src/hooks/useAppAutoEvents.ts
|
|
8312
|
-
import { useEffect as
|
|
8853
|
+
import { useEffect as useEffect10, useRef as useRef7 } from "react";
|
|
8313
8854
|
var FIRST_SEEN_KEY = "@panel:firstSeen";
|
|
8314
8855
|
var DEBOUNCE_MS = 1e3;
|
|
8315
8856
|
async function detectPlatform3() {
|
|
@@ -8340,7 +8881,7 @@ function useAppAutoEvents(config) {
|
|
|
8340
8881
|
debug
|
|
8341
8882
|
} = config;
|
|
8342
8883
|
const didRunRef = useRef7(false);
|
|
8343
|
-
|
|
8884
|
+
useEffect10(() => {
|
|
8344
8885
|
if (!isInitialized || didRunRef.current) return;
|
|
8345
8886
|
const timer = setTimeout(() => {
|
|
8346
8887
|
if (didRunRef.current) return;
|
|
@@ -8387,7 +8928,7 @@ function useAppAutoEvents(config) {
|
|
|
8387
8928
|
// src/hooks/useCampaignPreload.ts
|
|
8388
8929
|
init_PaywalloClient();
|
|
8389
8930
|
init_CampaignError();
|
|
8390
|
-
import { useCallback as
|
|
8931
|
+
import { useCallback as useCallback13, useRef as useRef8, useState as useState11 } from "react";
|
|
8391
8932
|
|
|
8392
8933
|
// src/utils/loadCampaignProducts.ts
|
|
8393
8934
|
init_IAPService();
|
|
@@ -8456,17 +8997,17 @@ function getCacheEntry(cache, placement) {
|
|
|
8456
8997
|
|
|
8457
8998
|
// src/hooks/useCampaignPreload.ts
|
|
8458
8999
|
function useCampaignPreload() {
|
|
8459
|
-
const [preloadedWebView, setPreloadedWebView] =
|
|
9000
|
+
const [preloadedWebView, setPreloadedWebView] = useState11(null);
|
|
8460
9001
|
const preloadedCampaignsRef = useRef8(/* @__PURE__ */ new Map());
|
|
8461
|
-
const isPreloadValid =
|
|
9002
|
+
const isPreloadValid = useCallback13(
|
|
8462
9003
|
(placement) => isCacheEntryValid(preloadedCampaignsRef.current.get(placement)),
|
|
8463
9004
|
[]
|
|
8464
9005
|
);
|
|
8465
|
-
const consumePreloadedCampaign =
|
|
9006
|
+
const consumePreloadedCampaign = useCallback13(
|
|
8466
9007
|
(placement) => getCacheEntry(preloadedCampaignsRef.current, placement),
|
|
8467
9008
|
[]
|
|
8468
9009
|
);
|
|
8469
|
-
const preloadCampaign =
|
|
9010
|
+
const preloadCampaign = useCallback13(
|
|
8470
9011
|
async (placement, context) => {
|
|
8471
9012
|
try {
|
|
8472
9013
|
const campaign = await PaywalloClient.getCampaign(placement, context);
|
|
@@ -8540,12 +9081,12 @@ init_SecureStorage();
|
|
|
8540
9081
|
init_paywall();
|
|
8541
9082
|
|
|
8542
9083
|
// src/hooks/useProductLoader.ts
|
|
8543
|
-
import { useCallback as
|
|
9084
|
+
import { useCallback as useCallback14, useState as useState12 } from "react";
|
|
8544
9085
|
init_PaywalloClient();
|
|
8545
9086
|
function useProductLoader() {
|
|
8546
|
-
const [products, setProducts] =
|
|
8547
|
-
const [isLoadingProducts, setIsLoadingProducts] =
|
|
8548
|
-
const refreshProducts =
|
|
9087
|
+
const [products, setProducts] = useState12(/* @__PURE__ */ new Map());
|
|
9088
|
+
const [isLoadingProducts, setIsLoadingProducts] = useState12(false);
|
|
9089
|
+
const refreshProducts = useCallback14(async (productIds) => {
|
|
8549
9090
|
setIsLoadingProducts(true);
|
|
8550
9091
|
try {
|
|
8551
9092
|
const iapService = getIAPService();
|
|
@@ -8563,12 +9104,12 @@ function useProductLoader() {
|
|
|
8563
9104
|
}
|
|
8564
9105
|
|
|
8565
9106
|
// src/hooks/usePurchaseOrchestrator.ts
|
|
8566
|
-
import { useCallback as
|
|
9107
|
+
import { useCallback as useCallback15 } from "react";
|
|
8567
9108
|
init_PaywalloClient();
|
|
8568
9109
|
init_paywall();
|
|
8569
9110
|
function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clearPreloadedWebView, setShowingPreloadedWebView, presentedAtRef, invalidateSubscriptionCache) {
|
|
8570
9111
|
const { trackDismissed, trackProductSelected, trackPurchased } = usePaywallTracking();
|
|
8571
|
-
const handlePreloadedPurchase =
|
|
9112
|
+
const handlePreloadedPurchase = useCallback15(
|
|
8572
9113
|
async (productId) => {
|
|
8573
9114
|
try {
|
|
8574
9115
|
if (preloadedWebView) {
|
|
@@ -8606,7 +9147,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
|
|
|
8606
9147
|
},
|
|
8607
9148
|
[preloadedWebView, resolvePreloadedPaywall, clearPreloadedWebView, setShowingPreloadedWebView, presentedAtRef, trackDismissed, trackProductSelected, trackPurchased, invalidateSubscriptionCache]
|
|
8608
9149
|
);
|
|
8609
|
-
const handlePreloadedRestore =
|
|
9150
|
+
const handlePreloadedRestore = useCallback15(async () => {
|
|
8610
9151
|
try {
|
|
8611
9152
|
const transactions = await getIAPService().restore();
|
|
8612
9153
|
if (transactions.length === 0) return;
|
|
@@ -8631,7 +9172,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
|
|
|
8631
9172
|
// src/hooks/useSubscriptionSync.ts
|
|
8632
9173
|
init_PaywalloClient();
|
|
8633
9174
|
init_SubscriptionCache();
|
|
8634
|
-
import { useCallback as
|
|
9175
|
+
import { useCallback as useCallback16, useRef as useRef9, useState as useState13 } from "react";
|
|
8635
9176
|
var CACHE_TTL_MS2 = 5 * 60 * 1e3;
|
|
8636
9177
|
var ACTIVE_STATUSES = ["active", "in_grace_period"];
|
|
8637
9178
|
var PUBLIC_TO_DOMAIN_STATUS = {
|
|
@@ -8696,14 +9237,14 @@ function isActiveCacheEntry(entry) {
|
|
|
8696
9237
|
return isSubscriptionStillActive(entry.data);
|
|
8697
9238
|
}
|
|
8698
9239
|
function useSubscriptionSync() {
|
|
8699
|
-
const [subscription, setSubscription] =
|
|
9240
|
+
const [subscription, setSubscription] = useState13(null);
|
|
8700
9241
|
const cacheRef = useRef9(null);
|
|
8701
|
-
const invalidateCache =
|
|
9242
|
+
const invalidateCache = useCallback16(() => {
|
|
8702
9243
|
cacheRef.current = null;
|
|
8703
9244
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8704
9245
|
if (distinctId) void subscriptionCache.invalidate(distinctId);
|
|
8705
9246
|
}, []);
|
|
8706
|
-
const fetchAndCache =
|
|
9247
|
+
const fetchAndCache = useCallback16(async () => {
|
|
8707
9248
|
const apiClient = PaywalloClient.getApiClient();
|
|
8708
9249
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8709
9250
|
if (!apiClient || !distinctId) return null;
|
|
@@ -8717,7 +9258,7 @@ function useSubscriptionSync() {
|
|
|
8717
9258
|
void subscriptionCache.set(distinctId, toDomainResponse(status));
|
|
8718
9259
|
return sub;
|
|
8719
9260
|
}, []);
|
|
8720
|
-
const hasActiveSubscription =
|
|
9261
|
+
const hasActiveSubscription = useCallback16(async () => {
|
|
8721
9262
|
const apiClient = PaywalloClient.getApiClient();
|
|
8722
9263
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8723
9264
|
if (!apiClient || !distinctId) return false;
|
|
@@ -8760,7 +9301,7 @@ function useSubscriptionSync() {
|
|
|
8760
9301
|
return resolveOfflineFromCache(distinctId);
|
|
8761
9302
|
}
|
|
8762
9303
|
}, []);
|
|
8763
|
-
const getSubscription =
|
|
9304
|
+
const getSubscription = useCallback16(async () => {
|
|
8764
9305
|
const apiClient = PaywalloClient.getApiClient();
|
|
8765
9306
|
const distinctId = PaywalloClient.getDistinctId();
|
|
8766
9307
|
if (!apiClient || !distinctId) return null;
|
|
@@ -8787,20 +9328,20 @@ init_ClientError();
|
|
|
8787
9328
|
init_localization();
|
|
8788
9329
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
8789
9330
|
function PaywalloProvider({ children, config }) {
|
|
8790
|
-
const [isInitialized, setIsInitialized] =
|
|
8791
|
-
const [initError, setInitError] =
|
|
8792
|
-
const [distinctId, setDistinctId] =
|
|
8793
|
-
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);
|
|
8794
9335
|
const { products, isLoadingProducts, refreshProducts } = useProductLoader();
|
|
8795
9336
|
const { subscription, hasActiveSubscription, getSubscription, invalidateCache } = useSubscriptionSync();
|
|
8796
9337
|
const { preloadedWebView, setPreloadedWebView, preloadCampaign, consumePreloadedCampaign, isPreloadValid } = useCampaignPreload();
|
|
8797
|
-
const clearPreloadedWebView =
|
|
9338
|
+
const clearPreloadedWebView = useCallback17(() => setPreloadedWebView(null), [setPreloadedWebView]);
|
|
8798
9339
|
const autoPreloadTriggeredRef = useRef10(false);
|
|
8799
9340
|
const preloadedWebViewRef = useRef10(preloadedWebView);
|
|
8800
9341
|
const pollTimerRef = useRef10(null);
|
|
8801
9342
|
const pollCancelledRef = useRef10(false);
|
|
8802
9343
|
const secureStorageRef = useRef10(new SecureStorage(config.debug));
|
|
8803
|
-
|
|
9344
|
+
useEffect11(() => {
|
|
8804
9345
|
preloadedWebViewRef.current = preloadedWebView;
|
|
8805
9346
|
}, [preloadedWebView]);
|
|
8806
9347
|
useAppAutoEvents({
|
|
@@ -8816,20 +9357,20 @@ function PaywalloProvider({ children, config }) {
|
|
|
8816
9357
|
storageSet: (key, value) => secureStorageRef.current.set(key, value),
|
|
8817
9358
|
debug: config.debug
|
|
8818
9359
|
});
|
|
8819
|
-
const triggerRepreload =
|
|
9360
|
+
const triggerRepreload = useCallback17((placement) => {
|
|
8820
9361
|
void PaywalloClient.preloadCampaign(placement).catch(() => {
|
|
8821
9362
|
});
|
|
8822
9363
|
}, []);
|
|
8823
9364
|
const { showingPreloadedWebView, presentPreloadedWebView, resolvePreloadedPaywall, handlePreloadedWebViewReady: baseHandlePreloadedWebViewReady, handlePreloadedClose: baseHandlePreloadedClose, setShowingPreloadedWebView, presentedAtRef } = usePaywallPresenter(preloadedWebView, setPreloadedWebView);
|
|
8824
9365
|
const SCREEN_HEIGHT = useMemo2(() => Dimensions4.get("window").height, []);
|
|
8825
9366
|
const slideAnim = useRef10(new Animated3.Value(SCREEN_HEIGHT)).current;
|
|
8826
|
-
const handlePreloadedWebViewReady =
|
|
9367
|
+
const handlePreloadedWebViewReady = useCallback17(() => {
|
|
8827
9368
|
if (PaywalloClient.getConfig()?.debug) {
|
|
8828
9369
|
console.log(`[Paywallo WEBVIEW] loaded \u2014 placement: ${preloadedWebView?.placement}`);
|
|
8829
9370
|
}
|
|
8830
9371
|
baseHandlePreloadedWebViewReady();
|
|
8831
9372
|
}, [preloadedWebView?.placement, baseHandlePreloadedWebViewReady]);
|
|
8832
|
-
const handlePreloadedClose =
|
|
9373
|
+
const handlePreloadedClose = useCallback17(() => {
|
|
8833
9374
|
const placement = preloadedWebView?.placement;
|
|
8834
9375
|
Animated3.timing(slideAnim, { toValue: SCREEN_HEIGHT, duration: 200, easing: Easing2.in(Easing2.cubic), useNativeDriver: true }).start(() => {
|
|
8835
9376
|
baseHandlePreloadedClose();
|
|
@@ -8844,8 +9385,8 @@ function PaywalloProvider({ children, config }) {
|
|
|
8844
9385
|
presentedAtRef,
|
|
8845
9386
|
invalidateCache
|
|
8846
9387
|
);
|
|
8847
|
-
const [isPreloadPurchasing, setIsPreloadPurchasing] =
|
|
8848
|
-
const handlePreloadedPurchase =
|
|
9388
|
+
const [isPreloadPurchasing, setIsPreloadPurchasing] = useState14(false);
|
|
9389
|
+
const handlePreloadedPurchase = useCallback17(async (productId) => {
|
|
8849
9390
|
setIsPreloadPurchasing(true);
|
|
8850
9391
|
try {
|
|
8851
9392
|
await rawPreloadedPurchase(productId);
|
|
@@ -8854,7 +9395,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
8854
9395
|
}
|
|
8855
9396
|
}, [rawPreloadedPurchase]);
|
|
8856
9397
|
const configRef = useRef10(config);
|
|
8857
|
-
|
|
9398
|
+
useEffect11(() => {
|
|
8858
9399
|
let mounted = true;
|
|
8859
9400
|
initLocalization({ detectDevice: true });
|
|
8860
9401
|
PaywalloClient.init(configRef.current).then(async () => {
|
|
@@ -8875,14 +9416,14 @@ function PaywalloProvider({ children, config }) {
|
|
|
8875
9416
|
mounted = false;
|
|
8876
9417
|
};
|
|
8877
9418
|
}, [preloadCampaign]);
|
|
8878
|
-
const getPaywallConfig =
|
|
9419
|
+
const getPaywallConfig = useCallback17(async (p) => {
|
|
8879
9420
|
const api = PaywalloClient.getApiClient();
|
|
8880
9421
|
return api ? api.getPaywall(p) : null;
|
|
8881
9422
|
}, []);
|
|
8882
|
-
const presentPaywall =
|
|
9423
|
+
const presentPaywall = useCallback17((placement) => {
|
|
8883
9424
|
return new Promise((resolve) => setActivePaywall({ placement, resolver: resolve }));
|
|
8884
9425
|
}, []);
|
|
8885
|
-
const trackCampaignImpression =
|
|
9426
|
+
const trackCampaignImpression = useCallback17((placement, variantKey, campaignId) => {
|
|
8886
9427
|
const api = PaywalloClient.getApiClient();
|
|
8887
9428
|
if (!api) return;
|
|
8888
9429
|
const sessionId = PaywalloClient.getSessionId();
|
|
@@ -8896,7 +9437,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
8896
9437
|
}).catch(() => {
|
|
8897
9438
|
});
|
|
8898
9439
|
}, []);
|
|
8899
|
-
const presentCampaign =
|
|
9440
|
+
const presentCampaign = useCallback17(
|
|
8900
9441
|
async (placement, context) => {
|
|
8901
9442
|
try {
|
|
8902
9443
|
if (preloadedWebView?.placement === placement && preloadedWebView.loaded && isPreloadValid(placement)) {
|
|
@@ -8970,7 +9511,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
8970
9511
|
},
|
|
8971
9512
|
[preloadedWebView, isPreloadValid, consumePreloadedCampaign, presentPreloadedWebView, trackCampaignImpression]
|
|
8972
9513
|
);
|
|
8973
|
-
const restorePurchases =
|
|
9514
|
+
const restorePurchases = useCallback17(async () => {
|
|
8974
9515
|
invalidateCache();
|
|
8975
9516
|
try {
|
|
8976
9517
|
const txs = await getIAPService().restore();
|
|
@@ -8979,13 +9520,13 @@ function PaywalloProvider({ children, config }) {
|
|
|
8979
9520
|
return { success: false, restoredProducts: [], error: error instanceof Error ? error : new PurchaseError(PURCHASE_ERROR_CODES.RESTORE_FAILED, String(error)) };
|
|
8980
9521
|
}
|
|
8981
9522
|
}, [invalidateCache]);
|
|
8982
|
-
const handlePaywallResult =
|
|
9523
|
+
const handlePaywallResult = useCallback17((result) => {
|
|
8983
9524
|
if (activePaywall) {
|
|
8984
9525
|
activePaywall.resolver(result);
|
|
8985
9526
|
setActivePaywall(null);
|
|
8986
9527
|
}
|
|
8987
9528
|
}, [activePaywall]);
|
|
8988
|
-
const bridgePaywallPresenter =
|
|
9529
|
+
const bridgePaywallPresenter = useCallback17((placement) => {
|
|
8989
9530
|
if (PaywalloClient.getConfig()?.debug) {
|
|
8990
9531
|
console.log(`[Paywallo PRESENT] called \u2014 preloaded: ${preloadedWebViewRef.current?.loaded === true} placement: ${placement}`);
|
|
8991
9532
|
}
|
|
@@ -9014,7 +9555,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
9014
9555
|
}
|
|
9015
9556
|
return presentCampaign(placement);
|
|
9016
9557
|
}, [presentPreloadedWebView, presentCampaign]);
|
|
9017
|
-
|
|
9558
|
+
useEffect11(() => {
|
|
9018
9559
|
if (!isInitialized) return;
|
|
9019
9560
|
const onEmergency = async (id) => {
|
|
9020
9561
|
try {
|
|
@@ -9041,7 +9582,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
9041
9582
|
};
|
|
9042
9583
|
}, [isInitialized, bridgePaywallPresenter, getSubscription, hasActiveSubscription, restorePurchases]);
|
|
9043
9584
|
const isReady = isInitialized && !isLoadingProducts;
|
|
9044
|
-
const noOp =
|
|
9585
|
+
const noOp = useCallback17(() => {
|
|
9045
9586
|
}, []);
|
|
9046
9587
|
const contextValue = useMemo2(() => ({
|
|
9047
9588
|
config: PaywalloClient.getConfig(),
|
|
@@ -9283,6 +9824,8 @@ export {
|
|
|
9283
9824
|
PaywalloContext,
|
|
9284
9825
|
PaywalloError,
|
|
9285
9826
|
PaywalloProvider,
|
|
9827
|
+
PlanCache,
|
|
9828
|
+
PlanService,
|
|
9286
9829
|
PurchaseError,
|
|
9287
9830
|
SESSION_ERROR_CODES,
|
|
9288
9831
|
SessionError,
|
|
@@ -9305,6 +9848,8 @@ export {
|
|
|
9305
9848
|
offlineQueue,
|
|
9306
9849
|
onboardingManager,
|
|
9307
9850
|
parseVariables,
|
|
9851
|
+
planCache,
|
|
9852
|
+
planService,
|
|
9308
9853
|
queueProcessor,
|
|
9309
9854
|
resolveText,
|
|
9310
9855
|
sessionManager,
|
|
@@ -9314,6 +9859,8 @@ export {
|
|
|
9314
9859
|
useOnboarding,
|
|
9315
9860
|
usePaywallContext,
|
|
9316
9861
|
usePaywallo,
|
|
9862
|
+
usePlanPurchase,
|
|
9863
|
+
usePlans,
|
|
9317
9864
|
useProducts,
|
|
9318
9865
|
usePurchase,
|
|
9319
9866
|
useSubscription
|