@virex-tech/paywallo-sdk 2.2.6 → 2.2.7
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 +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +834 -508
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +726 -400
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2370,8 +2370,8 @@ var init_NotificationHandlerSetup = __esm({
|
|
|
2370
2370
|
// src/core/version.ts
|
|
2371
2371
|
function resolveVersion() {
|
|
2372
2372
|
try {
|
|
2373
|
-
if ("2.2.
|
|
2374
|
-
return "2.2.
|
|
2373
|
+
if ("2.2.7") {
|
|
2374
|
+
return "2.2.7";
|
|
2375
2375
|
}
|
|
2376
2376
|
} catch {
|
|
2377
2377
|
}
|
|
@@ -3041,6 +3041,41 @@ var init_emitPaywallClosed = __esm({
|
|
|
3041
3041
|
}
|
|
3042
3042
|
});
|
|
3043
3043
|
|
|
3044
|
+
// src/domains/paywall/extractFirstPageBackground.ts
|
|
3045
|
+
function extractFirstPageBackground(craftData) {
|
|
3046
|
+
if (!craftData) return DEFAULT_BACKGROUND;
|
|
3047
|
+
try {
|
|
3048
|
+
const data = JSON.parse(craftData);
|
|
3049
|
+
const nodes = { ...data.nodes, ...data.sharedNodes };
|
|
3050
|
+
const rootId = data.rootId;
|
|
3051
|
+
if (!rootId || !nodes[rootId]) return DEFAULT_BACKGROUND;
|
|
3052
|
+
const firstPageId = nodes[rootId].children?.[0];
|
|
3053
|
+
if (!firstPageId) return DEFAULT_BACKGROUND;
|
|
3054
|
+
const bg = nodes[firstPageId]?.props?.backgroundColor;
|
|
3055
|
+
return typeof bg === "string" && bg.length > 0 && bg !== "transparent" ? bg : DEFAULT_BACKGROUND;
|
|
3056
|
+
} catch {
|
|
3057
|
+
return DEFAULT_BACKGROUND;
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
function isColorDark(color) {
|
|
3061
|
+
const hex = color.replace("#", "").trim();
|
|
3062
|
+
const normalized = hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex;
|
|
3063
|
+
if (normalized.length !== 6) return false;
|
|
3064
|
+
const r = parseInt(normalized.slice(0, 2), 16);
|
|
3065
|
+
const g = parseInt(normalized.slice(2, 4), 16);
|
|
3066
|
+
const b = parseInt(normalized.slice(4, 6), 16);
|
|
3067
|
+
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) return false;
|
|
3068
|
+
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
3069
|
+
return luminance < 0.5;
|
|
3070
|
+
}
|
|
3071
|
+
var DEFAULT_BACKGROUND;
|
|
3072
|
+
var init_extractFirstPageBackground = __esm({
|
|
3073
|
+
"src/domains/paywall/extractFirstPageBackground.ts"() {
|
|
3074
|
+
"use strict";
|
|
3075
|
+
DEFAULT_BACKGROUND = "#FFFFFF";
|
|
3076
|
+
}
|
|
3077
|
+
});
|
|
3078
|
+
|
|
3044
3079
|
// src/domains/paywall/parseWebViewMessage.ts
|
|
3045
3080
|
function deriveMessageId(message) {
|
|
3046
3081
|
if (message.id) return message.id;
|
|
@@ -3283,6 +3318,66 @@ var init_localization = __esm({
|
|
|
3283
3318
|
}
|
|
3284
3319
|
});
|
|
3285
3320
|
|
|
3321
|
+
// src/domains/paywall/PaywallSkeleton.tsx
|
|
3322
|
+
import { useEffect, useRef } from "react";
|
|
3323
|
+
import { Animated, StyleSheet, View } from "react-native";
|
|
3324
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3325
|
+
function SkeletonBlock({ style, color, opacity }) {
|
|
3326
|
+
return /* @__PURE__ */ jsx(Animated.View, { style: [style, { backgroundColor: color, opacity }] });
|
|
3327
|
+
}
|
|
3328
|
+
function PaywallSkeleton({ backgroundColor = "#FFFFFF" }) {
|
|
3329
|
+
const pulse = useRef(new Animated.Value(0.4)).current;
|
|
3330
|
+
useEffect(() => {
|
|
3331
|
+
const loop = Animated.loop(
|
|
3332
|
+
Animated.sequence([
|
|
3333
|
+
Animated.timing(pulse, { toValue: 1, duration: 700, useNativeDriver: true }),
|
|
3334
|
+
Animated.timing(pulse, { toValue: 0.4, duration: 700, useNativeDriver: true })
|
|
3335
|
+
])
|
|
3336
|
+
);
|
|
3337
|
+
loop.start();
|
|
3338
|
+
return () => loop.stop();
|
|
3339
|
+
}, [pulse]);
|
|
3340
|
+
const placeholder = isColorDark(backgroundColor) ? "rgba(255,255,255,0.13)" : "rgba(0,0,0,0.07)";
|
|
3341
|
+
return /* @__PURE__ */ jsxs(View, { style: [styles.container, { backgroundColor }], pointerEvents: "none", children: [
|
|
3342
|
+
/* @__PURE__ */ jsx(View, { style: styles.header, children: /* @__PURE__ */ jsx(SkeletonBlock, { style: styles.logo, color: placeholder, opacity: pulse }) }),
|
|
3343
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { style: styles.hero, color: placeholder, opacity: pulse }),
|
|
3344
|
+
/* @__PURE__ */ jsxs(View, { style: styles.titleGroup, children: [
|
|
3345
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { style: styles.titleLine, color: placeholder, opacity: pulse }),
|
|
3346
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { style: styles.titleLineShort, color: placeholder, opacity: pulse })
|
|
3347
|
+
] }),
|
|
3348
|
+
/* @__PURE__ */ jsxs(View, { style: styles.cardsRow, children: [
|
|
3349
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { style: styles.card, color: placeholder, opacity: pulse }),
|
|
3350
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { style: styles.card, color: placeholder, opacity: pulse })
|
|
3351
|
+
] }),
|
|
3352
|
+
/* @__PURE__ */ jsxs(View, { style: styles.footerGroup, children: [
|
|
3353
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { style: styles.cta, color: placeholder, opacity: pulse }),
|
|
3354
|
+
/* @__PURE__ */ jsx(SkeletonBlock, { style: styles.footer, color: placeholder, opacity: pulse })
|
|
3355
|
+
] })
|
|
3356
|
+
] });
|
|
3357
|
+
}
|
|
3358
|
+
var RADIUS, styles;
|
|
3359
|
+
var init_PaywallSkeleton = __esm({
|
|
3360
|
+
"src/domains/paywall/PaywallSkeleton.tsx"() {
|
|
3361
|
+
"use strict";
|
|
3362
|
+
init_extractFirstPageBackground();
|
|
3363
|
+
RADIUS = 14;
|
|
3364
|
+
styles = StyleSheet.create({
|
|
3365
|
+
card: { borderRadius: RADIUS, flex: 1, height: 120 },
|
|
3366
|
+
cardsRow: { flexDirection: "row", gap: 12, marginTop: "auto", paddingHorizontal: 24 },
|
|
3367
|
+
container: { flex: 1, paddingBottom: 40, paddingTop: 64 },
|
|
3368
|
+
cta: { borderRadius: 30, height: 58, marginHorizontal: 24 },
|
|
3369
|
+
footer: { alignSelf: "center", borderRadius: 6, height: 12, marginTop: 20, width: 180 },
|
|
3370
|
+
footerGroup: { marginTop: 28 },
|
|
3371
|
+
header: { alignItems: "center", paddingVertical: 12 },
|
|
3372
|
+
hero: { alignSelf: "center", borderRadius: 20, height: 220, marginTop: 16, width: "70%" },
|
|
3373
|
+
logo: { borderRadius: 6, height: 22, width: 110 },
|
|
3374
|
+
titleGroup: { alignItems: "center", gap: 12, marginTop: 28, paddingHorizontal: 24 },
|
|
3375
|
+
titleLine: { borderRadius: 8, height: 26, width: "85%" },
|
|
3376
|
+
titleLineShort: { borderRadius: 8, height: 26, width: "60%" }
|
|
3377
|
+
});
|
|
3378
|
+
}
|
|
3379
|
+
});
|
|
3380
|
+
|
|
3286
3381
|
// src/domains/paywall/paywallScripts.ts
|
|
3287
3382
|
function buildPaywallInjectionScript(data) {
|
|
3288
3383
|
const paywallData = {
|
|
@@ -3327,7 +3422,7 @@ var init_paywallScripts = __esm({
|
|
|
3327
3422
|
});
|
|
3328
3423
|
|
|
3329
3424
|
// src/domains/paywall/PaywallWebView.tsx
|
|
3330
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3425
|
+
import { useCallback, useEffect as useEffect2, useMemo, useRef as useRef2, useState } from "react";
|
|
3331
3426
|
import {
|
|
3332
3427
|
BackHandler,
|
|
3333
3428
|
findNodeHandle,
|
|
@@ -3336,11 +3431,11 @@ import {
|
|
|
3336
3431
|
NativeModules as NativeModules6,
|
|
3337
3432
|
Platform as Platform9,
|
|
3338
3433
|
requireNativeComponent,
|
|
3339
|
-
StyleSheet,
|
|
3434
|
+
StyleSheet as StyleSheet2,
|
|
3340
3435
|
UIManager,
|
|
3341
|
-
View
|
|
3436
|
+
View as View2
|
|
3342
3437
|
} from "react-native";
|
|
3343
|
-
import { jsx } from "react/jsx-runtime";
|
|
3438
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
3344
3439
|
function getNativeWebView() {
|
|
3345
3440
|
if (NativeWebViewComponent) return NativeWebViewComponent;
|
|
3346
3441
|
if (nativeWebViewLookupFailed) return null;
|
|
@@ -3398,16 +3493,16 @@ function PaywallWebView({
|
|
|
3398
3493
|
onReady,
|
|
3399
3494
|
onError
|
|
3400
3495
|
}) {
|
|
3401
|
-
const paywallDataSent =
|
|
3402
|
-
const loadEndReceived =
|
|
3496
|
+
const paywallDataSent = useRef2(false);
|
|
3497
|
+
const loadEndReceived = useRef2(false);
|
|
3403
3498
|
const [scriptToInject, setScriptToInject] = useState(void 0);
|
|
3404
|
-
const webViewRef =
|
|
3405
|
-
const onErrorRef =
|
|
3499
|
+
const webViewRef = useRef2(null);
|
|
3500
|
+
const onErrorRef = useRef2(onError);
|
|
3406
3501
|
onErrorRef.current = onError;
|
|
3407
|
-
const onReadyRef =
|
|
3502
|
+
const onReadyRef = useRef2(onReady);
|
|
3408
3503
|
onReadyRef.current = onReady;
|
|
3409
3504
|
const NativeWebView = useMemo(() => getNativeWebView(), []);
|
|
3410
|
-
|
|
3505
|
+
useEffect2(() => {
|
|
3411
3506
|
if (!NativeWebView) {
|
|
3412
3507
|
onErrorRef.current?.({
|
|
3413
3508
|
code: -1,
|
|
@@ -3418,7 +3513,7 @@ function PaywallWebView({
|
|
|
3418
3513
|
const [resolvedWebUrl, setResolvedWebUrl] = useState(
|
|
3419
3514
|
() => webUrlProp ?? PaywalloClient.getWebUrl()
|
|
3420
3515
|
);
|
|
3421
|
-
|
|
3516
|
+
useEffect2(() => {
|
|
3422
3517
|
if (webUrlProp !== void 0) {
|
|
3423
3518
|
setResolvedWebUrl(webUrlProp ?? null);
|
|
3424
3519
|
return;
|
|
@@ -3437,7 +3532,7 @@ function PaywallWebView({
|
|
|
3437
3532
|
}, 200);
|
|
3438
3533
|
return () => clearInterval(interval);
|
|
3439
3534
|
}, [webUrlProp]);
|
|
3440
|
-
|
|
3535
|
+
useEffect2(() => {
|
|
3441
3536
|
if (!resolvedWebUrl) {
|
|
3442
3537
|
onErrorRef.current?.({
|
|
3443
3538
|
code: -1,
|
|
@@ -3465,9 +3560,9 @@ function PaywallWebView({
|
|
|
3465
3560
|
});
|
|
3466
3561
|
injectScript(script);
|
|
3467
3562
|
}, [craftData, products, primaryProductId, secondaryProductId, injectScript]);
|
|
3468
|
-
const processedIdsRef =
|
|
3469
|
-
const dedupeTimersRef =
|
|
3470
|
-
|
|
3563
|
+
const processedIdsRef = useRef2(/* @__PURE__ */ new Set());
|
|
3564
|
+
const dedupeTimersRef = useRef2(/* @__PURE__ */ new Map());
|
|
3565
|
+
useEffect2(() => {
|
|
3471
3566
|
return () => {
|
|
3472
3567
|
for (const timerId of dedupeTimersRef.current.values()) clearTimeout(timerId);
|
|
3473
3568
|
dedupeTimersRef.current.clear();
|
|
@@ -3519,7 +3614,7 @@ function PaywallWebView({
|
|
|
3519
3614
|
},
|
|
3520
3615
|
[buildAndSetInjectionScript, onPurchase, onClose, onRestore]
|
|
3521
3616
|
);
|
|
3522
|
-
|
|
3617
|
+
useEffect2(() => {
|
|
3523
3618
|
const emitter = getWebViewEmitter();
|
|
3524
3619
|
if (!emitter) return;
|
|
3525
3620
|
const loadEndSub = emitter.addListener("PaywalloWebViewLoadEnd", () => {
|
|
@@ -3544,7 +3639,7 @@ function PaywallWebView({
|
|
|
3544
3639
|
errorSub.remove();
|
|
3545
3640
|
};
|
|
3546
3641
|
}, [buildAndSetInjectionScript, handleParsedMessage]);
|
|
3547
|
-
|
|
3642
|
+
useEffect2(() => {
|
|
3548
3643
|
const timer = setTimeout(() => {
|
|
3549
3644
|
if (!paywallDataSent.current) {
|
|
3550
3645
|
onErrorRef.current?.({
|
|
@@ -3584,11 +3679,11 @@ function PaywallWebView({
|
|
|
3584
3679
|
},
|
|
3585
3680
|
[handleParsedMessage]
|
|
3586
3681
|
);
|
|
3587
|
-
|
|
3682
|
+
useEffect2(() => {
|
|
3588
3683
|
if (!paywallDataSent.current) return;
|
|
3589
3684
|
injectScript(buildPurchaseStateScript(isPurchasing));
|
|
3590
3685
|
}, [isPurchasing, injectScript]);
|
|
3591
|
-
|
|
3686
|
+
useEffect2(() => {
|
|
3592
3687
|
if (Platform9.OS !== "android") return;
|
|
3593
3688
|
const onBackPress = () => {
|
|
3594
3689
|
if (!paywallDataSent.current) return false;
|
|
@@ -3600,7 +3695,7 @@ function PaywallWebView({
|
|
|
3600
3695
|
}, [injectScript]);
|
|
3601
3696
|
if (!resolvedWebUrl || !NativeWebView) return null;
|
|
3602
3697
|
const paywallUrl = `${resolvedWebUrl}/paywall/${paywallId}`;
|
|
3603
|
-
return /* @__PURE__ */
|
|
3698
|
+
return /* @__PURE__ */ jsx2(View2, { style: styles2.container, children: /* @__PURE__ */ jsx2(
|
|
3604
3699
|
NativeWebView,
|
|
3605
3700
|
{
|
|
3606
3701
|
ref: webViewRef,
|
|
@@ -3609,11 +3704,11 @@ function PaywallWebView({
|
|
|
3609
3704
|
onMessage: handleMessage,
|
|
3610
3705
|
onLoadEnd: handleLoadEnd,
|
|
3611
3706
|
onError: handleNativeError,
|
|
3612
|
-
style:
|
|
3707
|
+
style: styles2.webview
|
|
3613
3708
|
}
|
|
3614
3709
|
) });
|
|
3615
3710
|
}
|
|
3616
|
-
var NativeWebViewComponent, nativeWebViewLookupFailed, webViewEmitter,
|
|
3711
|
+
var NativeWebViewComponent, nativeWebViewLookupFailed, webViewEmitter, styles2;
|
|
3617
3712
|
var init_PaywallWebView = __esm({
|
|
3618
3713
|
"src/domains/paywall/PaywallWebView.tsx"() {
|
|
3619
3714
|
"use strict";
|
|
@@ -3623,7 +3718,7 @@ var init_PaywallWebView = __esm({
|
|
|
3623
3718
|
NativeWebViewComponent = null;
|
|
3624
3719
|
nativeWebViewLookupFailed = false;
|
|
3625
3720
|
webViewEmitter = null;
|
|
3626
|
-
|
|
3721
|
+
styles2 = StyleSheet2.create({
|
|
3627
3722
|
container: { flex: 1 },
|
|
3628
3723
|
webview: { flex: 1, backgroundColor: "transparent" }
|
|
3629
3724
|
});
|
|
@@ -5264,21 +5359,21 @@ var init_usePaywallTracking = __esm({
|
|
|
5264
5359
|
});
|
|
5265
5360
|
|
|
5266
5361
|
// src/domains/paywall/usePaywallActions.ts
|
|
5267
|
-
import { useCallback as useCallback3, useEffect as
|
|
5268
|
-
import { Animated, AppState as AppState3, Dimensions as Dimensions2 } from "react-native";
|
|
5362
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef3, useState as useState2 } from "react";
|
|
5363
|
+
import { Animated as Animated2, AppState as AppState3, Dimensions as Dimensions2 } from "react-native";
|
|
5269
5364
|
function usePaywallActions(placement, paywallConfig, onResult, variantKey, campaignId, openAnim, variantId) {
|
|
5270
5365
|
const [isPurchasing, setIsPurchasing] = useState2(false);
|
|
5271
|
-
const isPurchasingRef =
|
|
5366
|
+
const isPurchasingRef = useRef3(false);
|
|
5272
5367
|
const [isClosing, setIsClosing] = useState2(false);
|
|
5273
|
-
const slideAnim =
|
|
5274
|
-
const presentedAtRef =
|
|
5275
|
-
const closedRef =
|
|
5368
|
+
const slideAnim = useRef3(new Animated2.Value(0)).current;
|
|
5369
|
+
const presentedAtRef = useRef3(Date.now());
|
|
5370
|
+
const closedRef = useRef3(false);
|
|
5276
5371
|
const { trackDismissed, trackProductSelected, trackPurchased } = usePaywallTracking();
|
|
5277
5372
|
const closeWithReason = useCallback3((reason, resultOverride) => {
|
|
5278
5373
|
if (closedRef.current) return;
|
|
5279
5374
|
closedRef.current = true;
|
|
5280
5375
|
const animTarget = openAnim ?? slideAnim;
|
|
5281
|
-
|
|
5376
|
+
Animated2.timing(animTarget, {
|
|
5282
5377
|
toValue: Dimensions2.get("window").height,
|
|
5283
5378
|
duration: 350,
|
|
5284
5379
|
useNativeDriver: true
|
|
@@ -5298,7 +5393,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
5298
5393
|
setIsClosing(true);
|
|
5299
5394
|
closeWithReason("dismissed");
|
|
5300
5395
|
}, [isClosing, closeWithReason]);
|
|
5301
|
-
|
|
5396
|
+
useEffect3(() => {
|
|
5302
5397
|
const sub = AppState3.addEventListener("change", (nextState) => {
|
|
5303
5398
|
if (isPurchasingRef.current) return;
|
|
5304
5399
|
if (nextState === "background" || nextState === "inactive") {
|
|
@@ -5307,7 +5402,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
5307
5402
|
});
|
|
5308
5403
|
return () => sub.remove();
|
|
5309
5404
|
}, [closeWithReason]);
|
|
5310
|
-
|
|
5405
|
+
useEffect3(() => {
|
|
5311
5406
|
const timer = setTimeout(() => {
|
|
5312
5407
|
closeWithReason("timeout");
|
|
5313
5408
|
}, PAYWALL_TIMEOUT_MS);
|
|
@@ -5378,17 +5473,17 @@ var init_usePaywallActions = __esm({
|
|
|
5378
5473
|
});
|
|
5379
5474
|
|
|
5380
5475
|
// src/domains/paywall/usePaywallLoader.ts
|
|
5381
|
-
import { useEffect as
|
|
5476
|
+
import { useEffect as useEffect4, useRef as useRef4, useState as useState3 } from "react";
|
|
5382
5477
|
function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts, variantKey, campaignId, variantId) {
|
|
5383
5478
|
const [error, setError] = useState3(null);
|
|
5384
5479
|
const [paywallConfig, setPaywallConfig] = useState3(null);
|
|
5385
5480
|
const [products, setProducts] = useState3(/* @__PURE__ */ new Map());
|
|
5386
|
-
const preloadedConfigRef =
|
|
5481
|
+
const preloadedConfigRef = useRef4(preloadedConfig);
|
|
5387
5482
|
preloadedConfigRef.current = preloadedConfig;
|
|
5388
|
-
const preloadedProductsRef =
|
|
5483
|
+
const preloadedProductsRef = useRef4(preloadedProducts);
|
|
5389
5484
|
preloadedProductsRef.current = preloadedProducts;
|
|
5390
|
-
const trackingDoneRef =
|
|
5391
|
-
|
|
5485
|
+
const trackingDoneRef = useRef4(false);
|
|
5486
|
+
useEffect4(() => {
|
|
5392
5487
|
if (!visible) {
|
|
5393
5488
|
trackingDoneRef.current = false;
|
|
5394
5489
|
return;
|
|
@@ -5483,28 +5578,28 @@ var init_usePaywallLoader = __esm({
|
|
|
5483
5578
|
});
|
|
5484
5579
|
|
|
5485
5580
|
// src/domains/paywall/PaywallModal.tsx
|
|
5486
|
-
import { useCallback as useCallback4, useEffect as
|
|
5581
|
+
import { useCallback as useCallback4, useEffect as useEffect5, useRef as useRef5, useState as useState4 } from "react";
|
|
5487
5582
|
import {
|
|
5488
|
-
Animated as
|
|
5583
|
+
Animated as Animated3,
|
|
5489
5584
|
Dimensions as Dimensions3,
|
|
5490
5585
|
Easing,
|
|
5491
5586
|
Modal,
|
|
5492
5587
|
Pressable,
|
|
5493
|
-
StyleSheet as
|
|
5588
|
+
StyleSheet as StyleSheet3,
|
|
5494
5589
|
Text,
|
|
5495
|
-
View as
|
|
5590
|
+
View as View3
|
|
5496
5591
|
} from "react-native";
|
|
5497
|
-
import { Fragment, jsx as
|
|
5592
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
5498
5593
|
function ErrorFallback({ description, onRetry, onClose }) {
|
|
5499
5594
|
const overrides = PaywalloClient.getConfig()?.errorStrings;
|
|
5500
5595
|
const title = overrides?.title ?? getSdkString("paywallErrorTitle");
|
|
5501
5596
|
const retryLabel = overrides?.retry ?? getSdkString("paywallRetryButton");
|
|
5502
5597
|
const closeLabel = overrides?.close ?? getSdkString("paywallCloseButton");
|
|
5503
|
-
return /* @__PURE__ */
|
|
5504
|
-
/* @__PURE__ */
|
|
5505
|
-
/* @__PURE__ */
|
|
5506
|
-
/* @__PURE__ */
|
|
5507
|
-
/* @__PURE__ */
|
|
5598
|
+
return /* @__PURE__ */ jsx3(View3, { style: styles3.fallbackContainer, children: /* @__PURE__ */ jsxs2(View3, { style: styles3.fallbackCard, children: [
|
|
5599
|
+
/* @__PURE__ */ jsx3(Text, { style: styles3.fallbackTitle, children: title }),
|
|
5600
|
+
/* @__PURE__ */ jsx3(Text, { style: styles3.fallbackDescription, children: description }),
|
|
5601
|
+
/* @__PURE__ */ jsx3(Pressable, { style: styles3.retryButton, onPress: onRetry, children: /* @__PURE__ */ jsx3(Text, { style: styles3.retryButtonText, children: retryLabel }) }),
|
|
5602
|
+
/* @__PURE__ */ jsx3(Pressable, { style: styles3.closeButton, onPress: onClose, children: /* @__PURE__ */ jsx3(Text, { style: styles3.closeButtonText, children: closeLabel }) })
|
|
5508
5603
|
] }) });
|
|
5509
5604
|
}
|
|
5510
5605
|
function PaywallModal({
|
|
@@ -5527,7 +5622,7 @@ function PaywallModal({
|
|
|
5527
5622
|
variantId
|
|
5528
5623
|
);
|
|
5529
5624
|
const screenHeight = Dimensions3.get("window").height;
|
|
5530
|
-
const openAnim =
|
|
5625
|
+
const openAnim = useRef5(new Animated3.Value(screenHeight)).current;
|
|
5531
5626
|
const [modalVisible, setModalVisible] = useState4(false);
|
|
5532
5627
|
const handleResult = useCallback4((result) => {
|
|
5533
5628
|
setModalVisible(false);
|
|
@@ -5536,7 +5631,9 @@ function PaywallModal({
|
|
|
5536
5631
|
const { isPurchasing, slideAnim, handleClose, handlePurchase, handleRestore } = usePaywallActions(placement, paywallConfig, handleResult, variantKey, campaignId, openAnim, variantId);
|
|
5537
5632
|
const [webViewError, setWebViewError] = useState4(null);
|
|
5538
5633
|
const [retryCount, setRetryCount] = useState4(0);
|
|
5539
|
-
const
|
|
5634
|
+
const [showSkeleton, setShowSkeleton] = useState4(true);
|
|
5635
|
+
const skeletonOpacity = useRef5(new Animated3.Value(1)).current;
|
|
5636
|
+
const retryCountRef = useRef5(0);
|
|
5540
5637
|
const handleWebViewError = useCallback4(
|
|
5541
5638
|
(err) => {
|
|
5542
5639
|
if (retryCountRef.current >= 1) {
|
|
@@ -5552,21 +5649,39 @@ function PaywallModal({
|
|
|
5552
5649
|
retryCountRef.current = 0;
|
|
5553
5650
|
setWebViewError(null);
|
|
5554
5651
|
setRetryCount(0);
|
|
5555
|
-
|
|
5556
|
-
|
|
5652
|
+
setShowSkeleton(true);
|
|
5653
|
+
skeletonOpacity.setValue(1);
|
|
5654
|
+
}, [skeletonOpacity]);
|
|
5655
|
+
const handleWebViewReady = useCallback4(() => {
|
|
5656
|
+
Animated3.timing(skeletonOpacity, {
|
|
5657
|
+
toValue: 0,
|
|
5658
|
+
duration: 250,
|
|
5659
|
+
easing: Easing.out(Easing.cubic),
|
|
5660
|
+
useNativeDriver: true
|
|
5661
|
+
}).start(() => setShowSkeleton(false));
|
|
5662
|
+
}, [skeletonOpacity]);
|
|
5663
|
+
useEffect5(() => {
|
|
5664
|
+
if (!visible || !showSkeleton) return;
|
|
5665
|
+
const timer = setTimeout(handleWebViewReady, 8e3);
|
|
5666
|
+
return () => clearTimeout(timer);
|
|
5667
|
+
}, [visible, showSkeleton, handleWebViewReady]);
|
|
5668
|
+
useEffect5(() => {
|
|
5557
5669
|
if (visible) {
|
|
5558
5670
|
setModalVisible(true);
|
|
5671
|
+
setShowSkeleton(true);
|
|
5672
|
+
skeletonOpacity.setValue(1);
|
|
5559
5673
|
openAnim.setValue(Dimensions3.get("window").height);
|
|
5560
|
-
|
|
5674
|
+
Animated3.timing(openAnim, {
|
|
5561
5675
|
toValue: 0,
|
|
5562
5676
|
duration: 550,
|
|
5563
5677
|
easing: Easing.out(Easing.cubic),
|
|
5564
5678
|
useNativeDriver: true
|
|
5565
5679
|
}).start();
|
|
5566
5680
|
}
|
|
5567
|
-
}, [visible, openAnim]);
|
|
5681
|
+
}, [visible, openAnim, skeletonOpacity]);
|
|
5568
5682
|
if (!modalVisible && !visible) return null;
|
|
5569
|
-
|
|
5683
|
+
const skeletonBackground = paywallConfig && "craftData" in paywallConfig.config ? extractFirstPageBackground(paywallConfig.config.craftData) : "#FFFFFF";
|
|
5684
|
+
return /* @__PURE__ */ jsx3(
|
|
5570
5685
|
Modal,
|
|
5571
5686
|
{
|
|
5572
5687
|
visible: modalVisible,
|
|
@@ -5575,16 +5690,16 @@ function PaywallModal({
|
|
|
5575
5690
|
onRequestClose: handleClose,
|
|
5576
5691
|
transparent: true,
|
|
5577
5692
|
statusBarTranslucent: true,
|
|
5578
|
-
children: /* @__PURE__ */
|
|
5579
|
-
error && /* @__PURE__ */
|
|
5580
|
-
!error && paywallConfig && "craftData" in paywallConfig.config && /* @__PURE__ */
|
|
5693
|
+
children: /* @__PURE__ */ jsx3(View3, { style: styles3.overlay, children: /* @__PURE__ */ jsx3(Animated3.View, { style: [styles3.animatedContainer, { transform: [{ translateY: openAnim }] }], children: /* @__PURE__ */ jsxs2(View3, { style: styles3.container, children: [
|
|
5694
|
+
error && /* @__PURE__ */ jsx3(View3, { style: styles3.errorContainer, children: /* @__PURE__ */ jsx3(Text, { style: styles3.errorText, children: error.message }) }),
|
|
5695
|
+
!error && paywallConfig && "craftData" in paywallConfig.config && /* @__PURE__ */ jsx3(Fragment, { children: webViewError ? /* @__PURE__ */ jsx3(
|
|
5581
5696
|
ErrorFallback,
|
|
5582
5697
|
{
|
|
5583
5698
|
description: webViewError.description,
|
|
5584
5699
|
onRetry: handleRetry,
|
|
5585
5700
|
onClose: handleClose
|
|
5586
5701
|
}
|
|
5587
|
-
) : /* @__PURE__ */
|
|
5702
|
+
) : /* @__PURE__ */ jsx3(
|
|
5588
5703
|
PaywallWebView,
|
|
5589
5704
|
{
|
|
5590
5705
|
paywallId: paywallConfig.id,
|
|
@@ -5593,27 +5708,38 @@ function PaywallModal({
|
|
|
5593
5708
|
primaryProductId: paywallConfig.primaryProductId,
|
|
5594
5709
|
secondaryProductId: paywallConfig.secondaryProductId,
|
|
5595
5710
|
isPurchasing,
|
|
5711
|
+
onReady: handleWebViewReady,
|
|
5596
5712
|
onClose: handleClose,
|
|
5597
5713
|
onPurchase: handlePurchase,
|
|
5598
5714
|
onRestore: handleRestore,
|
|
5599
5715
|
onError: handleWebViewError
|
|
5600
5716
|
},
|
|
5601
5717
|
retryCount
|
|
5602
|
-
) })
|
|
5718
|
+
) }),
|
|
5719
|
+
showSkeleton && !error && !webViewError && /* @__PURE__ */ jsx3(
|
|
5720
|
+
Animated3.View,
|
|
5721
|
+
{
|
|
5722
|
+
style: [StyleSheet3.absoluteFill, { opacity: skeletonOpacity }],
|
|
5723
|
+
pointerEvents: "none",
|
|
5724
|
+
children: /* @__PURE__ */ jsx3(PaywallSkeleton, { backgroundColor: skeletonBackground })
|
|
5725
|
+
}
|
|
5726
|
+
)
|
|
5603
5727
|
] }) }) })
|
|
5604
5728
|
}
|
|
5605
5729
|
);
|
|
5606
5730
|
}
|
|
5607
|
-
var
|
|
5731
|
+
var styles3;
|
|
5608
5732
|
var init_PaywallModal = __esm({
|
|
5609
5733
|
"src/domains/paywall/PaywallModal.tsx"() {
|
|
5610
5734
|
"use strict";
|
|
5611
5735
|
init_PaywalloClient();
|
|
5612
5736
|
init_localization();
|
|
5737
|
+
init_extractFirstPageBackground();
|
|
5738
|
+
init_PaywallSkeleton();
|
|
5613
5739
|
init_PaywallWebView();
|
|
5614
5740
|
init_usePaywallActions();
|
|
5615
5741
|
init_usePaywallLoader();
|
|
5616
|
-
|
|
5742
|
+
styles3 = StyleSheet3.create({
|
|
5617
5743
|
overlay: { flex: 1, backgroundColor: "rgba(0,0,0,0.3)" },
|
|
5618
5744
|
animatedContainer: { flex: 1, backgroundColor: "#fff" },
|
|
5619
5745
|
container: { flex: 1, backgroundColor: "#fff" },
|
|
@@ -5669,13 +5795,176 @@ var init_PaywallModal = __esm({
|
|
|
5669
5795
|
}
|
|
5670
5796
|
});
|
|
5671
5797
|
|
|
5798
|
+
// src/domains/paywall/PaywallPreloadService.ts
|
|
5799
|
+
var PRELOAD_TTL_MS, STALE_THRESHOLD, PaywallPreloadService, paywallPreloadService;
|
|
5800
|
+
var init_PaywallPreloadService = __esm({
|
|
5801
|
+
"src/domains/paywall/PaywallPreloadService.ts"() {
|
|
5802
|
+
"use strict";
|
|
5803
|
+
init_PaywalloClient();
|
|
5804
|
+
init_IAPService();
|
|
5805
|
+
init_PaywallError();
|
|
5806
|
+
PRELOAD_TTL_MS = 5 * 60 * 1e3;
|
|
5807
|
+
STALE_THRESHOLD = 0.75;
|
|
5808
|
+
PaywallPreloadService = class {
|
|
5809
|
+
constructor() {
|
|
5810
|
+
this.preloaded = /* @__PURE__ */ new Map();
|
|
5811
|
+
this.activePreloads = /* @__PURE__ */ new Map();
|
|
5812
|
+
this.apiClientRef = null;
|
|
5813
|
+
}
|
|
5814
|
+
async preload(apiClient, placement) {
|
|
5815
|
+
this.apiClientRef = apiClient;
|
|
5816
|
+
const existing = this.activePreloads.get(placement);
|
|
5817
|
+
if (existing) return existing;
|
|
5818
|
+
const promise = this.doPreload(apiClient, placement);
|
|
5819
|
+
this.activePreloads.set(placement, promise);
|
|
5820
|
+
try {
|
|
5821
|
+
return await promise;
|
|
5822
|
+
} finally {
|
|
5823
|
+
this.activePreloads.delete(placement);
|
|
5824
|
+
}
|
|
5825
|
+
}
|
|
5826
|
+
async preloadMany(apiClient, placements) {
|
|
5827
|
+
this.apiClientRef = apiClient;
|
|
5828
|
+
if (placements.length === 0) return;
|
|
5829
|
+
const debug = PaywalloClient.getConfig()?.debug;
|
|
5830
|
+
if (debug) console.log(`[Paywallo PRELOAD] paywalls: ${placements.length} placements`);
|
|
5831
|
+
for (let i = 0; i < placements.length; i++) {
|
|
5832
|
+
if (i > 0) await new Promise((r) => setTimeout(r, 200));
|
|
5833
|
+
void this.preload(apiClient, placements[i]).catch((err) => {
|
|
5834
|
+
if (debug) console.log(`[Paywallo PRELOAD] paywall failed ${placements[i]}:`, err);
|
|
5835
|
+
});
|
|
5836
|
+
}
|
|
5837
|
+
}
|
|
5838
|
+
getPreloaded(placement) {
|
|
5839
|
+
const cached2 = this.preloaded.get(placement);
|
|
5840
|
+
if (!cached2) return null;
|
|
5841
|
+
const age = Date.now() - cached2.preloadedAt;
|
|
5842
|
+
if (age >= PRELOAD_TTL_MS) {
|
|
5843
|
+
this.preloaded.delete(placement);
|
|
5844
|
+
return null;
|
|
5845
|
+
}
|
|
5846
|
+
if (age >= PRELOAD_TTL_MS * STALE_THRESHOLD && this.apiClientRef) {
|
|
5847
|
+
void this.preload(this.apiClientRef, placement).catch(() => {
|
|
5848
|
+
});
|
|
5849
|
+
}
|
|
5850
|
+
return { config: cached2.config, products: new Map(cached2.products) };
|
|
5851
|
+
}
|
|
5852
|
+
isPreloaded(placement) {
|
|
5853
|
+
return this.getPreloaded(placement) !== null;
|
|
5854
|
+
}
|
|
5855
|
+
clear() {
|
|
5856
|
+
this.preloaded.clear();
|
|
5857
|
+
this.activePreloads.clear();
|
|
5858
|
+
}
|
|
5859
|
+
async doPreload(apiClient, placement) {
|
|
5860
|
+
try {
|
|
5861
|
+
const config = await apiClient.getPaywall(placement);
|
|
5862
|
+
if (!config) {
|
|
5863
|
+
return {
|
|
5864
|
+
success: false,
|
|
5865
|
+
error: new PaywallError(
|
|
5866
|
+
PAYWALL_ERROR_CODES.NOT_FOUND,
|
|
5867
|
+
`Paywall not found for placement: ${placement}`
|
|
5868
|
+
)
|
|
5869
|
+
};
|
|
5870
|
+
}
|
|
5871
|
+
const products = await this.loadProductsFor(config);
|
|
5872
|
+
this.preloaded.set(placement, { config, products, preloadedAt: Date.now() });
|
|
5873
|
+
if (PaywalloClient.getConfig()?.debug) {
|
|
5874
|
+
console.log(`[Paywallo PRELOAD] paywall cached \u2014 placement: ${placement}`);
|
|
5875
|
+
}
|
|
5876
|
+
return { success: true };
|
|
5877
|
+
} catch (error) {
|
|
5878
|
+
return {
|
|
5879
|
+
success: false,
|
|
5880
|
+
error: error instanceof Error ? error : new PaywallError(PAYWALL_ERROR_CODES.LOAD_FAILED, String(error))
|
|
5881
|
+
};
|
|
5882
|
+
}
|
|
5883
|
+
}
|
|
5884
|
+
async loadProductsFor(config) {
|
|
5885
|
+
const productIds = [];
|
|
5886
|
+
if (config.primaryProductId) productIds.push(config.primaryProductId);
|
|
5887
|
+
if (config.secondaryProductId) productIds.push(config.secondaryProductId);
|
|
5888
|
+
if (productIds.length === 0) return /* @__PURE__ */ new Map();
|
|
5889
|
+
try {
|
|
5890
|
+
const loaded = await getIAPService().loadProducts(productIds);
|
|
5891
|
+
const map = /* @__PURE__ */ new Map();
|
|
5892
|
+
for (const p of loaded) map.set(p.productId, p);
|
|
5893
|
+
return map;
|
|
5894
|
+
} catch (err) {
|
|
5895
|
+
if (PaywalloClient.getConfig()?.debug) {
|
|
5896
|
+
console.log("[Paywallo PRELOAD] products failed, caching config only:", err);
|
|
5897
|
+
}
|
|
5898
|
+
return /* @__PURE__ */ new Map();
|
|
5899
|
+
}
|
|
5900
|
+
}
|
|
5901
|
+
};
|
|
5902
|
+
paywallPreloadService = new PaywallPreloadService();
|
|
5903
|
+
}
|
|
5904
|
+
});
|
|
5905
|
+
|
|
5906
|
+
// src/domains/paywall/PaywallWebViewPrewarmer.tsx
|
|
5907
|
+
import { useEffect as useEffect6, useMemo as useMemo2, useState as useState5 } from "react";
|
|
5908
|
+
import { requireNativeComponent as requireNativeComponent2, StyleSheet as StyleSheet4, View as View4 } from "react-native";
|
|
5909
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
5910
|
+
function getNativeWebView2() {
|
|
5911
|
+
if (NativeWebViewComponent2) return NativeWebViewComponent2;
|
|
5912
|
+
if (nativeLookupFailed) return null;
|
|
5913
|
+
try {
|
|
5914
|
+
NativeWebViewComponent2 = requireNativeComponent2("PaywalloWebView");
|
|
5915
|
+
return NativeWebViewComponent2;
|
|
5916
|
+
} catch {
|
|
5917
|
+
nativeLookupFailed = true;
|
|
5918
|
+
return null;
|
|
5919
|
+
}
|
|
5920
|
+
}
|
|
5921
|
+
function PaywallWebViewPrewarmer({
|
|
5922
|
+
webUrl,
|
|
5923
|
+
durationMs = DEFAULT_DURATION_MS
|
|
5924
|
+
}) {
|
|
5925
|
+
const NativeWebView = useMemo2(() => getNativeWebView2(), []);
|
|
5926
|
+
const [mounted, setMounted] = useState5(true);
|
|
5927
|
+
useEffect6(() => {
|
|
5928
|
+
if (!NativeWebView) return;
|
|
5929
|
+
const timer = setTimeout(() => setMounted(false), durationMs);
|
|
5930
|
+
return () => clearTimeout(timer);
|
|
5931
|
+
}, [NativeWebView, durationMs]);
|
|
5932
|
+
if (!NativeWebView || !mounted) return null;
|
|
5933
|
+
const preheatUrl = `${webUrl}/paywall/preheat`;
|
|
5934
|
+
if (PaywalloClient.getConfig()?.debug) {
|
|
5935
|
+
console.log(`[Paywallo PREWARM] mounting hidden WebView: ${preheatUrl}`);
|
|
5936
|
+
}
|
|
5937
|
+
return /* @__PURE__ */ jsx4(View4, { pointerEvents: "none", style: styles4.hidden, children: /* @__PURE__ */ jsx4(NativeWebView, { sourceUrl: preheatUrl, style: styles4.fill }) });
|
|
5938
|
+
}
|
|
5939
|
+
var NativeWebViewComponent2, nativeLookupFailed, DEFAULT_DURATION_MS, styles4;
|
|
5940
|
+
var init_PaywallWebViewPrewarmer = __esm({
|
|
5941
|
+
"src/domains/paywall/PaywallWebViewPrewarmer.tsx"() {
|
|
5942
|
+
"use strict";
|
|
5943
|
+
init_PaywalloClient();
|
|
5944
|
+
NativeWebViewComponent2 = null;
|
|
5945
|
+
nativeLookupFailed = false;
|
|
5946
|
+
DEFAULT_DURATION_MS = 60 * 1e3;
|
|
5947
|
+
styles4 = StyleSheet4.create({
|
|
5948
|
+
hidden: {
|
|
5949
|
+
height: 1,
|
|
5950
|
+
left: -9999,
|
|
5951
|
+
opacity: 0,
|
|
5952
|
+
position: "absolute",
|
|
5953
|
+
top: -9999,
|
|
5954
|
+
width: 1
|
|
5955
|
+
},
|
|
5956
|
+
fill: { flex: 1 }
|
|
5957
|
+
});
|
|
5958
|
+
}
|
|
5959
|
+
});
|
|
5960
|
+
|
|
5672
5961
|
// src/domains/paywall/usePaywallSession.ts
|
|
5673
|
-
import { useCallback as useCallback5, useEffect as
|
|
5962
|
+
import { useCallback as useCallback5, useEffect as useEffect7, useRef as useRef6 } from "react";
|
|
5674
5963
|
function usePaywallSession(options) {
|
|
5675
|
-
const closedRef =
|
|
5676
|
-
const optsRef =
|
|
5964
|
+
const closedRef = useRef6(false);
|
|
5965
|
+
const optsRef = useRef6(options);
|
|
5677
5966
|
optsRef.current = options;
|
|
5678
|
-
|
|
5967
|
+
useEffect7(() => {
|
|
5679
5968
|
if (!options) return;
|
|
5680
5969
|
closedRef.current = false;
|
|
5681
5970
|
startHeartbeat({
|
|
@@ -5719,11 +6008,11 @@ var init_usePaywallSession = __esm({
|
|
|
5719
6008
|
});
|
|
5720
6009
|
|
|
5721
6010
|
// src/domains/paywall/usePaywallPresenter.ts
|
|
5722
|
-
import { useCallback as useCallback6, useEffect as
|
|
6011
|
+
import { useCallback as useCallback6, useEffect as useEffect8, useRef as useRef7, useState as useState6 } from "react";
|
|
5723
6012
|
function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
5724
|
-
const [showingPreloadedWebView, setShowingPreloadedWebView] =
|
|
5725
|
-
const resolverRef =
|
|
5726
|
-
const presentedAtRef =
|
|
6013
|
+
const [showingPreloadedWebView, setShowingPreloadedWebView] = useState6(false);
|
|
6014
|
+
const resolverRef = useRef7(null);
|
|
6015
|
+
const presentedAtRef = useRef7(Date.now());
|
|
5727
6016
|
const sessionOpts = showingPreloadedWebView && preloadedWebView ? {
|
|
5728
6017
|
placement: preloadedWebView.placement,
|
|
5729
6018
|
paywallId: preloadedWebView.paywallId,
|
|
@@ -5733,7 +6022,7 @@ function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
|
5733
6022
|
...preloadedWebView.campaignId && { campaignId: preloadedWebView.campaignId }
|
|
5734
6023
|
} : null;
|
|
5735
6024
|
const { markClosed } = usePaywallSession(sessionOpts);
|
|
5736
|
-
|
|
6025
|
+
useEffect8(() => {
|
|
5737
6026
|
return () => {
|
|
5738
6027
|
if (resolverRef.current) {
|
|
5739
6028
|
resolverRef.current({ presented: false, purchased: false, cancelled: true, restored: false });
|
|
@@ -5820,7 +6109,9 @@ var init_paywall = __esm({
|
|
|
5820
6109
|
init_PaywallError();
|
|
5821
6110
|
init_PaywallErrorBoundary();
|
|
5822
6111
|
init_PaywallModal();
|
|
6112
|
+
init_PaywallPreloadService();
|
|
5823
6113
|
init_PaywallWebView();
|
|
6114
|
+
init_PaywallWebViewPrewarmer();
|
|
5824
6115
|
init_usePaywallPresenter();
|
|
5825
6116
|
init_usePaywallTracking();
|
|
5826
6117
|
}
|
|
@@ -8392,6 +8683,7 @@ async function doFullReset(state) {
|
|
|
8392
8683
|
offlineQueue.dispose();
|
|
8393
8684
|
networkMonitor.dispose();
|
|
8394
8685
|
campaignGateService.clearPreloaded();
|
|
8686
|
+
paywallPreloadService.clear();
|
|
8395
8687
|
await notificationsManager.invalidateLocalToken().catch(() => void 0);
|
|
8396
8688
|
notificationsManager.destroy();
|
|
8397
8689
|
deepLinkAttributionCapture.stop();
|
|
@@ -8426,6 +8718,7 @@ var init_PaywalloLifecycle = __esm({
|
|
|
8426
8718
|
init_identity();
|
|
8427
8719
|
init_DeepLinkAttributionCapture();
|
|
8428
8720
|
init_notifications();
|
|
8721
|
+
init_paywall();
|
|
8429
8722
|
init_session();
|
|
8430
8723
|
init_SubscriptionCache();
|
|
8431
8724
|
init_network();
|
|
@@ -8729,6 +9022,15 @@ var init_PaywalloClient = __esm({
|
|
|
8729
9022
|
isPreloaded(placement) {
|
|
8730
9023
|
return campaignGateService.getPreloadedCampaign(placement) !== null;
|
|
8731
9024
|
}
|
|
9025
|
+
async preloadPaywall(placement) {
|
|
9026
|
+
return paywallPreloadService.preload(this.getApiClientOrThrow(), placement);
|
|
9027
|
+
}
|
|
9028
|
+
async preloadPaywalls(placements) {
|
|
9029
|
+
return paywallPreloadService.preloadMany(this.getApiClientOrThrow(), placements);
|
|
9030
|
+
}
|
|
9031
|
+
isPaywallPreloaded(placement) {
|
|
9032
|
+
return paywallPreloadService.isPreloaded(placement);
|
|
9033
|
+
}
|
|
8732
9034
|
getAutoPreloadedPlacement() {
|
|
8733
9035
|
return this.state.autoPreloadedPlacement;
|
|
8734
9036
|
}
|
|
@@ -8943,7 +9245,7 @@ init_session();
|
|
|
8943
9245
|
init_PaywalloError();
|
|
8944
9246
|
|
|
8945
9247
|
// src/hooks/useOfferingPurchase.ts
|
|
8946
|
-
import { useCallback as useCallback7, useState as
|
|
9248
|
+
import { useCallback as useCallback7, useState as useState7 } from "react";
|
|
8947
9249
|
|
|
8948
9250
|
// src/domains/plan/invalidateCache.ts
|
|
8949
9251
|
async function invalidatePlanCache() {
|
|
@@ -8956,7 +9258,7 @@ async function invalidatePlanCache() {
|
|
|
8956
9258
|
|
|
8957
9259
|
// src/hooks/useOfferingPurchase.ts
|
|
8958
9260
|
function useOfferingPurchase() {
|
|
8959
|
-
const [state, setState] =
|
|
9261
|
+
const [state, setState] = useState7("idle");
|
|
8960
9262
|
const purchase = useCallback7(async (productId) => {
|
|
8961
9263
|
setState("purchasing");
|
|
8962
9264
|
try {
|
|
@@ -8981,7 +9283,7 @@ function useOfferingPurchase() {
|
|
|
8981
9283
|
}
|
|
8982
9284
|
|
|
8983
9285
|
// src/hooks/useOfferings.ts
|
|
8984
|
-
import { useCallback as useCallback8, useEffect as
|
|
9286
|
+
import { useCallback as useCallback8, useEffect as useEffect9, useState as useState8 } from "react";
|
|
8985
9287
|
async function getOfferingService() {
|
|
8986
9288
|
try {
|
|
8987
9289
|
const mod = await Promise.resolve().then(() => (init_OfferingService(), OfferingService_exports));
|
|
@@ -8991,8 +9293,8 @@ async function getOfferingService() {
|
|
|
8991
9293
|
}
|
|
8992
9294
|
}
|
|
8993
9295
|
function useOfferings(ids) {
|
|
8994
|
-
const [offerings, setOfferings] =
|
|
8995
|
-
const [isLoading, setIsLoading] =
|
|
9296
|
+
const [offerings, setOfferings] = useState8([]);
|
|
9297
|
+
const [isLoading, setIsLoading] = useState8(true);
|
|
8996
9298
|
const idsKey = ids?.join(",") ?? "";
|
|
8997
9299
|
const fetchOfferings = useCallback8(async () => {
|
|
8998
9300
|
setIsLoading(true);
|
|
@@ -9010,7 +9312,7 @@ function useOfferings(ids) {
|
|
|
9010
9312
|
setIsLoading(false);
|
|
9011
9313
|
}
|
|
9012
9314
|
}, [idsKey]);
|
|
9013
|
-
|
|
9315
|
+
useEffect9(() => {
|
|
9014
9316
|
void fetchOfferings();
|
|
9015
9317
|
}, [fetchOfferings]);
|
|
9016
9318
|
return { offerings, isLoading };
|
|
@@ -9047,10 +9349,10 @@ function usePaywallo() {
|
|
|
9047
9349
|
}
|
|
9048
9350
|
|
|
9049
9351
|
// src/hooks/usePlanPurchase.ts
|
|
9050
|
-
import { useCallback as useCallback10, useState as
|
|
9352
|
+
import { useCallback as useCallback10, useState as useState9 } from "react";
|
|
9051
9353
|
function usePlanPurchase() {
|
|
9052
|
-
const [state, setState] =
|
|
9053
|
-
const [error, setError] =
|
|
9354
|
+
const [state, setState] = useState9("idle");
|
|
9355
|
+
const [error, setError] = useState9(null);
|
|
9054
9356
|
const purchase = useCallback10(async (productId) => {
|
|
9055
9357
|
setState("purchasing");
|
|
9056
9358
|
setError(null);
|
|
@@ -9103,7 +9405,7 @@ function usePlanPurchase() {
|
|
|
9103
9405
|
}
|
|
9104
9406
|
|
|
9105
9407
|
// src/hooks/usePlans.ts
|
|
9106
|
-
import { useCallback as useCallback11, useEffect as
|
|
9408
|
+
import { useCallback as useCallback11, useEffect as useEffect10, useState as useState10 } from "react";
|
|
9107
9409
|
async function getPlanService() {
|
|
9108
9410
|
try {
|
|
9109
9411
|
const mod = await Promise.resolve().then(() => (init_PlanService(), PlanService_exports));
|
|
@@ -9113,10 +9415,10 @@ async function getPlanService() {
|
|
|
9113
9415
|
}
|
|
9114
9416
|
}
|
|
9115
9417
|
function usePlans() {
|
|
9116
|
-
const [allPlans, setAllPlans] =
|
|
9117
|
-
const [currentPlan, setCurrentPlan] =
|
|
9118
|
-
const [isLoading, setIsLoading] =
|
|
9119
|
-
const [error, setError] =
|
|
9418
|
+
const [allPlans, setAllPlans] = useState10([]);
|
|
9419
|
+
const [currentPlan, setCurrentPlan] = useState10(null);
|
|
9420
|
+
const [isLoading, setIsLoading] = useState10(true);
|
|
9421
|
+
const [error, setError] = useState10(null);
|
|
9120
9422
|
const fetchPlans = useCallback11(async (forceRefresh = false) => {
|
|
9121
9423
|
setIsLoading(true);
|
|
9122
9424
|
setError(null);
|
|
@@ -9141,14 +9443,14 @@ function usePlans() {
|
|
|
9141
9443
|
const refresh = useCallback11(() => {
|
|
9142
9444
|
return fetchPlans(true);
|
|
9143
9445
|
}, [fetchPlans]);
|
|
9144
|
-
|
|
9446
|
+
useEffect10(() => {
|
|
9145
9447
|
void fetchPlans(false);
|
|
9146
9448
|
}, [fetchPlans]);
|
|
9147
9449
|
return { currentPlan, allPlans, isLoading, error, refresh };
|
|
9148
9450
|
}
|
|
9149
9451
|
|
|
9150
9452
|
// src/hooks/useProducts.ts
|
|
9151
|
-
import { useCallback as useCallback12, useEffect as
|
|
9453
|
+
import { useCallback as useCallback12, useEffect as useEffect11, useState as useState11 } from "react";
|
|
9152
9454
|
|
|
9153
9455
|
// src/utils/productMappers.ts
|
|
9154
9456
|
function mapToIAPProduct(product) {
|
|
@@ -9187,10 +9489,10 @@ function mapToFormattedProduct(product) {
|
|
|
9187
9489
|
|
|
9188
9490
|
// src/hooks/useProducts.ts
|
|
9189
9491
|
function useProducts(initialProductIds) {
|
|
9190
|
-
const [products, setProducts] =
|
|
9191
|
-
const [formattedProducts, setFormattedProducts] =
|
|
9192
|
-
const [isLoading, setIsLoading] =
|
|
9193
|
-
const [error, setError] =
|
|
9492
|
+
const [products, setProducts] = useState11([]);
|
|
9493
|
+
const [formattedProducts, setFormattedProducts] = useState11([]);
|
|
9494
|
+
const [isLoading, setIsLoading] = useState11(false);
|
|
9495
|
+
const [error, setError] = useState11(null);
|
|
9194
9496
|
const loadProducts = useCallback12(async (productIds) => {
|
|
9195
9497
|
setIsLoading(true);
|
|
9196
9498
|
setError(null);
|
|
@@ -9205,7 +9507,7 @@ function useProducts(initialProductIds) {
|
|
|
9205
9507
|
setIsLoading(false);
|
|
9206
9508
|
}
|
|
9207
9509
|
}, []);
|
|
9208
|
-
|
|
9510
|
+
useEffect11(() => {
|
|
9209
9511
|
if (initialProductIds && initialProductIds.length > 0) {
|
|
9210
9512
|
void loadProducts(initialProductIds);
|
|
9211
9513
|
}
|
|
@@ -9251,13 +9553,13 @@ function useProducts(initialProductIds) {
|
|
|
9251
9553
|
}
|
|
9252
9554
|
|
|
9253
9555
|
// src/hooks/usePurchase.ts
|
|
9254
|
-
import { useCallback as useCallback13, useState as
|
|
9556
|
+
import { useCallback as useCallback13, useState as useState12 } from "react";
|
|
9255
9557
|
function toIAPPurchase(p) {
|
|
9256
9558
|
return { productId: p.productId, transactionId: p.transactionId, transactionDate: p.transactionDate, transactionReceipt: p.receipt };
|
|
9257
9559
|
}
|
|
9258
9560
|
function usePurchase() {
|
|
9259
|
-
const [state, setState] =
|
|
9260
|
-
const [error, setError] =
|
|
9561
|
+
const [state, setState] = useState12("idle");
|
|
9562
|
+
const [error, setError] = useState12(null);
|
|
9261
9563
|
const purchase = useCallback13(async (productId) => {
|
|
9262
9564
|
setState("purchasing");
|
|
9263
9565
|
setError(null);
|
|
@@ -9305,13 +9607,13 @@ function usePurchase() {
|
|
|
9305
9607
|
}
|
|
9306
9608
|
|
|
9307
9609
|
// src/hooks/useSubscription.ts
|
|
9308
|
-
import { useCallback as useCallback14, useEffect as
|
|
9610
|
+
import { useCallback as useCallback14, useEffect as useEffect12, useState as useState13 } from "react";
|
|
9309
9611
|
init_SubscriptionManager();
|
|
9310
9612
|
var EMPTY_ENTITLEMENTS = [];
|
|
9311
9613
|
function useSubscription() {
|
|
9312
|
-
const [status, setStatus] =
|
|
9313
|
-
const [isLoading, setIsLoading] =
|
|
9314
|
-
const [error, setError] =
|
|
9614
|
+
const [status, setStatus] = useState13(null);
|
|
9615
|
+
const [isLoading, setIsLoading] = useState13(true);
|
|
9616
|
+
const [error, setError] = useState13(null);
|
|
9315
9617
|
const refresh = useCallback14(async () => {
|
|
9316
9618
|
setIsLoading(true);
|
|
9317
9619
|
setError(null);
|
|
@@ -9338,7 +9640,7 @@ function useSubscription() {
|
|
|
9338
9640
|
setIsLoading(false);
|
|
9339
9641
|
}
|
|
9340
9642
|
}, []);
|
|
9341
|
-
|
|
9643
|
+
useEffect12(() => {
|
|
9342
9644
|
void subscriptionManager.getSubscriptionStatus().then((s) => {
|
|
9343
9645
|
setStatus(s);
|
|
9344
9646
|
setIsLoading(false);
|
|
@@ -9366,94 +9668,288 @@ function useSubscription() {
|
|
|
9366
9668
|
}
|
|
9367
9669
|
|
|
9368
9670
|
// src/PaywalloProvider.tsx
|
|
9369
|
-
import { useCallback as useCallback19, useEffect as
|
|
9370
|
-
import { Animated as
|
|
9671
|
+
import { useCallback as useCallback19, useEffect as useEffect14, useLayoutEffect, useMemo as useMemo3, useRef as useRef11, useState as useState17 } from "react";
|
|
9672
|
+
import { Animated as Animated4, Dimensions as Dimensions5, Easing as Easing2, StyleSheet as StyleSheet5 } from "react-native";
|
|
9371
9673
|
init_PaywalloClient();
|
|
9372
|
-
init_SecureStorage();
|
|
9373
9674
|
init_NativeStorage();
|
|
9675
|
+
init_SecureStorage();
|
|
9374
9676
|
init_campaign();
|
|
9375
9677
|
init_paywall();
|
|
9376
9678
|
init_paywall();
|
|
9377
9679
|
init_paywall();
|
|
9378
9680
|
init_paywall();
|
|
9379
|
-
|
|
9380
|
-
|
|
9681
|
+
init_paywall();
|
|
9682
|
+
init_paywall();
|
|
9381
9683
|
|
|
9382
|
-
// src/
|
|
9383
|
-
|
|
9684
|
+
// src/domains/paywall/SuperwallAutoBridge.ts
|
|
9685
|
+
init_PaywalloClient();
|
|
9384
9686
|
|
|
9385
|
-
// src/utils/
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9687
|
+
// src/core/utils/eventId.ts
|
|
9688
|
+
function hashString(input) {
|
|
9689
|
+
let h1 = 3735928559;
|
|
9690
|
+
let h2 = 1103547991;
|
|
9691
|
+
for (let i = 0; i < input.length; i++) {
|
|
9692
|
+
const ch = input.charCodeAt(i);
|
|
9693
|
+
h1 = Math.imul(h1 ^ ch, 2654435769);
|
|
9694
|
+
h2 = Math.imul(h2 ^ ch, 1598716949);
|
|
9392
9695
|
}
|
|
9696
|
+
h1 = Math.imul(h1 ^ h1 >>> 16, 73244475);
|
|
9697
|
+
h1 ^= Math.imul(h2 ^ h2 >>> 13, 351452291);
|
|
9698
|
+
h2 = Math.imul(h2 ^ h2 >>> 16, 73244475);
|
|
9699
|
+
h2 ^= Math.imul(h1 ^ h1 >>> 13, 351452291);
|
|
9700
|
+
const toHex = (n) => (n >>> 0).toString(16).padStart(8, "0");
|
|
9701
|
+
return toHex(h1) + toHex(h2);
|
|
9393
9702
|
}
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
}
|
|
9703
|
+
function buildDeterministicEventId(parts) {
|
|
9704
|
+
const raw = hashString(parts.join("|"));
|
|
9705
|
+
const p1 = raw.slice(0, 8);
|
|
9706
|
+
const p2 = raw.slice(8, 12);
|
|
9707
|
+
const p3 = "4" + raw.slice(13, 16);
|
|
9708
|
+
const p4 = (parseInt(raw[16], 16) & 3 | 8).toString(16) + raw.slice(17, 20);
|
|
9709
|
+
const p5 = raw.padEnd(32, "0").slice(20, 32);
|
|
9710
|
+
return `${p1}-${p2}-${p3}-${p4}-${p5}`;
|
|
9402
9711
|
}
|
|
9403
9712
|
|
|
9404
|
-
// src/
|
|
9405
|
-
var
|
|
9406
|
-
var
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9413
|
-
|
|
9414
|
-
|
|
9415
|
-
didRunRef.current = true;
|
|
9416
|
-
void (async () => {
|
|
9417
|
-
const sessionId = getSessionId();
|
|
9418
|
-
const appVersion = getAppVersion2();
|
|
9419
|
-
const deviceType = await detectPlatform3();
|
|
9420
|
-
const osVersion = await detectOsVersion();
|
|
9421
|
-
if (debug) console.log("[Paywallo EVENTS] computed device context", { deviceType, osVersion, appVersion, sessionId, hasSessionId: !!sessionId });
|
|
9422
|
-
try {
|
|
9423
|
-
if (debug) console.log("[Paywallo EVENTS] checking install \u2014 about to read FIRST_SEEN_KEY");
|
|
9424
|
-
const firstSeen = await storageGet(FIRST_SEEN_KEY);
|
|
9425
|
-
if (!firstSeen) {
|
|
9426
|
-
await emitLifecycle({ type: "install", device_type: deviceType, os_version: osVersion, app_version: appVersion, ...sessionId ? { session_id: sessionId } : {} }, "critical");
|
|
9427
|
-
await storageSet(FIRST_SEEN_KEY, (/* @__PURE__ */ new Date()).toISOString());
|
|
9428
|
-
if (debug) console.log("[Paywallo EVENTS] install event emitted (first time)");
|
|
9429
|
-
if (debug) console.log("[Paywallo EVENTS] lifecycle install emitted");
|
|
9430
|
-
} else {
|
|
9431
|
-
if (debug) console.log("[Paywallo EVENTS] install skipped \u2014 firstSeen already exists", { firstSeen });
|
|
9432
|
-
}
|
|
9433
|
-
} catch (err) {
|
|
9434
|
-
if (debug) console.log("[Paywallo EVENTS] lifecycle install check failed", err);
|
|
9435
|
-
}
|
|
9436
|
-
try {
|
|
9437
|
-
if (debug) console.log("[Paywallo EVENTS] emitting cold_start");
|
|
9438
|
-
await emitLifecycle({ type: "cold_start", app_version: appVersion, device_type: deviceType, os_version: osVersion, ...sessionId ? { session_id: sessionId } : {} }, "normal");
|
|
9439
|
-
if (debug) console.log("[Paywallo EVENTS] lifecycle cold_start emitted");
|
|
9440
|
-
} catch (err) {
|
|
9441
|
-
if (debug) console.log("[Paywallo EVENTS] lifecycle cold_start failed", err);
|
|
9442
|
-
}
|
|
9443
|
-
})();
|
|
9444
|
-
}, DEBOUNCE_MS);
|
|
9445
|
-
return () => clearTimeout(timer);
|
|
9446
|
-
}, [isInitialized]);
|
|
9713
|
+
// src/domains/paywall/SuperwallAutoBridge.ts
|
|
9714
|
+
var bridgeStarted = false;
|
|
9715
|
+
var unsubscribe = null;
|
|
9716
|
+
var debugEnabled = false;
|
|
9717
|
+
function log(msg, data) {
|
|
9718
|
+
if (!debugEnabled) return;
|
|
9719
|
+
if (data !== void 0) {
|
|
9720
|
+
console.log(`[Paywallo:SuperwallBridge] ${msg}`, data);
|
|
9721
|
+
} else {
|
|
9722
|
+
console.log(`[Paywallo:SuperwallBridge] ${msg}`);
|
|
9723
|
+
}
|
|
9447
9724
|
}
|
|
9725
|
+
function minuteBucket(ts) {
|
|
9726
|
+
return String(Math.floor(ts / 6e4));
|
|
9727
|
+
}
|
|
9728
|
+
function buildEventId(type, identifier, ts) {
|
|
9729
|
+
return buildDeterministicEventId(["sw", type, identifier, minuteBucket(ts)]);
|
|
9730
|
+
}
|
|
9731
|
+
async function trackPaywallEvent(type, identifier, ts, extra) {
|
|
9732
|
+
const _eventId = buildEventId(type, identifier, ts);
|
|
9733
|
+
try {
|
|
9734
|
+
const cleanExtra = {};
|
|
9735
|
+
if (extra) {
|
|
9736
|
+
for (const [k, v] of Object.entries(extra)) if (v !== void 0) cleanExtra[k] = v;
|
|
9737
|
+
}
|
|
9738
|
+
await PaywalloClient.track("paywall", {
|
|
9739
|
+
priority: "critical",
|
|
9740
|
+
properties: {
|
|
9741
|
+
type,
|
|
9742
|
+
paywall_id: identifier,
|
|
9743
|
+
...cleanExtra
|
|
9744
|
+
}
|
|
9745
|
+
});
|
|
9746
|
+
} catch (err) {
|
|
9747
|
+
log("track error", { type, identifier, eventId: _eventId, err: String(err) });
|
|
9748
|
+
}
|
|
9749
|
+
}
|
|
9750
|
+
function mapDismissToCloseReason(resultType) {
|
|
9751
|
+
switch (resultType) {
|
|
9752
|
+
case "purchased":
|
|
9753
|
+
return "purchased";
|
|
9754
|
+
case "restored":
|
|
9755
|
+
return "purchased";
|
|
9756
|
+
// restore counts as a purchase outcome for funnel
|
|
9757
|
+
case "declined":
|
|
9758
|
+
return "dismissed";
|
|
9759
|
+
default:
|
|
9760
|
+
return void 0;
|
|
9761
|
+
}
|
|
9762
|
+
}
|
|
9763
|
+
function buildCallbacks() {
|
|
9764
|
+
return {
|
|
9765
|
+
onPaywallPresent: (info) => {
|
|
9766
|
+
const ts = Date.now();
|
|
9767
|
+
log("onPaywallPresent", { identifier: info.identifier });
|
|
9768
|
+
void trackPaywallEvent("viewed", info.identifier, ts, {
|
|
9769
|
+
placement: info.presentedByEventWithName,
|
|
9770
|
+
variant_id: info.experiment?.variant?.id,
|
|
9771
|
+
campaign_id: info.experiment?.id
|
|
9772
|
+
});
|
|
9773
|
+
},
|
|
9774
|
+
onPaywallDismiss: (info, result) => {
|
|
9775
|
+
const ts = Date.now();
|
|
9776
|
+
log("onPaywallDismiss", { identifier: info.identifier, result: result.type });
|
|
9777
|
+
void trackPaywallEvent("closed", info.identifier, ts, {
|
|
9778
|
+
placement: info.presentedByEventWithName,
|
|
9779
|
+
variant_id: info.experiment?.variant?.id,
|
|
9780
|
+
campaign_id: info.experiment?.id,
|
|
9781
|
+
close_reason: mapDismissToCloseReason(result.type),
|
|
9782
|
+
closed_at: new Date(ts).toISOString()
|
|
9783
|
+
});
|
|
9784
|
+
},
|
|
9785
|
+
onPurchase: (params) => {
|
|
9786
|
+
const ts = Date.now();
|
|
9787
|
+
const safe = params !== null && typeof params === "object" ? params : {};
|
|
9788
|
+
const productId = "productId" in safe && typeof safe.productId === "string" ? safe.productId : "unknown";
|
|
9789
|
+
const identifier = "paywallIdentifier" in safe && typeof safe.paywallIdentifier === "string" ? safe.paywallIdentifier : productId;
|
|
9790
|
+
log("onPurchase", { productId, identifier });
|
|
9791
|
+
void trackPaywallEvent("purchased", identifier, ts, { product_id: productId });
|
|
9792
|
+
},
|
|
9793
|
+
// Global Superwall event listener — used specifically for `transactionComplete`
|
|
9794
|
+
// which is the only event that exposes the full product (currency/price) +
|
|
9795
|
+
// transaction (storeTransactionId) shape needed to create a server-side
|
|
9796
|
+
// `transactions` row. Other events are skipped (paywallOpen/Dismiss already
|
|
9797
|
+
// handled above with their typed callbacks).
|
|
9798
|
+
onSuperwallEvent: (info) => {
|
|
9799
|
+
const ev = info?.event;
|
|
9800
|
+
if (!ev || ev.event !== "transactionComplete") return;
|
|
9801
|
+
const ts = Date.now();
|
|
9802
|
+
const product = ev.product;
|
|
9803
|
+
const transaction = ev.transaction;
|
|
9804
|
+
if (!product) {
|
|
9805
|
+
log("transactionComplete missing product \u2014 skipping transaction track");
|
|
9806
|
+
return;
|
|
9807
|
+
}
|
|
9808
|
+
const productId = product.productIdentifier ?? product.id ?? "unknown";
|
|
9809
|
+
const currency = product.currencyCode ?? "USD";
|
|
9810
|
+
const price = product.price ?? 0;
|
|
9811
|
+
const transactionId = transaction?.storeTransactionId ?? transaction?.originalTransactionIdentifier ?? `${productId}_${String(ts)}`;
|
|
9812
|
+
const isTrial = product.hasFreeTrial === true || (product.trialPeriodPrice ?? 0) > 0;
|
|
9813
|
+
const paywallIdentifier = ev.paywallInfo?.identifier;
|
|
9814
|
+
log("onSuperwallEvent: transactionComplete", { productId, currency, price, transactionId, isTrial });
|
|
9815
|
+
void (async () => {
|
|
9816
|
+
try {
|
|
9817
|
+
await PaywalloClient.track("transaction", {
|
|
9818
|
+
priority: "critical",
|
|
9819
|
+
properties: {
|
|
9820
|
+
type: isTrial ? "trial_started" : "completed",
|
|
9821
|
+
// Server's IngestTranslator looks for `transaction_id`/`product_id`
|
|
9822
|
+
// /`amount`/`currency`/`paywall_id` keys (not `tx_id`). PurchaseHandler
|
|
9823
|
+
// then resolves type=trial/new/renewal based on amount being 0 vs >0.
|
|
9824
|
+
transaction_id: transactionId,
|
|
9825
|
+
product_id: productId,
|
|
9826
|
+
amount: price,
|
|
9827
|
+
currency,
|
|
9828
|
+
...paywallIdentifier ? { paywall_id: paywallIdentifier } : {}
|
|
9829
|
+
}
|
|
9830
|
+
});
|
|
9831
|
+
} catch (err) {
|
|
9832
|
+
log("transactionComplete track error", { err: String(err) });
|
|
9833
|
+
}
|
|
9834
|
+
})();
|
|
9835
|
+
}
|
|
9836
|
+
};
|
|
9837
|
+
}
|
|
9838
|
+
function startSuperwallAutoBridge(debug = false) {
|
|
9839
|
+
debugEnabled = debug;
|
|
9840
|
+
if (bridgeStarted) {
|
|
9841
|
+
log("already started, skipping");
|
|
9842
|
+
return;
|
|
9843
|
+
}
|
|
9844
|
+
void detectAndStart();
|
|
9845
|
+
}
|
|
9846
|
+
async function detectAndStart() {
|
|
9847
|
+
let subscribeFn;
|
|
9848
|
+
try {
|
|
9849
|
+
const mod = await import("expo-superwall");
|
|
9850
|
+
if (!mod || typeof mod.subscribeToSuperwallEvents !== "function") {
|
|
9851
|
+
const internal = await import("expo-superwall/build/src/internal/superwallEventBridge");
|
|
9852
|
+
if (typeof internal.subscribeToSuperwallEvents !== "function") {
|
|
9853
|
+
log("expo-superwall subscribeToSuperwallEvents not found \u2014 bridge inactive");
|
|
9854
|
+
return;
|
|
9855
|
+
}
|
|
9856
|
+
subscribeFn = internal.subscribeToSuperwallEvents;
|
|
9857
|
+
} else {
|
|
9858
|
+
subscribeFn = mod.subscribeToSuperwallEvents;
|
|
9859
|
+
}
|
|
9860
|
+
} catch {
|
|
9861
|
+
log("expo-superwall not installed \u2014 bridge inactive");
|
|
9862
|
+
return;
|
|
9863
|
+
}
|
|
9864
|
+
try {
|
|
9865
|
+
const callbacks = buildCallbacks();
|
|
9866
|
+
unsubscribe = subscribeFn(void 0, () => callbacks);
|
|
9867
|
+
bridgeStarted = true;
|
|
9868
|
+
log("bridge started");
|
|
9869
|
+
} catch (err) {
|
|
9870
|
+
log("subscribe failed", { err: String(err) });
|
|
9871
|
+
}
|
|
9872
|
+
}
|
|
9873
|
+
|
|
9874
|
+
// src/PaywalloProvider.tsx
|
|
9875
|
+
init_session();
|
|
9876
|
+
init_ClientError();
|
|
9877
|
+
|
|
9878
|
+
// src/hooks/useAppAutoEvents.ts
|
|
9879
|
+
import { useEffect as useEffect13, useRef as useRef8 } from "react";
|
|
9880
|
+
|
|
9881
|
+
// src/utils/platformDetection.ts
|
|
9882
|
+
async function detectPlatform3() {
|
|
9883
|
+
try {
|
|
9884
|
+
const rn = await import("react-native");
|
|
9885
|
+
return rn.Platform?.OS === "ios" ? "ios" : "android";
|
|
9886
|
+
} catch {
|
|
9887
|
+
return "android";
|
|
9888
|
+
}
|
|
9889
|
+
}
|
|
9890
|
+
async function detectOsVersion() {
|
|
9891
|
+
try {
|
|
9892
|
+
const rn = await import("react-native");
|
|
9893
|
+
const version = rn.Platform?.Version;
|
|
9894
|
+
return version != null ? String(version) : "unknown";
|
|
9895
|
+
} catch {
|
|
9896
|
+
return "unknown";
|
|
9897
|
+
}
|
|
9898
|
+
}
|
|
9899
|
+
|
|
9900
|
+
// src/hooks/useAppAutoEvents.ts
|
|
9901
|
+
var FIRST_SEEN_KEY = "@paywallo:firstSeen_v226";
|
|
9902
|
+
var DEBOUNCE_MS = 1e3;
|
|
9903
|
+
function useAppAutoEvents(config) {
|
|
9904
|
+
const { isInitialized, getAppVersion: getAppVersion2, getSessionId, emitLifecycle, storageGet, storageSet, debug } = config;
|
|
9905
|
+
const didRunRef = useRef8(false);
|
|
9906
|
+
useEffect13(() => {
|
|
9907
|
+
if (debug) console.log("[Paywallo EVENTS] useEffect fired", { isInitialized, didRunRefCurrent: didRunRef.current });
|
|
9908
|
+
if (!isInitialized || didRunRef.current) return;
|
|
9909
|
+
const timer = setTimeout(() => {
|
|
9910
|
+
if (didRunRef.current) return;
|
|
9911
|
+
didRunRef.current = true;
|
|
9912
|
+
void (async () => {
|
|
9913
|
+
const sessionId = getSessionId();
|
|
9914
|
+
const appVersion = getAppVersion2();
|
|
9915
|
+
const deviceType = await detectPlatform3();
|
|
9916
|
+
const osVersion = await detectOsVersion();
|
|
9917
|
+
if (debug) console.log("[Paywallo EVENTS] computed device context", { deviceType, osVersion, appVersion, sessionId, hasSessionId: !!sessionId });
|
|
9918
|
+
try {
|
|
9919
|
+
if (debug) console.log("[Paywallo EVENTS] checking install \u2014 about to read FIRST_SEEN_KEY");
|
|
9920
|
+
const firstSeen = await storageGet(FIRST_SEEN_KEY);
|
|
9921
|
+
if (!firstSeen) {
|
|
9922
|
+
await emitLifecycle({ type: "install", device_type: deviceType, os_version: osVersion, app_version: appVersion, ...sessionId ? { session_id: sessionId } : {} }, "critical");
|
|
9923
|
+
await storageSet(FIRST_SEEN_KEY, (/* @__PURE__ */ new Date()).toISOString());
|
|
9924
|
+
if (debug) console.log("[Paywallo EVENTS] install event emitted (first time)");
|
|
9925
|
+
if (debug) console.log("[Paywallo EVENTS] lifecycle install emitted");
|
|
9926
|
+
} else {
|
|
9927
|
+
if (debug) console.log("[Paywallo EVENTS] install skipped \u2014 firstSeen already exists", { firstSeen });
|
|
9928
|
+
}
|
|
9929
|
+
} catch (err) {
|
|
9930
|
+
if (debug) console.log("[Paywallo EVENTS] lifecycle install check failed", err);
|
|
9931
|
+
}
|
|
9932
|
+
try {
|
|
9933
|
+
if (debug) console.log("[Paywallo EVENTS] emitting cold_start");
|
|
9934
|
+
await emitLifecycle({ type: "cold_start", app_version: appVersion, device_type: deviceType, os_version: osVersion, ...sessionId ? { session_id: sessionId } : {} }, "normal");
|
|
9935
|
+
if (debug) console.log("[Paywallo EVENTS] lifecycle cold_start emitted");
|
|
9936
|
+
} catch (err) {
|
|
9937
|
+
if (debug) console.log("[Paywallo EVENTS] lifecycle cold_start failed", err);
|
|
9938
|
+
}
|
|
9939
|
+
})();
|
|
9940
|
+
}, DEBOUNCE_MS);
|
|
9941
|
+
return () => clearTimeout(timer);
|
|
9942
|
+
}, [isInitialized]);
|
|
9943
|
+
}
|
|
9944
|
+
|
|
9945
|
+
// src/hooks/useCampaignPreload.ts
|
|
9946
|
+
init_PaywalloClient();
|
|
9947
|
+
init_CampaignError();
|
|
9948
|
+
import { useCallback as useCallback15, useRef as useRef9, useState as useState14 } from "react";
|
|
9949
|
+
|
|
9950
|
+
// src/utils/loadCampaignProducts.ts
|
|
9951
|
+
init_IAPService();
|
|
9448
9952
|
|
|
9449
|
-
// src/hooks/useCampaignPreload.ts
|
|
9450
|
-
init_PaywalloClient();
|
|
9451
|
-
init_CampaignError();
|
|
9452
|
-
import { useCallback as useCallback15, useRef as useRef8, useState as useState13 } from "react";
|
|
9453
|
-
|
|
9454
|
-
// src/utils/loadCampaignProducts.ts
|
|
9455
|
-
init_IAPService();
|
|
9456
|
-
|
|
9457
9953
|
// src/utils/serverProduct.ts
|
|
9458
9954
|
var PERIOD_MAP = {
|
|
9459
9955
|
P1Y: "ano",
|
|
@@ -9518,8 +10014,8 @@ function getCacheEntry(cache, placement) {
|
|
|
9518
10014
|
|
|
9519
10015
|
// src/hooks/useCampaignPreload.ts
|
|
9520
10016
|
function useCampaignPreload() {
|
|
9521
|
-
const [preloadedWebView, setPreloadedWebView] =
|
|
9522
|
-
const preloadedCampaignsRef =
|
|
10017
|
+
const [preloadedWebView, setPreloadedWebView] = useState14(null);
|
|
10018
|
+
const preloadedCampaignsRef = useRef9(/* @__PURE__ */ new Map());
|
|
9523
10019
|
const isPreloadValid = useCallback15(
|
|
9524
10020
|
(placement) => isCacheEntryValid(preloadedCampaignsRef.current.get(placement)),
|
|
9525
10021
|
[]
|
|
@@ -9597,10 +10093,10 @@ function useCampaignPreload() {
|
|
|
9597
10093
|
}
|
|
9598
10094
|
|
|
9599
10095
|
// src/hooks/useProductLoader.ts
|
|
9600
|
-
import { useCallback as useCallback16, useState as
|
|
10096
|
+
import { useCallback as useCallback16, useState as useState15 } from "react";
|
|
9601
10097
|
function useProductLoader() {
|
|
9602
|
-
const [products, setProducts] =
|
|
9603
|
-
const [isLoadingProducts, setIsLoadingProducts] =
|
|
10098
|
+
const [products, setProducts] = useState15(/* @__PURE__ */ new Map());
|
|
10099
|
+
const [isLoadingProducts, setIsLoadingProducts] = useState15(false);
|
|
9604
10100
|
const refreshProducts = useCallback16(async (productIds) => {
|
|
9605
10101
|
setIsLoadingProducts(true);
|
|
9606
10102
|
try {
|
|
@@ -9686,7 +10182,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
|
|
|
9686
10182
|
// src/hooks/useSubscriptionSync.ts
|
|
9687
10183
|
init_PaywalloClient();
|
|
9688
10184
|
init_SubscriptionCache();
|
|
9689
|
-
import { useCallback as useCallback18, useRef as
|
|
10185
|
+
import { useCallback as useCallback18, useRef as useRef10, useState as useState16 } from "react";
|
|
9690
10186
|
|
|
9691
10187
|
// src/hooks/subscriptionSyncHelpers.ts
|
|
9692
10188
|
init_SubscriptionCache();
|
|
@@ -9794,8 +10290,8 @@ async function checkPersistedCache(distinctId, onHit) {
|
|
|
9794
10290
|
|
|
9795
10291
|
// src/hooks/useSubscriptionSync.ts
|
|
9796
10292
|
function useSubscriptionSync() {
|
|
9797
|
-
const [subscription, setSubscription] =
|
|
9798
|
-
const cacheRef =
|
|
10293
|
+
const [subscription, setSubscription] = useState16(null);
|
|
10294
|
+
const cacheRef = useRef10(null);
|
|
9799
10295
|
const setCacheAndState = useCallback18((sub) => {
|
|
9800
10296
|
cacheRef.current = { data: sub, expiresAt: Date.now() + CACHE_TTL_MS2 };
|
|
9801
10297
|
setSubscription(sub);
|
|
@@ -9856,214 +10352,24 @@ function useSubscriptionSync() {
|
|
|
9856
10352
|
return { subscription, hasActiveSubscription, getSubscription, invalidateCache };
|
|
9857
10353
|
}
|
|
9858
10354
|
|
|
9859
|
-
// src/domains/paywall/SuperwallAutoBridge.ts
|
|
9860
|
-
init_PaywalloClient();
|
|
9861
|
-
|
|
9862
|
-
// src/core/utils/eventId.ts
|
|
9863
|
-
function hashString(input) {
|
|
9864
|
-
let h1 = 3735928559;
|
|
9865
|
-
let h2 = 1103547991;
|
|
9866
|
-
for (let i = 0; i < input.length; i++) {
|
|
9867
|
-
const ch = input.charCodeAt(i);
|
|
9868
|
-
h1 = Math.imul(h1 ^ ch, 2654435769);
|
|
9869
|
-
h2 = Math.imul(h2 ^ ch, 1598716949);
|
|
9870
|
-
}
|
|
9871
|
-
h1 = Math.imul(h1 ^ h1 >>> 16, 73244475);
|
|
9872
|
-
h1 ^= Math.imul(h2 ^ h2 >>> 13, 351452291);
|
|
9873
|
-
h2 = Math.imul(h2 ^ h2 >>> 16, 73244475);
|
|
9874
|
-
h2 ^= Math.imul(h1 ^ h1 >>> 13, 351452291);
|
|
9875
|
-
const toHex = (n) => (n >>> 0).toString(16).padStart(8, "0");
|
|
9876
|
-
return toHex(h1) + toHex(h2);
|
|
9877
|
-
}
|
|
9878
|
-
function buildDeterministicEventId(parts) {
|
|
9879
|
-
const raw = hashString(parts.join("|"));
|
|
9880
|
-
const p1 = raw.slice(0, 8);
|
|
9881
|
-
const p2 = raw.slice(8, 12);
|
|
9882
|
-
const p3 = "4" + raw.slice(13, 16);
|
|
9883
|
-
const p4 = (parseInt(raw[16], 16) & 3 | 8).toString(16) + raw.slice(17, 20);
|
|
9884
|
-
const p5 = raw.padEnd(32, "0").slice(20, 32);
|
|
9885
|
-
return `${p1}-${p2}-${p3}-${p4}-${p5}`;
|
|
9886
|
-
}
|
|
9887
|
-
|
|
9888
|
-
// src/domains/paywall/SuperwallAutoBridge.ts
|
|
9889
|
-
var bridgeStarted = false;
|
|
9890
|
-
var unsubscribe = null;
|
|
9891
|
-
var debugEnabled = false;
|
|
9892
|
-
function log(msg, data) {
|
|
9893
|
-
if (!debugEnabled) return;
|
|
9894
|
-
if (data !== void 0) {
|
|
9895
|
-
console.log(`[Paywallo:SuperwallBridge] ${msg}`, data);
|
|
9896
|
-
} else {
|
|
9897
|
-
console.log(`[Paywallo:SuperwallBridge] ${msg}`);
|
|
9898
|
-
}
|
|
9899
|
-
}
|
|
9900
|
-
function minuteBucket(ts) {
|
|
9901
|
-
return String(Math.floor(ts / 6e4));
|
|
9902
|
-
}
|
|
9903
|
-
function buildEventId(type, identifier, ts) {
|
|
9904
|
-
return buildDeterministicEventId(["sw", type, identifier, minuteBucket(ts)]);
|
|
9905
|
-
}
|
|
9906
|
-
async function trackPaywallEvent(type, identifier, ts, extra) {
|
|
9907
|
-
const _eventId = buildEventId(type, identifier, ts);
|
|
9908
|
-
try {
|
|
9909
|
-
const cleanExtra = {};
|
|
9910
|
-
if (extra) {
|
|
9911
|
-
for (const [k, v] of Object.entries(extra)) if (v !== void 0) cleanExtra[k] = v;
|
|
9912
|
-
}
|
|
9913
|
-
await PaywalloClient.track("paywall", {
|
|
9914
|
-
priority: "critical",
|
|
9915
|
-
properties: {
|
|
9916
|
-
type,
|
|
9917
|
-
paywall_id: identifier,
|
|
9918
|
-
...cleanExtra
|
|
9919
|
-
}
|
|
9920
|
-
});
|
|
9921
|
-
} catch (err) {
|
|
9922
|
-
log("track error", { type, identifier, eventId: _eventId, err: String(err) });
|
|
9923
|
-
}
|
|
9924
|
-
}
|
|
9925
|
-
function mapDismissToCloseReason(resultType) {
|
|
9926
|
-
switch (resultType) {
|
|
9927
|
-
case "purchased":
|
|
9928
|
-
return "purchased";
|
|
9929
|
-
case "restored":
|
|
9930
|
-
return "purchased";
|
|
9931
|
-
// restore counts as a purchase outcome for funnel
|
|
9932
|
-
case "declined":
|
|
9933
|
-
return "dismissed";
|
|
9934
|
-
default:
|
|
9935
|
-
return void 0;
|
|
9936
|
-
}
|
|
9937
|
-
}
|
|
9938
|
-
function buildCallbacks() {
|
|
9939
|
-
return {
|
|
9940
|
-
onPaywallPresent: (info) => {
|
|
9941
|
-
const ts = Date.now();
|
|
9942
|
-
log("onPaywallPresent", { identifier: info.identifier });
|
|
9943
|
-
void trackPaywallEvent("viewed", info.identifier, ts, {
|
|
9944
|
-
placement: info.presentedByEventWithName,
|
|
9945
|
-
variant_id: info.experiment?.variant?.id,
|
|
9946
|
-
campaign_id: info.experiment?.id
|
|
9947
|
-
});
|
|
9948
|
-
},
|
|
9949
|
-
onPaywallDismiss: (info, result) => {
|
|
9950
|
-
const ts = Date.now();
|
|
9951
|
-
log("onPaywallDismiss", { identifier: info.identifier, result: result.type });
|
|
9952
|
-
void trackPaywallEvent("closed", info.identifier, ts, {
|
|
9953
|
-
placement: info.presentedByEventWithName,
|
|
9954
|
-
variant_id: info.experiment?.variant?.id,
|
|
9955
|
-
campaign_id: info.experiment?.id,
|
|
9956
|
-
close_reason: mapDismissToCloseReason(result.type),
|
|
9957
|
-
closed_at: new Date(ts).toISOString()
|
|
9958
|
-
});
|
|
9959
|
-
},
|
|
9960
|
-
onPurchase: (params) => {
|
|
9961
|
-
const ts = Date.now();
|
|
9962
|
-
const safe = params !== null && typeof params === "object" ? params : {};
|
|
9963
|
-
const productId = "productId" in safe && typeof safe.productId === "string" ? safe.productId : "unknown";
|
|
9964
|
-
const identifier = "paywallIdentifier" in safe && typeof safe.paywallIdentifier === "string" ? safe.paywallIdentifier : productId;
|
|
9965
|
-
log("onPurchase", { productId, identifier });
|
|
9966
|
-
void trackPaywallEvent("purchased", identifier, ts, { product_id: productId });
|
|
9967
|
-
},
|
|
9968
|
-
// Global Superwall event listener — used specifically for `transactionComplete`
|
|
9969
|
-
// which is the only event that exposes the full product (currency/price) +
|
|
9970
|
-
// transaction (storeTransactionId) shape needed to create a server-side
|
|
9971
|
-
// `transactions` row. Other events are skipped (paywallOpen/Dismiss already
|
|
9972
|
-
// handled above with their typed callbacks).
|
|
9973
|
-
onSuperwallEvent: (info) => {
|
|
9974
|
-
const ev = info?.event;
|
|
9975
|
-
if (!ev || ev.event !== "transactionComplete") return;
|
|
9976
|
-
const ts = Date.now();
|
|
9977
|
-
const product = ev.product;
|
|
9978
|
-
const transaction = ev.transaction;
|
|
9979
|
-
if (!product) {
|
|
9980
|
-
log("transactionComplete missing product \u2014 skipping transaction track");
|
|
9981
|
-
return;
|
|
9982
|
-
}
|
|
9983
|
-
const productId = product.productIdentifier ?? product.id ?? "unknown";
|
|
9984
|
-
const currency = product.currencyCode ?? "USD";
|
|
9985
|
-
const price = product.price ?? 0;
|
|
9986
|
-
const transactionId = transaction?.storeTransactionId ?? transaction?.originalTransactionIdentifier ?? `${productId}_${String(ts)}`;
|
|
9987
|
-
const isTrial = product.hasFreeTrial === true || (product.trialPeriodPrice ?? 0) > 0;
|
|
9988
|
-
const paywallIdentifier = ev.paywallInfo?.identifier;
|
|
9989
|
-
log("onSuperwallEvent: transactionComplete", { productId, currency, price, transactionId, isTrial });
|
|
9990
|
-
void (async () => {
|
|
9991
|
-
try {
|
|
9992
|
-
await PaywalloClient.track("transaction", {
|
|
9993
|
-
priority: "critical",
|
|
9994
|
-
properties: {
|
|
9995
|
-
type: isTrial ? "trial_started" : "completed",
|
|
9996
|
-
// Server's IngestTranslator looks for `transaction_id`/`product_id`
|
|
9997
|
-
// /`amount`/`currency`/`paywall_id` keys (not `tx_id`). PurchaseHandler
|
|
9998
|
-
// then resolves type=trial/new/renewal based on amount being 0 vs >0.
|
|
9999
|
-
transaction_id: transactionId,
|
|
10000
|
-
product_id: productId,
|
|
10001
|
-
amount: price,
|
|
10002
|
-
currency,
|
|
10003
|
-
...paywallIdentifier ? { paywall_id: paywallIdentifier } : {}
|
|
10004
|
-
}
|
|
10005
|
-
});
|
|
10006
|
-
} catch (err) {
|
|
10007
|
-
log("transactionComplete track error", { err: String(err) });
|
|
10008
|
-
}
|
|
10009
|
-
})();
|
|
10010
|
-
}
|
|
10011
|
-
};
|
|
10012
|
-
}
|
|
10013
|
-
function startSuperwallAutoBridge(debug = false) {
|
|
10014
|
-
debugEnabled = debug;
|
|
10015
|
-
if (bridgeStarted) {
|
|
10016
|
-
log("already started, skipping");
|
|
10017
|
-
return;
|
|
10018
|
-
}
|
|
10019
|
-
void detectAndStart();
|
|
10020
|
-
}
|
|
10021
|
-
async function detectAndStart() {
|
|
10022
|
-
let subscribeFn;
|
|
10023
|
-
try {
|
|
10024
|
-
const mod = await import("expo-superwall");
|
|
10025
|
-
if (!mod || typeof mod.subscribeToSuperwallEvents !== "function") {
|
|
10026
|
-
const internal = await import("expo-superwall/build/src/internal/superwallEventBridge");
|
|
10027
|
-
if (typeof internal.subscribeToSuperwallEvents !== "function") {
|
|
10028
|
-
log("expo-superwall subscribeToSuperwallEvents not found \u2014 bridge inactive");
|
|
10029
|
-
return;
|
|
10030
|
-
}
|
|
10031
|
-
subscribeFn = internal.subscribeToSuperwallEvents;
|
|
10032
|
-
} else {
|
|
10033
|
-
subscribeFn = mod.subscribeToSuperwallEvents;
|
|
10034
|
-
}
|
|
10035
|
-
} catch {
|
|
10036
|
-
log("expo-superwall not installed \u2014 bridge inactive");
|
|
10037
|
-
return;
|
|
10038
|
-
}
|
|
10039
|
-
try {
|
|
10040
|
-
const callbacks = buildCallbacks();
|
|
10041
|
-
unsubscribe = subscribeFn(void 0, () => callbacks);
|
|
10042
|
-
bridgeStarted = true;
|
|
10043
|
-
log("bridge started");
|
|
10044
|
-
} catch (err) {
|
|
10045
|
-
log("subscribe failed", { err: String(err) });
|
|
10046
|
-
}
|
|
10047
|
-
}
|
|
10048
|
-
|
|
10049
10355
|
// src/PaywalloProvider.tsx
|
|
10050
10356
|
init_localization();
|
|
10051
|
-
import { jsx as
|
|
10357
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
10052
10358
|
function PaywalloProvider({ children, config }) {
|
|
10053
|
-
const [isInitialized, setIsInitialized] =
|
|
10054
|
-
const [initError, setInitError] =
|
|
10055
|
-
const [distinctId, setDistinctId] =
|
|
10056
|
-
const [activePaywall, setActivePaywall] =
|
|
10359
|
+
const [isInitialized, setIsInitialized] = useState17(false);
|
|
10360
|
+
const [initError, setInitError] = useState17(null);
|
|
10361
|
+
const [distinctId, setDistinctId] = useState17(null);
|
|
10362
|
+
const [activePaywall, setActivePaywall] = useState17(null);
|
|
10057
10363
|
const { products, isLoadingProducts, refreshProducts } = useProductLoader();
|
|
10058
10364
|
const { subscription, hasActiveSubscription, getSubscription, invalidateCache } = useSubscriptionSync();
|
|
10059
10365
|
const { preloadedWebView, setPreloadedWebView, preloadCampaign, consumePreloadedCampaign, isPreloadValid } = useCampaignPreload();
|
|
10060
10366
|
const clearPreloadedWebView = useCallback19(() => setPreloadedWebView(null), [setPreloadedWebView]);
|
|
10061
|
-
const autoPreloadTriggeredRef =
|
|
10062
|
-
const preloadedWebViewRef =
|
|
10063
|
-
const pollTimerRef =
|
|
10064
|
-
const pollCancelledRef =
|
|
10065
|
-
const secureStorageRef =
|
|
10066
|
-
|
|
10367
|
+
const autoPreloadTriggeredRef = useRef11(false);
|
|
10368
|
+
const preloadedWebViewRef = useRef11(preloadedWebView);
|
|
10369
|
+
const pollTimerRef = useRef11(null);
|
|
10370
|
+
const pollCancelledRef = useRef11(false);
|
|
10371
|
+
const secureStorageRef = useRef11(new SecureStorage(config.debug));
|
|
10372
|
+
useEffect14(() => {
|
|
10067
10373
|
preloadedWebViewRef.current = preloadedWebView;
|
|
10068
10374
|
}, [preloadedWebView]);
|
|
10069
10375
|
useAppAutoEvents({
|
|
@@ -10094,8 +10400,8 @@ function PaywalloProvider({ children, config }) {
|
|
|
10094
10400
|
});
|
|
10095
10401
|
}, []);
|
|
10096
10402
|
const { showingPreloadedWebView, presentPreloadedWebView, resolvePreloadedPaywall, handlePreloadedWebViewReady: baseHandlePreloadedWebViewReady, handlePreloadedClose: baseHandlePreloadedClose, setShowingPreloadedWebView, presentedAtRef } = usePaywallPresenter(preloadedWebView, setPreloadedWebView);
|
|
10097
|
-
const SCREEN_HEIGHT =
|
|
10098
|
-
const slideAnim =
|
|
10403
|
+
const SCREEN_HEIGHT = useMemo3(() => Dimensions5.get("window").height, []);
|
|
10404
|
+
const slideAnim = useRef11(new Animated4.Value(SCREEN_HEIGHT)).current;
|
|
10099
10405
|
const handlePreloadedWebViewReady = useCallback19(() => {
|
|
10100
10406
|
if (PaywalloClient.getConfig()?.debug) {
|
|
10101
10407
|
console.log(`[Paywallo WEBVIEW] loaded \u2014 placement: ${preloadedWebView?.placement}`);
|
|
@@ -10104,7 +10410,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10104
10410
|
}, [preloadedWebView?.placement, baseHandlePreloadedWebViewReady]);
|
|
10105
10411
|
const handlePreloadedClose = useCallback19(() => {
|
|
10106
10412
|
const placement = preloadedWebView?.placement;
|
|
10107
|
-
|
|
10413
|
+
Animated4.timing(slideAnim, { toValue: SCREEN_HEIGHT, duration: 200, easing: Easing2.in(Easing2.cubic), useNativeDriver: true }).start(() => {
|
|
10108
10414
|
baseHandlePreloadedClose();
|
|
10109
10415
|
if (placement) triggerRepreload(placement);
|
|
10110
10416
|
});
|
|
@@ -10117,7 +10423,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10117
10423
|
presentedAtRef,
|
|
10118
10424
|
invalidateCache
|
|
10119
10425
|
);
|
|
10120
|
-
const [isPreloadPurchasing, setIsPreloadPurchasing] =
|
|
10426
|
+
const [isPreloadPurchasing, setIsPreloadPurchasing] = useState17(false);
|
|
10121
10427
|
const handlePreloadedPurchase = useCallback19(async (productId) => {
|
|
10122
10428
|
setIsPreloadPurchasing(true);
|
|
10123
10429
|
try {
|
|
@@ -10126,8 +10432,8 @@ function PaywalloProvider({ children, config }) {
|
|
|
10126
10432
|
setIsPreloadPurchasing(false);
|
|
10127
10433
|
}
|
|
10128
10434
|
}, [rawPreloadedPurchase]);
|
|
10129
|
-
const configRef =
|
|
10130
|
-
|
|
10435
|
+
const configRef = useRef11(config);
|
|
10436
|
+
useEffect14(() => {
|
|
10131
10437
|
let mounted = true;
|
|
10132
10438
|
initLocalization({ detectDevice: true });
|
|
10133
10439
|
PaywalloClient.init(configRef.current).then(async () => {
|
|
@@ -10140,6 +10446,11 @@ function PaywalloProvider({ children, config }) {
|
|
|
10140
10446
|
const placement = await PaywalloClient.waitForAutoPreloadedPlacement();
|
|
10141
10447
|
if (mounted && placement) void preloadCampaign(placement).catch(() => {
|
|
10142
10448
|
});
|
|
10449
|
+
const preloadPlacements = configRef.current.preloadPaywalls;
|
|
10450
|
+
if (mounted && preloadPlacements && preloadPlacements.length > 0) {
|
|
10451
|
+
void PaywalloClient.preloadPaywalls(preloadPlacements).catch(() => {
|
|
10452
|
+
});
|
|
10453
|
+
}
|
|
10143
10454
|
}
|
|
10144
10455
|
}).catch((err) => {
|
|
10145
10456
|
if (!mounted) return;
|
|
@@ -10154,7 +10465,21 @@ function PaywalloProvider({ children, config }) {
|
|
|
10154
10465
|
return api ? api.getPaywall(p) : null;
|
|
10155
10466
|
}, []);
|
|
10156
10467
|
const presentPaywall = useCallback19((placement) => {
|
|
10157
|
-
|
|
10468
|
+
const preloaded = paywallPreloadService.getPreloaded(placement);
|
|
10469
|
+
return new Promise((resolve) => setActivePaywall({
|
|
10470
|
+
placement,
|
|
10471
|
+
resolver: resolve,
|
|
10472
|
+
...preloaded && {
|
|
10473
|
+
paywallConfig: {
|
|
10474
|
+
id: preloaded.config.id,
|
|
10475
|
+
placement: preloaded.config.placement,
|
|
10476
|
+
config: preloaded.config.config,
|
|
10477
|
+
primaryProductId: preloaded.config.primaryProductId,
|
|
10478
|
+
secondaryProductId: preloaded.config.secondaryProductId
|
|
10479
|
+
},
|
|
10480
|
+
preloadedProducts: preloaded.products
|
|
10481
|
+
}
|
|
10482
|
+
}));
|
|
10158
10483
|
}, []);
|
|
10159
10484
|
const trackCampaignImpression = useCallback19((placement, variantKey, campaignId) => {
|
|
10160
10485
|
const api = PaywalloClient.getApiClient();
|
|
@@ -10288,7 +10613,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10288
10613
|
}
|
|
10289
10614
|
return presentCampaign(placement);
|
|
10290
10615
|
}, [presentPreloadedWebView, presentCampaign]);
|
|
10291
|
-
|
|
10616
|
+
useEffect14(() => {
|
|
10292
10617
|
if (!isInitialized) return;
|
|
10293
10618
|
const onEmergency = async (id) => {
|
|
10294
10619
|
try {
|
|
@@ -10317,7 +10642,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10317
10642
|
const isReady = isInitialized && !isLoadingProducts;
|
|
10318
10643
|
const noOp = useCallback19(() => {
|
|
10319
10644
|
}, []);
|
|
10320
|
-
const contextValue =
|
|
10645
|
+
const contextValue = useMemo3(() => ({
|
|
10321
10646
|
config: PaywalloClient.getConfig(),
|
|
10322
10647
|
isInitialized,
|
|
10323
10648
|
isReady,
|
|
@@ -10354,17 +10679,17 @@ function PaywalloProvider({ children, config }) {
|
|
|
10354
10679
|
useLayoutEffect(() => {
|
|
10355
10680
|
if (showingPreloadedWebView) {
|
|
10356
10681
|
slideAnim.setValue(SCREEN_HEIGHT);
|
|
10357
|
-
|
|
10682
|
+
Animated4.timing(slideAnim, { toValue: 0, duration: 200, easing: Easing2.out(Easing2.cubic), useNativeDriver: true }).start();
|
|
10358
10683
|
}
|
|
10359
10684
|
}, [showingPreloadedWebView, slideAnim, SCREEN_HEIGHT]);
|
|
10360
10685
|
const preloadStyle = [
|
|
10361
|
-
|
|
10362
|
-
showingPreloadedWebView ?
|
|
10686
|
+
styles5.preloadOverlay,
|
|
10687
|
+
showingPreloadedWebView ? styles5.visible : styles5.hidden,
|
|
10363
10688
|
showingPreloadedWebView ? { transform: [{ translateY: slideAnim }] } : void 0
|
|
10364
10689
|
];
|
|
10365
|
-
return /* @__PURE__ */
|
|
10690
|
+
return /* @__PURE__ */ jsxs3(PaywalloContext.Provider, { value: contextValue, children: [
|
|
10366
10691
|
children,
|
|
10367
|
-
/* @__PURE__ */
|
|
10692
|
+
/* @__PURE__ */ jsx5(PaywallErrorBoundary, { children: !!preloadedWebView?.craftData && /* @__PURE__ */ jsx5(Animated4.View, { style: preloadStyle, pointerEvents: showingPreloadedWebView ? "auto" : "none", children: /* @__PURE__ */ jsx5(
|
|
10368
10693
|
PaywallWebView,
|
|
10369
10694
|
{
|
|
10370
10695
|
paywallId: preloadedWebView.paywallId,
|
|
@@ -10380,7 +10705,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10380
10705
|
onRestore: showingPreloadedWebView ? handlePreloadedRestore : noOp
|
|
10381
10706
|
}
|
|
10382
10707
|
) }) }),
|
|
10383
|
-
/* @__PURE__ */
|
|
10708
|
+
/* @__PURE__ */ jsx5(PaywallErrorBoundary, { children: activePaywall && /* @__PURE__ */ jsx5(
|
|
10384
10709
|
PaywallModal,
|
|
10385
10710
|
{
|
|
10386
10711
|
placement: activePaywall.placement,
|
|
@@ -10392,10 +10717,11 @@ function PaywalloProvider({ children, config }) {
|
|
|
10392
10717
|
campaignId: activePaywall.campaignId,
|
|
10393
10718
|
variantId: activePaywall.variantId
|
|
10394
10719
|
}
|
|
10395
|
-
) })
|
|
10720
|
+
) }),
|
|
10721
|
+
isInitialized && (config.preloadPaywalls?.length ?? 0) > 0 && PaywalloClient.getWebUrl() !== null && /* @__PURE__ */ jsx5(PaywallWebViewPrewarmer, { webUrl: PaywalloClient.getWebUrl() })
|
|
10396
10722
|
] });
|
|
10397
10723
|
}
|
|
10398
|
-
var
|
|
10724
|
+
var styles5 = StyleSheet5.create({
|
|
10399
10725
|
preloadOverlay: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: "#ffffff" },
|
|
10400
10726
|
hidden: { zIndex: -1, opacity: 0, width: 1, height: 1, overflow: "hidden" },
|
|
10401
10727
|
visible: { zIndex: 9999, opacity: 1 }
|