@virex-tech/paywallo-sdk 2.2.6 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +851 -511
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +743 -403
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2386,8 +2386,8 @@ var init_NotificationHandlerSetup = __esm({
|
|
|
2386
2386
|
// src/core/version.ts
|
|
2387
2387
|
function resolveVersion() {
|
|
2388
2388
|
try {
|
|
2389
|
-
if ("2.
|
|
2390
|
-
return "2.
|
|
2389
|
+
if ("2.3.0") {
|
|
2390
|
+
return "2.3.0";
|
|
2391
2391
|
}
|
|
2392
2392
|
} catch {
|
|
2393
2393
|
}
|
|
@@ -3057,6 +3057,41 @@ var init_emitPaywallClosed = __esm({
|
|
|
3057
3057
|
}
|
|
3058
3058
|
});
|
|
3059
3059
|
|
|
3060
|
+
// src/domains/paywall/extractFirstPageBackground.ts
|
|
3061
|
+
function extractFirstPageBackground(craftData) {
|
|
3062
|
+
if (!craftData) return DEFAULT_BACKGROUND;
|
|
3063
|
+
try {
|
|
3064
|
+
const data = JSON.parse(craftData);
|
|
3065
|
+
const nodes = { ...data.nodes, ...data.sharedNodes };
|
|
3066
|
+
const rootId = data.rootId;
|
|
3067
|
+
if (!rootId || !nodes[rootId]) return DEFAULT_BACKGROUND;
|
|
3068
|
+
const firstPageId = nodes[rootId].children?.[0];
|
|
3069
|
+
if (!firstPageId) return DEFAULT_BACKGROUND;
|
|
3070
|
+
const bg = nodes[firstPageId]?.props?.backgroundColor;
|
|
3071
|
+
return typeof bg === "string" && bg.length > 0 && bg !== "transparent" ? bg : DEFAULT_BACKGROUND;
|
|
3072
|
+
} catch {
|
|
3073
|
+
return DEFAULT_BACKGROUND;
|
|
3074
|
+
}
|
|
3075
|
+
}
|
|
3076
|
+
function isColorDark(color) {
|
|
3077
|
+
const hex = color.replace("#", "").trim();
|
|
3078
|
+
const normalized = hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex;
|
|
3079
|
+
if (normalized.length !== 6) return false;
|
|
3080
|
+
const r = parseInt(normalized.slice(0, 2), 16);
|
|
3081
|
+
const g = parseInt(normalized.slice(2, 4), 16);
|
|
3082
|
+
const b = parseInt(normalized.slice(4, 6), 16);
|
|
3083
|
+
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) return false;
|
|
3084
|
+
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
3085
|
+
return luminance < 0.5;
|
|
3086
|
+
}
|
|
3087
|
+
var DEFAULT_BACKGROUND;
|
|
3088
|
+
var init_extractFirstPageBackground = __esm({
|
|
3089
|
+
"src/domains/paywall/extractFirstPageBackground.ts"() {
|
|
3090
|
+
"use strict";
|
|
3091
|
+
DEFAULT_BACKGROUND = "#FFFFFF";
|
|
3092
|
+
}
|
|
3093
|
+
});
|
|
3094
|
+
|
|
3060
3095
|
// src/domains/paywall/parseWebViewMessage.ts
|
|
3061
3096
|
function deriveMessageId(message) {
|
|
3062
3097
|
if (message.id) return message.id;
|
|
@@ -3299,6 +3334,66 @@ var init_localization = __esm({
|
|
|
3299
3334
|
}
|
|
3300
3335
|
});
|
|
3301
3336
|
|
|
3337
|
+
// src/domains/paywall/PaywallSkeleton.tsx
|
|
3338
|
+
function SkeletonBlock({ style, color, opacity }) {
|
|
3339
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native14.Animated.View, { style: [style, { backgroundColor: color, opacity }] });
|
|
3340
|
+
}
|
|
3341
|
+
function PaywallSkeleton({ backgroundColor = "#FFFFFF" }) {
|
|
3342
|
+
const pulse = (0, import_react3.useRef)(new import_react_native14.Animated.Value(0.4)).current;
|
|
3343
|
+
(0, import_react3.useEffect)(() => {
|
|
3344
|
+
const loop = import_react_native14.Animated.loop(
|
|
3345
|
+
import_react_native14.Animated.sequence([
|
|
3346
|
+
import_react_native14.Animated.timing(pulse, { toValue: 1, duration: 700, useNativeDriver: true }),
|
|
3347
|
+
import_react_native14.Animated.timing(pulse, { toValue: 0.4, duration: 700, useNativeDriver: true })
|
|
3348
|
+
])
|
|
3349
|
+
);
|
|
3350
|
+
loop.start();
|
|
3351
|
+
return () => loop.stop();
|
|
3352
|
+
}, [pulse]);
|
|
3353
|
+
const placeholder = isColorDark(backgroundColor) ? "rgba(255,255,255,0.13)" : "rgba(0,0,0,0.07)";
|
|
3354
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native14.View, { style: [styles.container, { backgroundColor }], pointerEvents: "none", children: [
|
|
3355
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native14.View, { style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.logo, color: placeholder, opacity: pulse }) }),
|
|
3356
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.hero, color: placeholder, opacity: pulse }),
|
|
3357
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native14.View, { style: styles.titleGroup, children: [
|
|
3358
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.titleLine, color: placeholder, opacity: pulse }),
|
|
3359
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.titleLineShort, color: placeholder, opacity: pulse })
|
|
3360
|
+
] }),
|
|
3361
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native14.View, { style: styles.cardsRow, children: [
|
|
3362
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.card, color: placeholder, opacity: pulse }),
|
|
3363
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.card, color: placeholder, opacity: pulse })
|
|
3364
|
+
] }),
|
|
3365
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native14.View, { style: styles.footerGroup, children: [
|
|
3366
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.cta, color: placeholder, opacity: pulse }),
|
|
3367
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.footer, color: placeholder, opacity: pulse })
|
|
3368
|
+
] })
|
|
3369
|
+
] });
|
|
3370
|
+
}
|
|
3371
|
+
var import_react3, import_react_native14, import_jsx_runtime, RADIUS, styles;
|
|
3372
|
+
var init_PaywallSkeleton = __esm({
|
|
3373
|
+
"src/domains/paywall/PaywallSkeleton.tsx"() {
|
|
3374
|
+
"use strict";
|
|
3375
|
+
import_react3 = require("react");
|
|
3376
|
+
import_react_native14 = require("react-native");
|
|
3377
|
+
init_extractFirstPageBackground();
|
|
3378
|
+
import_jsx_runtime = require("react/jsx-runtime");
|
|
3379
|
+
RADIUS = 14;
|
|
3380
|
+
styles = import_react_native14.StyleSheet.create({
|
|
3381
|
+
card: { borderRadius: RADIUS, flex: 1, height: 120 },
|
|
3382
|
+
cardsRow: { flexDirection: "row", gap: 12, marginTop: "auto", paddingHorizontal: 24 },
|
|
3383
|
+
container: { flex: 1, paddingBottom: 40, paddingTop: 64 },
|
|
3384
|
+
cta: { borderRadius: 30, height: 58, marginHorizontal: 24 },
|
|
3385
|
+
footer: { alignSelf: "center", borderRadius: 6, height: 12, marginTop: 20, width: 180 },
|
|
3386
|
+
footerGroup: { marginTop: 28 },
|
|
3387
|
+
header: { alignItems: "center", paddingVertical: 12 },
|
|
3388
|
+
hero: { alignSelf: "center", borderRadius: 20, height: 220, marginTop: 16, width: "70%" },
|
|
3389
|
+
logo: { borderRadius: 6, height: 22, width: 110 },
|
|
3390
|
+
titleGroup: { alignItems: "center", gap: 12, marginTop: 28, paddingHorizontal: 24 },
|
|
3391
|
+
titleLine: { borderRadius: 8, height: 26, width: "85%" },
|
|
3392
|
+
titleLineShort: { borderRadius: 8, height: 26, width: "60%" }
|
|
3393
|
+
});
|
|
3394
|
+
}
|
|
3395
|
+
});
|
|
3396
|
+
|
|
3302
3397
|
// src/domains/paywall/paywallScripts.ts
|
|
3303
3398
|
function buildPaywallInjectionScript(data) {
|
|
3304
3399
|
const paywallData = {
|
|
@@ -3308,6 +3403,7 @@ function buildPaywallInjectionScript(data) {
|
|
|
3308
3403
|
products: data.products,
|
|
3309
3404
|
primaryProductId: data.primaryProductId,
|
|
3310
3405
|
secondaryProductId: data.secondaryProductId,
|
|
3406
|
+
tertiaryProductId: data.tertiaryProductId,
|
|
3311
3407
|
currentLanguage: getCurrentLanguage(),
|
|
3312
3408
|
defaultLanguage: getDefaultLanguage()
|
|
3313
3409
|
}
|
|
@@ -3347,7 +3443,7 @@ function getNativeWebView() {
|
|
|
3347
3443
|
if (NativeWebViewComponent) return NativeWebViewComponent;
|
|
3348
3444
|
if (nativeWebViewLookupFailed) return null;
|
|
3349
3445
|
try {
|
|
3350
|
-
NativeWebViewComponent = (0,
|
|
3446
|
+
NativeWebViewComponent = (0, import_react_native15.requireNativeComponent)("PaywalloWebView");
|
|
3351
3447
|
return NativeWebViewComponent;
|
|
3352
3448
|
} catch {
|
|
3353
3449
|
nativeWebViewLookupFailed = true;
|
|
@@ -3356,9 +3452,9 @@ function getNativeWebView() {
|
|
|
3356
3452
|
}
|
|
3357
3453
|
function getWebViewEmitter() {
|
|
3358
3454
|
if (webViewEmitter) return webViewEmitter;
|
|
3359
|
-
const mod =
|
|
3455
|
+
const mod = import_react_native15.NativeModules.PaywalloWebViewModule;
|
|
3360
3456
|
if (!mod) return null;
|
|
3361
|
-
webViewEmitter = new
|
|
3457
|
+
webViewEmitter = new import_react_native15.NativeEventEmitter(mod);
|
|
3362
3458
|
return webViewEmitter;
|
|
3363
3459
|
}
|
|
3364
3460
|
async function triggerNativeHaptic(style) {
|
|
@@ -3392,6 +3488,7 @@ function PaywallWebView({
|
|
|
3392
3488
|
products,
|
|
3393
3489
|
primaryProductId,
|
|
3394
3490
|
secondaryProductId,
|
|
3491
|
+
tertiaryProductId,
|
|
3395
3492
|
isPurchasing,
|
|
3396
3493
|
webUrl: webUrlProp,
|
|
3397
3494
|
onPurchase,
|
|
@@ -3400,16 +3497,16 @@ function PaywallWebView({
|
|
|
3400
3497
|
onReady,
|
|
3401
3498
|
onError
|
|
3402
3499
|
}) {
|
|
3403
|
-
const paywallDataSent = (0,
|
|
3404
|
-
const loadEndReceived = (0,
|
|
3405
|
-
const [scriptToInject, setScriptToInject] = (0,
|
|
3406
|
-
const webViewRef = (0,
|
|
3407
|
-
const onErrorRef = (0,
|
|
3500
|
+
const paywallDataSent = (0, import_react4.useRef)(false);
|
|
3501
|
+
const loadEndReceived = (0, import_react4.useRef)(false);
|
|
3502
|
+
const [scriptToInject, setScriptToInject] = (0, import_react4.useState)(void 0);
|
|
3503
|
+
const webViewRef = (0, import_react4.useRef)(null);
|
|
3504
|
+
const onErrorRef = (0, import_react4.useRef)(onError);
|
|
3408
3505
|
onErrorRef.current = onError;
|
|
3409
|
-
const onReadyRef = (0,
|
|
3506
|
+
const onReadyRef = (0, import_react4.useRef)(onReady);
|
|
3410
3507
|
onReadyRef.current = onReady;
|
|
3411
|
-
const NativeWebView = (0,
|
|
3412
|
-
(0,
|
|
3508
|
+
const NativeWebView = (0, import_react4.useMemo)(() => getNativeWebView(), []);
|
|
3509
|
+
(0, import_react4.useEffect)(() => {
|
|
3413
3510
|
if (!NativeWebView) {
|
|
3414
3511
|
onErrorRef.current?.({
|
|
3415
3512
|
code: -1,
|
|
@@ -3417,10 +3514,10 @@ function PaywallWebView({
|
|
|
3417
3514
|
});
|
|
3418
3515
|
}
|
|
3419
3516
|
}, [NativeWebView]);
|
|
3420
|
-
const [resolvedWebUrl, setResolvedWebUrl] = (0,
|
|
3517
|
+
const [resolvedWebUrl, setResolvedWebUrl] = (0, import_react4.useState)(
|
|
3421
3518
|
() => webUrlProp ?? PaywalloClient.getWebUrl()
|
|
3422
3519
|
);
|
|
3423
|
-
(0,
|
|
3520
|
+
(0, import_react4.useEffect)(() => {
|
|
3424
3521
|
if (webUrlProp !== void 0) {
|
|
3425
3522
|
setResolvedWebUrl(webUrlProp ?? null);
|
|
3426
3523
|
return;
|
|
@@ -3439,7 +3536,7 @@ function PaywallWebView({
|
|
|
3439
3536
|
}, 200);
|
|
3440
3537
|
return () => clearInterval(interval);
|
|
3441
3538
|
}, [webUrlProp]);
|
|
3442
|
-
(0,
|
|
3539
|
+
(0, import_react4.useEffect)(() => {
|
|
3443
3540
|
if (!resolvedWebUrl) {
|
|
3444
3541
|
onErrorRef.current?.({
|
|
3445
3542
|
code: -1,
|
|
@@ -3447,36 +3544,37 @@ function PaywallWebView({
|
|
|
3447
3544
|
});
|
|
3448
3545
|
}
|
|
3449
3546
|
}, []);
|
|
3450
|
-
const injectScript = (0,
|
|
3451
|
-
if (
|
|
3452
|
-
const handle = (0,
|
|
3547
|
+
const injectScript = (0, import_react4.useCallback)((script) => {
|
|
3548
|
+
if (import_react_native15.Platform.OS === "android") {
|
|
3549
|
+
const handle = (0, import_react_native15.findNodeHandle)(webViewRef.current);
|
|
3453
3550
|
if (handle == null) return;
|
|
3454
|
-
|
|
3551
|
+
import_react_native15.UIManager.dispatchViewManagerCommand(handle, "injectJavaScript", [script]);
|
|
3455
3552
|
return;
|
|
3456
3553
|
}
|
|
3457
3554
|
setScriptToInject(script);
|
|
3458
3555
|
}, []);
|
|
3459
|
-
const buildAndSetInjectionScript = (0,
|
|
3556
|
+
const buildAndSetInjectionScript = (0, import_react4.useCallback)(() => {
|
|
3460
3557
|
if (!craftData || paywallDataSent.current) return;
|
|
3461
3558
|
paywallDataSent.current = true;
|
|
3462
3559
|
const script = buildPaywallInjectionScript({
|
|
3463
3560
|
craftData,
|
|
3464
3561
|
products: Array.from(products.values()),
|
|
3465
3562
|
primaryProductId,
|
|
3466
|
-
secondaryProductId
|
|
3563
|
+
secondaryProductId,
|
|
3564
|
+
tertiaryProductId
|
|
3467
3565
|
});
|
|
3468
3566
|
injectScript(script);
|
|
3469
|
-
}, [craftData, products, primaryProductId, secondaryProductId, injectScript]);
|
|
3470
|
-
const processedIdsRef = (0,
|
|
3471
|
-
const dedupeTimersRef = (0,
|
|
3472
|
-
(0,
|
|
3567
|
+
}, [craftData, products, primaryProductId, secondaryProductId, tertiaryProductId, injectScript]);
|
|
3568
|
+
const processedIdsRef = (0, import_react4.useRef)(/* @__PURE__ */ new Set());
|
|
3569
|
+
const dedupeTimersRef = (0, import_react4.useRef)(/* @__PURE__ */ new Map());
|
|
3570
|
+
(0, import_react4.useEffect)(() => {
|
|
3473
3571
|
return () => {
|
|
3474
3572
|
for (const timerId of dedupeTimersRef.current.values()) clearTimeout(timerId);
|
|
3475
3573
|
dedupeTimersRef.current.clear();
|
|
3476
3574
|
processedIdsRef.current.clear();
|
|
3477
3575
|
};
|
|
3478
3576
|
}, []);
|
|
3479
|
-
const handleParsedMessage = (0,
|
|
3577
|
+
const handleParsedMessage = (0, import_react4.useCallback)(
|
|
3480
3578
|
(message) => {
|
|
3481
3579
|
const msgId = deriveMessageId(message);
|
|
3482
3580
|
if (processedIdsRef.current.has(msgId)) return;
|
|
@@ -3510,7 +3608,7 @@ function PaywallWebView({
|
|
|
3510
3608
|
if (message.payload?.url) {
|
|
3511
3609
|
const url = message.payload.url;
|
|
3512
3610
|
if (/^https?:\/\//i.test(url) || /^mailto:/i.test(url) || /^itms-apps:/i.test(url) || /^market:/i.test(url)) {
|
|
3513
|
-
void
|
|
3611
|
+
void import_react_native15.Linking.openURL(url);
|
|
3514
3612
|
}
|
|
3515
3613
|
}
|
|
3516
3614
|
break;
|
|
@@ -3521,7 +3619,7 @@ function PaywallWebView({
|
|
|
3521
3619
|
},
|
|
3522
3620
|
[buildAndSetInjectionScript, onPurchase, onClose, onRestore]
|
|
3523
3621
|
);
|
|
3524
|
-
(0,
|
|
3622
|
+
(0, import_react4.useEffect)(() => {
|
|
3525
3623
|
const emitter = getWebViewEmitter();
|
|
3526
3624
|
if (!emitter) return;
|
|
3527
3625
|
const loadEndSub = emitter.addListener("PaywalloWebViewLoadEnd", () => {
|
|
@@ -3546,7 +3644,7 @@ function PaywallWebView({
|
|
|
3546
3644
|
errorSub.remove();
|
|
3547
3645
|
};
|
|
3548
3646
|
}, [buildAndSetInjectionScript, handleParsedMessage]);
|
|
3549
|
-
(0,
|
|
3647
|
+
(0, import_react4.useEffect)(() => {
|
|
3550
3648
|
const timer = setTimeout(() => {
|
|
3551
3649
|
if (!paywallDataSent.current) {
|
|
3552
3650
|
onErrorRef.current?.({
|
|
@@ -3557,13 +3655,13 @@ function PaywallWebView({
|
|
|
3557
3655
|
}, 1e4);
|
|
3558
3656
|
return () => clearTimeout(timer);
|
|
3559
3657
|
}, []);
|
|
3560
|
-
const handleLoadEnd = (0,
|
|
3658
|
+
const handleLoadEnd = (0, import_react4.useCallback)(() => {
|
|
3561
3659
|
if (!loadEndReceived.current) {
|
|
3562
3660
|
loadEndReceived.current = true;
|
|
3563
3661
|
buildAndSetInjectionScript();
|
|
3564
3662
|
}
|
|
3565
3663
|
}, [buildAndSetInjectionScript]);
|
|
3566
|
-
const handleNativeError = (0,
|
|
3664
|
+
const handleNativeError = (0, import_react4.useCallback)((event) => {
|
|
3567
3665
|
const ne = event.nativeEvent;
|
|
3568
3666
|
let errorData;
|
|
3569
3667
|
if (ne["payload"] && typeof ne["payload"] === "object") {
|
|
@@ -3579,30 +3677,30 @@ function PaywallWebView({
|
|
|
3579
3677
|
}
|
|
3580
3678
|
onErrorRef.current?.(parseErrorEvent(errorData));
|
|
3581
3679
|
}, []);
|
|
3582
|
-
const handleMessage = (0,
|
|
3680
|
+
const handleMessage = (0, import_react4.useCallback)(
|
|
3583
3681
|
(event) => {
|
|
3584
3682
|
const message = parseWebViewMessage(event.nativeEvent.data);
|
|
3585
3683
|
if (message) handleParsedMessage(message);
|
|
3586
3684
|
},
|
|
3587
3685
|
[handleParsedMessage]
|
|
3588
3686
|
);
|
|
3589
|
-
(0,
|
|
3687
|
+
(0, import_react4.useEffect)(() => {
|
|
3590
3688
|
if (!paywallDataSent.current) return;
|
|
3591
3689
|
injectScript(buildPurchaseStateScript(isPurchasing));
|
|
3592
3690
|
}, [isPurchasing, injectScript]);
|
|
3593
|
-
(0,
|
|
3594
|
-
if (
|
|
3691
|
+
(0, import_react4.useEffect)(() => {
|
|
3692
|
+
if (import_react_native15.Platform.OS !== "android") return;
|
|
3595
3693
|
const onBackPress = () => {
|
|
3596
3694
|
if (!paywallDataSent.current) return false;
|
|
3597
3695
|
injectScript(buildBackButtonScript());
|
|
3598
3696
|
return true;
|
|
3599
3697
|
};
|
|
3600
|
-
const subscription =
|
|
3698
|
+
const subscription = import_react_native15.BackHandler.addEventListener("hardwareBackPress", onBackPress);
|
|
3601
3699
|
return () => subscription.remove();
|
|
3602
3700
|
}, [injectScript]);
|
|
3603
3701
|
if (!resolvedWebUrl || !NativeWebView) return null;
|
|
3604
3702
|
const paywallUrl = `${resolvedWebUrl}/paywall/${paywallId}`;
|
|
3605
|
-
return /* @__PURE__ */ (0,
|
|
3703
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native15.View, { style: styles2.container, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
3606
3704
|
NativeWebView,
|
|
3607
3705
|
{
|
|
3608
3706
|
ref: webViewRef,
|
|
@@ -3611,24 +3709,24 @@ function PaywallWebView({
|
|
|
3611
3709
|
onMessage: handleMessage,
|
|
3612
3710
|
onLoadEnd: handleLoadEnd,
|
|
3613
3711
|
onError: handleNativeError,
|
|
3614
|
-
style:
|
|
3712
|
+
style: styles2.webview
|
|
3615
3713
|
}
|
|
3616
3714
|
) });
|
|
3617
3715
|
}
|
|
3618
|
-
var
|
|
3716
|
+
var import_react4, import_react_native15, import_jsx_runtime2, NativeWebViewComponent, nativeWebViewLookupFailed, webViewEmitter, styles2;
|
|
3619
3717
|
var init_PaywallWebView = __esm({
|
|
3620
3718
|
"src/domains/paywall/PaywallWebView.tsx"() {
|
|
3621
3719
|
"use strict";
|
|
3622
|
-
|
|
3623
|
-
|
|
3720
|
+
import_react4 = require("react");
|
|
3721
|
+
import_react_native15 = require("react-native");
|
|
3624
3722
|
init_PaywalloClient();
|
|
3625
3723
|
init_parseWebViewMessage();
|
|
3626
3724
|
init_paywallScripts();
|
|
3627
|
-
|
|
3725
|
+
import_jsx_runtime2 = require("react/jsx-runtime");
|
|
3628
3726
|
NativeWebViewComponent = null;
|
|
3629
3727
|
nativeWebViewLookupFailed = false;
|
|
3630
3728
|
webViewEmitter = null;
|
|
3631
|
-
|
|
3729
|
+
styles2 = import_react_native15.StyleSheet.create({
|
|
3632
3730
|
container: { flex: 1 },
|
|
3633
3731
|
webview: { flex: 1, backgroundColor: "transparent" }
|
|
3634
3732
|
});
|
|
@@ -3763,7 +3861,7 @@ function mapNativePurchase(native) {
|
|
|
3763
3861
|
transactionId: native.transactionId,
|
|
3764
3862
|
transactionDate: native.transactionDate,
|
|
3765
3863
|
receipt: native.receipt,
|
|
3766
|
-
platform:
|
|
3864
|
+
platform: import_react_native16.Platform.OS
|
|
3767
3865
|
};
|
|
3768
3866
|
}
|
|
3769
3867
|
function normalizeTransactionUpdate(raw) {
|
|
@@ -3783,17 +3881,17 @@ function normalizeTransactionUpdate(raw) {
|
|
|
3783
3881
|
if (typeof r.currency === "string") update.currency = r.currency;
|
|
3784
3882
|
return update;
|
|
3785
3883
|
}
|
|
3786
|
-
var
|
|
3884
|
+
var import_react_native16, TRANSACTION_UPDATE_EVENT, PaywalloStoreKitNative, nativeStoreKit, NativeStoreKit;
|
|
3787
3885
|
var init_NativeStoreKit = __esm({
|
|
3788
3886
|
"src/domains/iap/NativeStoreKit.ts"() {
|
|
3789
3887
|
"use strict";
|
|
3790
|
-
|
|
3888
|
+
import_react_native16 = require("react-native");
|
|
3791
3889
|
init_PaywalloClient();
|
|
3792
3890
|
init_uuid();
|
|
3793
3891
|
init_IdentityManager();
|
|
3794
3892
|
init_PurchaseError();
|
|
3795
3893
|
TRANSACTION_UPDATE_EVENT = "PaywalloTransactionUpdate";
|
|
3796
|
-
PaywalloStoreKitNative =
|
|
3894
|
+
PaywalloStoreKitNative = import_react_native16.NativeModules.PaywalloStoreKit ?? null;
|
|
3797
3895
|
nativeStoreKit = {
|
|
3798
3896
|
isAvailable: isAvailable3,
|
|
3799
3897
|
async getProducts(productIds) {
|
|
@@ -3862,7 +3960,7 @@ var init_NativeStoreKit = __esm({
|
|
|
3862
3960
|
subscribeToTransactionUpdates(listener) {
|
|
3863
3961
|
if (!PaywalloStoreKitNative) return null;
|
|
3864
3962
|
try {
|
|
3865
|
-
const EmitterCtor =
|
|
3963
|
+
const EmitterCtor = import_react_native16.NativeEventEmitter;
|
|
3866
3964
|
const emitter = new EmitterCtor(PaywalloStoreKitNative);
|
|
3867
3965
|
const sub = emitter.addListener(TRANSACTION_UPDATE_EVENT, (payload) => {
|
|
3868
3966
|
const update = normalizeTransactionUpdate(payload);
|
|
@@ -4518,11 +4616,11 @@ var init_types2 = __esm({
|
|
|
4518
4616
|
});
|
|
4519
4617
|
|
|
4520
4618
|
// src/core/network/NetworkMonitor.ts
|
|
4521
|
-
var
|
|
4619
|
+
var import_react_native17, NetworkMonitorClass, networkMonitor;
|
|
4522
4620
|
var init_NetworkMonitor = __esm({
|
|
4523
4621
|
"src/core/network/NetworkMonitor.ts"() {
|
|
4524
4622
|
"use strict";
|
|
4525
|
-
|
|
4623
|
+
import_react_native17 = require("react-native");
|
|
4526
4624
|
init_types2();
|
|
4527
4625
|
NetworkMonitorClass = class {
|
|
4528
4626
|
constructor() {
|
|
@@ -4551,7 +4649,7 @@ var init_NetworkMonitor = __esm({
|
|
|
4551
4649
|
}, this.config.checkInterval);
|
|
4552
4650
|
}
|
|
4553
4651
|
setupAppStateListener() {
|
|
4554
|
-
this.appStateSubscription =
|
|
4652
|
+
this.appStateSubscription = import_react_native17.AppState.addEventListener("change", (state) => {
|
|
4555
4653
|
if (state === "active") {
|
|
4556
4654
|
if (!this.checkIntervalId) {
|
|
4557
4655
|
this.checkIntervalId = setInterval(() => {
|
|
@@ -4920,11 +5018,11 @@ var init_queue = __esm({
|
|
|
4920
5018
|
});
|
|
4921
5019
|
|
|
4922
5020
|
// src/domains/iap/IAPValidator.ts
|
|
4923
|
-
var
|
|
5021
|
+
var import_react_native18, IAPValidator;
|
|
4924
5022
|
var init_IAPValidator = __esm({
|
|
4925
5023
|
"src/domains/iap/IAPValidator.ts"() {
|
|
4926
5024
|
"use strict";
|
|
4927
|
-
|
|
5025
|
+
import_react_native18 = require("react-native");
|
|
4928
5026
|
init_PaywalloClient();
|
|
4929
5027
|
init_queue();
|
|
4930
5028
|
init_PurchaseError();
|
|
@@ -4950,7 +5048,7 @@ var init_IAPValidator = __esm({
|
|
|
4950
5048
|
async validateWithServer(purchase, productId, options) {
|
|
4951
5049
|
const apiClient = this.getApiClientFn();
|
|
4952
5050
|
const product = this.getProductFromCache(productId);
|
|
4953
|
-
const platform =
|
|
5051
|
+
const platform = import_react_native18.Platform.OS;
|
|
4954
5052
|
const distinctId = PaywalloClient.getDistinctId();
|
|
4955
5053
|
return this.validateWithRetry(
|
|
4956
5054
|
() => apiClient.validatePurchase(
|
|
@@ -4985,7 +5083,7 @@ var init_IAPValidator = __esm({
|
|
|
4985
5083
|
try {
|
|
4986
5084
|
const apiClient = this.getApiClientFn();
|
|
4987
5085
|
const product = this.getProductFromCache(productId);
|
|
4988
|
-
const platform =
|
|
5086
|
+
const platform = import_react_native18.Platform.OS;
|
|
4989
5087
|
const distinctId = PaywalloClient.getDistinctId();
|
|
4990
5088
|
const appKey = apiClient.getAppKey();
|
|
4991
5089
|
const body = {
|
|
@@ -5025,11 +5123,11 @@ function getIAPService() {
|
|
|
5025
5123
|
}
|
|
5026
5124
|
return _instance;
|
|
5027
5125
|
}
|
|
5028
|
-
var
|
|
5126
|
+
var import_react_native19, IAPService, _instance;
|
|
5029
5127
|
var init_IAPService = __esm({
|
|
5030
5128
|
"src/domains/iap/IAPService.ts"() {
|
|
5031
5129
|
"use strict";
|
|
5032
|
-
|
|
5130
|
+
import_react_native19 = require("react-native");
|
|
5033
5131
|
init_PaywalloClient();
|
|
5034
5132
|
init_IAPTransactionEmitter();
|
|
5035
5133
|
init_IAPValidator();
|
|
@@ -5179,7 +5277,7 @@ var init_IAPService = __esm({
|
|
|
5179
5277
|
const transactions = await nativeStoreKit.getActiveTransactions();
|
|
5180
5278
|
const apiClient = this.getApiClient();
|
|
5181
5279
|
const distinctId = PaywalloClient.getDistinctId();
|
|
5182
|
-
const platform =
|
|
5280
|
+
const platform = import_react_native19.Platform.OS;
|
|
5183
5281
|
const results = await Promise.allSettled(
|
|
5184
5282
|
transactions.map((tx) => {
|
|
5185
5283
|
const product = this.productsCache.get(tx.productId);
|
|
@@ -5237,11 +5335,11 @@ var init_IAPService = __esm({
|
|
|
5237
5335
|
|
|
5238
5336
|
// src/domains/paywall/usePaywallTracking.ts
|
|
5239
5337
|
function usePaywallTracking() {
|
|
5240
|
-
const trackClosed = (0,
|
|
5338
|
+
const trackClosed = (0, import_react5.useCallback)(async (opts) => {
|
|
5241
5339
|
await emitPaywallClosed(opts);
|
|
5242
5340
|
await stopHeartbeat();
|
|
5243
5341
|
}, []);
|
|
5244
|
-
const trackDismissed = (0,
|
|
5342
|
+
const trackDismissed = (0, import_react5.useCallback)(async (opts) => {
|
|
5245
5343
|
const presentedAt = Date.now() - Math.max(0, opts.duration_ms);
|
|
5246
5344
|
await trackClosed({
|
|
5247
5345
|
placement: opts.placement,
|
|
@@ -5253,17 +5351,17 @@ function usePaywallTracking() {
|
|
|
5253
5351
|
...opts.variantId && { variantId: opts.variantId }
|
|
5254
5352
|
});
|
|
5255
5353
|
}, [trackClosed]);
|
|
5256
|
-
const trackProductSelected = (0,
|
|
5354
|
+
const trackProductSelected = (0, import_react5.useCallback)((_opts) => {
|
|
5257
5355
|
}, []);
|
|
5258
|
-
const trackPurchased = (0,
|
|
5356
|
+
const trackPurchased = (0, import_react5.useCallback)(async (_opts) => {
|
|
5259
5357
|
}, []);
|
|
5260
5358
|
return { trackClosed, trackDismissed, trackProductSelected, trackPurchased };
|
|
5261
5359
|
}
|
|
5262
|
-
var
|
|
5360
|
+
var import_react5;
|
|
5263
5361
|
var init_usePaywallTracking = __esm({
|
|
5264
5362
|
"src/domains/paywall/usePaywallTracking.ts"() {
|
|
5265
5363
|
"use strict";
|
|
5266
|
-
|
|
5364
|
+
import_react5 = require("react");
|
|
5267
5365
|
init_emitPaywallClosed();
|
|
5268
5366
|
init_paywallHeartbeat();
|
|
5269
5367
|
}
|
|
@@ -5271,19 +5369,19 @@ var init_usePaywallTracking = __esm({
|
|
|
5271
5369
|
|
|
5272
5370
|
// src/domains/paywall/usePaywallActions.ts
|
|
5273
5371
|
function usePaywallActions(placement, paywallConfig, onResult, variantKey, campaignId, openAnim, variantId) {
|
|
5274
|
-
const [isPurchasing, setIsPurchasing] = (0,
|
|
5275
|
-
const isPurchasingRef = (0,
|
|
5276
|
-
const [isClosing, setIsClosing] = (0,
|
|
5277
|
-
const slideAnim = (0,
|
|
5278
|
-
const presentedAtRef = (0,
|
|
5279
|
-
const closedRef = (0,
|
|
5372
|
+
const [isPurchasing, setIsPurchasing] = (0, import_react6.useState)(false);
|
|
5373
|
+
const isPurchasingRef = (0, import_react6.useRef)(false);
|
|
5374
|
+
const [isClosing, setIsClosing] = (0, import_react6.useState)(false);
|
|
5375
|
+
const slideAnim = (0, import_react6.useRef)(new import_react_native20.Animated.Value(0)).current;
|
|
5376
|
+
const presentedAtRef = (0, import_react6.useRef)(Date.now());
|
|
5377
|
+
const closedRef = (0, import_react6.useRef)(false);
|
|
5280
5378
|
const { trackDismissed, trackProductSelected, trackPurchased } = usePaywallTracking();
|
|
5281
|
-
const closeWithReason = (0,
|
|
5379
|
+
const closeWithReason = (0, import_react6.useCallback)((reason, resultOverride) => {
|
|
5282
5380
|
if (closedRef.current) return;
|
|
5283
5381
|
closedRef.current = true;
|
|
5284
5382
|
const animTarget = openAnim ?? slideAnim;
|
|
5285
|
-
|
|
5286
|
-
toValue:
|
|
5383
|
+
import_react_native20.Animated.timing(animTarget, {
|
|
5384
|
+
toValue: import_react_native20.Dimensions.get("window").height,
|
|
5287
5385
|
duration: 350,
|
|
5288
5386
|
useNativeDriver: true
|
|
5289
5387
|
}).start(() => {
|
|
@@ -5297,13 +5395,13 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
5297
5395
|
onResult(resultOverride ?? { presented: true, purchased: false, cancelled: true, restored: false });
|
|
5298
5396
|
});
|
|
5299
5397
|
}, [openAnim, slideAnim, paywallConfig, placement, trackDismissed, variantKey, campaignId, variantId, onResult]);
|
|
5300
|
-
const handleClose = (0,
|
|
5398
|
+
const handleClose = (0, import_react6.useCallback)(() => {
|
|
5301
5399
|
if (isClosing) return;
|
|
5302
5400
|
setIsClosing(true);
|
|
5303
5401
|
closeWithReason("dismissed");
|
|
5304
5402
|
}, [isClosing, closeWithReason]);
|
|
5305
|
-
(0,
|
|
5306
|
-
const sub =
|
|
5403
|
+
(0, import_react6.useEffect)(() => {
|
|
5404
|
+
const sub = import_react_native20.AppState.addEventListener("change", (nextState) => {
|
|
5307
5405
|
if (isPurchasingRef.current) return;
|
|
5308
5406
|
if (nextState === "background" || nextState === "inactive") {
|
|
5309
5407
|
closeWithReason("backgrounded");
|
|
@@ -5311,13 +5409,13 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
5311
5409
|
});
|
|
5312
5410
|
return () => sub.remove();
|
|
5313
5411
|
}, [closeWithReason]);
|
|
5314
|
-
(0,
|
|
5412
|
+
(0, import_react6.useEffect)(() => {
|
|
5315
5413
|
const timer = setTimeout(() => {
|
|
5316
5414
|
closeWithReason("timeout");
|
|
5317
5415
|
}, PAYWALL_TIMEOUT_MS);
|
|
5318
5416
|
return () => clearTimeout(timer);
|
|
5319
5417
|
}, [closeWithReason]);
|
|
5320
|
-
const handlePurchase = (0,
|
|
5418
|
+
const handlePurchase = (0, import_react6.useCallback)(async (productId) => {
|
|
5321
5419
|
if (isPurchasing) return;
|
|
5322
5420
|
setIsPurchasing(true);
|
|
5323
5421
|
isPurchasingRef.current = true;
|
|
@@ -5347,7 +5445,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
5347
5445
|
setIsPurchasing(false);
|
|
5348
5446
|
}
|
|
5349
5447
|
}, [isPurchasing, onResult, paywallConfig, placement, trackDismissed, trackProductSelected, trackPurchased, variantKey, campaignId, variantId]);
|
|
5350
|
-
const handleRestore = (0,
|
|
5448
|
+
const handleRestore = (0, import_react6.useCallback)(async () => {
|
|
5351
5449
|
if (isPurchasing) return;
|
|
5352
5450
|
setIsPurchasing(true);
|
|
5353
5451
|
isPurchasingRef.current = true;
|
|
@@ -5371,12 +5469,12 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
|
|
|
5371
5469
|
}, [isPurchasing, onResult, paywallConfig, placement, trackDismissed, variantKey, campaignId, variantId]);
|
|
5372
5470
|
return { isPurchasing, slideAnim, handleClose, handlePurchase, handleRestore };
|
|
5373
5471
|
}
|
|
5374
|
-
var
|
|
5472
|
+
var import_react6, import_react_native20, PAYWALL_TIMEOUT_MS;
|
|
5375
5473
|
var init_usePaywallActions = __esm({
|
|
5376
5474
|
"src/domains/paywall/usePaywallActions.ts"() {
|
|
5377
5475
|
"use strict";
|
|
5378
|
-
|
|
5379
|
-
|
|
5476
|
+
import_react6 = require("react");
|
|
5477
|
+
import_react_native20 = require("react-native");
|
|
5380
5478
|
init_IAPService();
|
|
5381
5479
|
init_usePaywallTracking();
|
|
5382
5480
|
PAYWALL_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
@@ -5385,15 +5483,15 @@ var init_usePaywallActions = __esm({
|
|
|
5385
5483
|
|
|
5386
5484
|
// src/domains/paywall/usePaywallLoader.ts
|
|
5387
5485
|
function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts, variantKey, campaignId, variantId) {
|
|
5388
|
-
const [error, setError] = (0,
|
|
5389
|
-
const [paywallConfig, setPaywallConfig] = (0,
|
|
5390
|
-
const [products, setProducts] = (0,
|
|
5391
|
-
const preloadedConfigRef = (0,
|
|
5486
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
5487
|
+
const [paywallConfig, setPaywallConfig] = (0, import_react7.useState)(null);
|
|
5488
|
+
const [products, setProducts] = (0, import_react7.useState)(/* @__PURE__ */ new Map());
|
|
5489
|
+
const preloadedConfigRef = (0, import_react7.useRef)(preloadedConfig);
|
|
5392
5490
|
preloadedConfigRef.current = preloadedConfig;
|
|
5393
|
-
const preloadedProductsRef = (0,
|
|
5491
|
+
const preloadedProductsRef = (0, import_react7.useRef)(preloadedProducts);
|
|
5394
5492
|
preloadedProductsRef.current = preloadedProducts;
|
|
5395
|
-
const trackingDoneRef = (0,
|
|
5396
|
-
(0,
|
|
5493
|
+
const trackingDoneRef = (0, import_react7.useRef)(false);
|
|
5494
|
+
(0, import_react7.useEffect)(() => {
|
|
5397
5495
|
if (!visible) {
|
|
5398
5496
|
trackingDoneRef.current = false;
|
|
5399
5497
|
return;
|
|
@@ -5412,7 +5510,8 @@ function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts
|
|
|
5412
5510
|
placement: snap.placement,
|
|
5413
5511
|
config: snap.config,
|
|
5414
5512
|
primaryProductId: snap.primaryProductId,
|
|
5415
|
-
secondaryProductId: snap.secondaryProductId
|
|
5513
|
+
secondaryProductId: snap.secondaryProductId,
|
|
5514
|
+
tertiaryProductId: snap.tertiaryProductId
|
|
5416
5515
|
};
|
|
5417
5516
|
} else {
|
|
5418
5517
|
const fetched = await apiClient.getPaywall(placement);
|
|
@@ -5424,6 +5523,7 @@ function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts
|
|
|
5424
5523
|
const productIds = [];
|
|
5425
5524
|
if (config.primaryProductId) productIds.push(config.primaryProductId);
|
|
5426
5525
|
if (config.secondaryProductId) productIds.push(config.secondaryProductId);
|
|
5526
|
+
if (config.tertiaryProductId) productIds.push(config.tertiaryProductId);
|
|
5427
5527
|
const snapProducts = preloadedProductsRef.current;
|
|
5428
5528
|
if (snapProducts && snapProducts.size > 0) {
|
|
5429
5529
|
if (!cancelled) setProducts(snapProducts);
|
|
@@ -5478,11 +5578,11 @@ function usePaywallLoader(placement, visible, preloadedConfig, preloadedProducts
|
|
|
5478
5578
|
}, [placement, visible, variantKey, campaignId, variantId]);
|
|
5479
5579
|
return { paywallConfig, products, error };
|
|
5480
5580
|
}
|
|
5481
|
-
var
|
|
5581
|
+
var import_react7;
|
|
5482
5582
|
var init_usePaywallLoader = __esm({
|
|
5483
5583
|
"src/domains/paywall/usePaywallLoader.ts"() {
|
|
5484
5584
|
"use strict";
|
|
5485
|
-
|
|
5585
|
+
import_react7 = require("react");
|
|
5486
5586
|
init_PaywalloClient();
|
|
5487
5587
|
init_IAPService();
|
|
5488
5588
|
init_PaywallError();
|
|
@@ -5495,11 +5595,11 @@ function ErrorFallback({ description, onRetry, onClose }) {
|
|
|
5495
5595
|
const title = overrides?.title ?? getSdkString("paywallErrorTitle");
|
|
5496
5596
|
const retryLabel = overrides?.retry ?? getSdkString("paywallRetryButton");
|
|
5497
5597
|
const closeLabel = overrides?.close ?? getSdkString("paywallCloseButton");
|
|
5498
|
-
return /* @__PURE__ */ (0,
|
|
5499
|
-
/* @__PURE__ */ (0,
|
|
5500
|
-
/* @__PURE__ */ (0,
|
|
5501
|
-
/* @__PURE__ */ (0,
|
|
5502
|
-
/* @__PURE__ */ (0,
|
|
5598
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.View, { style: styles3.fallbackContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native21.View, { style: styles3.fallbackCard, children: [
|
|
5599
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Text, { style: styles3.fallbackTitle, children: title }),
|
|
5600
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Text, { style: styles3.fallbackDescription, children: description }),
|
|
5601
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Pressable, { style: styles3.retryButton, onPress: onRetry, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Text, { style: styles3.retryButtonText, children: retryLabel }) }),
|
|
5602
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Pressable, { style: styles3.closeButton, onPress: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Text, { style: styles3.closeButtonText, children: closeLabel }) })
|
|
5503
5603
|
] }) });
|
|
5504
5604
|
}
|
|
5505
5605
|
function PaywallModal({
|
|
@@ -5521,18 +5621,20 @@ function PaywallModal({
|
|
|
5521
5621
|
campaignId,
|
|
5522
5622
|
variantId
|
|
5523
5623
|
);
|
|
5524
|
-
const screenHeight =
|
|
5525
|
-
const openAnim = (0,
|
|
5526
|
-
const [modalVisible, setModalVisible] = (0,
|
|
5527
|
-
const handleResult = (0,
|
|
5624
|
+
const screenHeight = import_react_native21.Dimensions.get("window").height;
|
|
5625
|
+
const openAnim = (0, import_react8.useRef)(new import_react_native21.Animated.Value(screenHeight)).current;
|
|
5626
|
+
const [modalVisible, setModalVisible] = (0, import_react8.useState)(false);
|
|
5627
|
+
const handleResult = (0, import_react8.useCallback)((result) => {
|
|
5528
5628
|
setModalVisible(false);
|
|
5529
5629
|
onResult(result);
|
|
5530
5630
|
}, [onResult]);
|
|
5531
5631
|
const { isPurchasing, slideAnim, handleClose, handlePurchase, handleRestore } = usePaywallActions(placement, paywallConfig, handleResult, variantKey, campaignId, openAnim, variantId);
|
|
5532
|
-
const [webViewError, setWebViewError] = (0,
|
|
5533
|
-
const [retryCount, setRetryCount] = (0,
|
|
5534
|
-
const
|
|
5535
|
-
const
|
|
5632
|
+
const [webViewError, setWebViewError] = (0, import_react8.useState)(null);
|
|
5633
|
+
const [retryCount, setRetryCount] = (0, import_react8.useState)(0);
|
|
5634
|
+
const [showSkeleton, setShowSkeleton] = (0, import_react8.useState)(true);
|
|
5635
|
+
const skeletonOpacity = (0, import_react8.useRef)(new import_react_native21.Animated.Value(1)).current;
|
|
5636
|
+
const retryCountRef = (0, import_react8.useRef)(0);
|
|
5637
|
+
const handleWebViewError = (0, import_react8.useCallback)(
|
|
5536
5638
|
(err) => {
|
|
5537
5639
|
if (retryCountRef.current >= 1) {
|
|
5538
5640
|
setWebViewError({ code: err.code, description: err.description });
|
|
@@ -5543,26 +5645,44 @@ function PaywallModal({
|
|
|
5543
5645
|
},
|
|
5544
5646
|
[]
|
|
5545
5647
|
);
|
|
5546
|
-
const handleRetry = (0,
|
|
5648
|
+
const handleRetry = (0, import_react8.useCallback)(() => {
|
|
5547
5649
|
retryCountRef.current = 0;
|
|
5548
5650
|
setWebViewError(null);
|
|
5549
5651
|
setRetryCount(0);
|
|
5550
|
-
|
|
5551
|
-
|
|
5652
|
+
setShowSkeleton(true);
|
|
5653
|
+
skeletonOpacity.setValue(1);
|
|
5654
|
+
}, [skeletonOpacity]);
|
|
5655
|
+
const handleWebViewReady = (0, import_react8.useCallback)(() => {
|
|
5656
|
+
import_react_native21.Animated.timing(skeletonOpacity, {
|
|
5657
|
+
toValue: 0,
|
|
5658
|
+
duration: 250,
|
|
5659
|
+
easing: import_react_native21.Easing.out(import_react_native21.Easing.cubic),
|
|
5660
|
+
useNativeDriver: true
|
|
5661
|
+
}).start(() => setShowSkeleton(false));
|
|
5662
|
+
}, [skeletonOpacity]);
|
|
5663
|
+
(0, import_react8.useEffect)(() => {
|
|
5664
|
+
if (!visible || !showSkeleton) return;
|
|
5665
|
+
const timer = setTimeout(handleWebViewReady, 8e3);
|
|
5666
|
+
return () => clearTimeout(timer);
|
|
5667
|
+
}, [visible, showSkeleton, handleWebViewReady]);
|
|
5668
|
+
(0, import_react8.useEffect)(() => {
|
|
5552
5669
|
if (visible) {
|
|
5553
5670
|
setModalVisible(true);
|
|
5554
|
-
|
|
5555
|
-
|
|
5671
|
+
setShowSkeleton(true);
|
|
5672
|
+
skeletonOpacity.setValue(1);
|
|
5673
|
+
openAnim.setValue(import_react_native21.Dimensions.get("window").height);
|
|
5674
|
+
import_react_native21.Animated.timing(openAnim, {
|
|
5556
5675
|
toValue: 0,
|
|
5557
5676
|
duration: 550,
|
|
5558
|
-
easing:
|
|
5677
|
+
easing: import_react_native21.Easing.out(import_react_native21.Easing.cubic),
|
|
5559
5678
|
useNativeDriver: true
|
|
5560
5679
|
}).start();
|
|
5561
5680
|
}
|
|
5562
|
-
}, [visible, openAnim]);
|
|
5681
|
+
}, [visible, openAnim, skeletonOpacity]);
|
|
5563
5682
|
if (!modalVisible && !visible) return null;
|
|
5564
|
-
|
|
5565
|
-
|
|
5683
|
+
const skeletonBackground = paywallConfig && "craftData" in paywallConfig.config ? extractFirstPageBackground(paywallConfig.config.craftData) : "#FFFFFF";
|
|
5684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5685
|
+
import_react_native21.Modal,
|
|
5566
5686
|
{
|
|
5567
5687
|
visible: modalVisible,
|
|
5568
5688
|
animationType: "none",
|
|
@@ -5570,16 +5690,16 @@ function PaywallModal({
|
|
|
5570
5690
|
onRequestClose: handleClose,
|
|
5571
5691
|
transparent: true,
|
|
5572
5692
|
statusBarTranslucent: true,
|
|
5573
|
-
children: /* @__PURE__ */ (0,
|
|
5574
|
-
error && /* @__PURE__ */ (0,
|
|
5575
|
-
!error && paywallConfig && "craftData" in paywallConfig.config && /* @__PURE__ */ (0,
|
|
5693
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.View, { style: styles3.overlay, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Animated.View, { style: [styles3.animatedContainer, { transform: [{ translateY: openAnim }] }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native21.View, { style: styles3.container, children: [
|
|
5694
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.View, { style: styles3.errorContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Text, { style: styles3.errorText, children: error.message }) }),
|
|
5695
|
+
!error && paywallConfig && "craftData" in paywallConfig.config && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: webViewError ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5576
5696
|
ErrorFallback,
|
|
5577
5697
|
{
|
|
5578
5698
|
description: webViewError.description,
|
|
5579
5699
|
onRetry: handleRetry,
|
|
5580
5700
|
onClose: handleClose
|
|
5581
5701
|
}
|
|
5582
|
-
) : /* @__PURE__ */ (0,
|
|
5702
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5583
5703
|
PaywallWebView,
|
|
5584
5704
|
{
|
|
5585
5705
|
paywallId: paywallConfig.id,
|
|
@@ -5587,31 +5707,43 @@ function PaywallModal({
|
|
|
5587
5707
|
products,
|
|
5588
5708
|
primaryProductId: paywallConfig.primaryProductId,
|
|
5589
5709
|
secondaryProductId: paywallConfig.secondaryProductId,
|
|
5710
|
+
tertiaryProductId: paywallConfig.tertiaryProductId,
|
|
5590
5711
|
isPurchasing,
|
|
5712
|
+
onReady: handleWebViewReady,
|
|
5591
5713
|
onClose: handleClose,
|
|
5592
5714
|
onPurchase: handlePurchase,
|
|
5593
5715
|
onRestore: handleRestore,
|
|
5594
5716
|
onError: handleWebViewError
|
|
5595
5717
|
},
|
|
5596
5718
|
retryCount
|
|
5597
|
-
) })
|
|
5719
|
+
) }),
|
|
5720
|
+
showSkeleton && !error && !webViewError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
5721
|
+
import_react_native21.Animated.View,
|
|
5722
|
+
{
|
|
5723
|
+
style: [import_react_native21.StyleSheet.absoluteFill, { opacity: skeletonOpacity }],
|
|
5724
|
+
pointerEvents: "none",
|
|
5725
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PaywallSkeleton, { backgroundColor: skeletonBackground })
|
|
5726
|
+
}
|
|
5727
|
+
)
|
|
5598
5728
|
] }) }) })
|
|
5599
5729
|
}
|
|
5600
5730
|
);
|
|
5601
5731
|
}
|
|
5602
|
-
var
|
|
5732
|
+
var import_react8, import_react_native21, import_jsx_runtime3, styles3;
|
|
5603
5733
|
var init_PaywallModal = __esm({
|
|
5604
5734
|
"src/domains/paywall/PaywallModal.tsx"() {
|
|
5605
5735
|
"use strict";
|
|
5606
|
-
|
|
5607
|
-
|
|
5736
|
+
import_react8 = require("react");
|
|
5737
|
+
import_react_native21 = require("react-native");
|
|
5608
5738
|
init_PaywalloClient();
|
|
5609
5739
|
init_localization();
|
|
5740
|
+
init_extractFirstPageBackground();
|
|
5741
|
+
init_PaywallSkeleton();
|
|
5610
5742
|
init_PaywallWebView();
|
|
5611
5743
|
init_usePaywallActions();
|
|
5612
5744
|
init_usePaywallLoader();
|
|
5613
|
-
|
|
5614
|
-
|
|
5745
|
+
import_jsx_runtime3 = require("react/jsx-runtime");
|
|
5746
|
+
styles3 = import_react_native21.StyleSheet.create({
|
|
5615
5747
|
overlay: { flex: 1, backgroundColor: "rgba(0,0,0,0.3)" },
|
|
5616
5748
|
animatedContainer: { flex: 1, backgroundColor: "#fff" },
|
|
5617
5749
|
container: { flex: 1, backgroundColor: "#fff" },
|
|
@@ -5667,12 +5799,176 @@ var init_PaywallModal = __esm({
|
|
|
5667
5799
|
}
|
|
5668
5800
|
});
|
|
5669
5801
|
|
|
5802
|
+
// src/domains/paywall/PaywallPreloadService.ts
|
|
5803
|
+
var PRELOAD_TTL_MS, STALE_THRESHOLD, PaywallPreloadService, paywallPreloadService;
|
|
5804
|
+
var init_PaywallPreloadService = __esm({
|
|
5805
|
+
"src/domains/paywall/PaywallPreloadService.ts"() {
|
|
5806
|
+
"use strict";
|
|
5807
|
+
init_PaywalloClient();
|
|
5808
|
+
init_IAPService();
|
|
5809
|
+
init_PaywallError();
|
|
5810
|
+
PRELOAD_TTL_MS = 5 * 60 * 1e3;
|
|
5811
|
+
STALE_THRESHOLD = 0.75;
|
|
5812
|
+
PaywallPreloadService = class {
|
|
5813
|
+
constructor() {
|
|
5814
|
+
this.preloaded = /* @__PURE__ */ new Map();
|
|
5815
|
+
this.activePreloads = /* @__PURE__ */ new Map();
|
|
5816
|
+
this.apiClientRef = null;
|
|
5817
|
+
}
|
|
5818
|
+
async preload(apiClient, placement) {
|
|
5819
|
+
this.apiClientRef = apiClient;
|
|
5820
|
+
const existing = this.activePreloads.get(placement);
|
|
5821
|
+
if (existing) return existing;
|
|
5822
|
+
const promise = this.doPreload(apiClient, placement);
|
|
5823
|
+
this.activePreloads.set(placement, promise);
|
|
5824
|
+
try {
|
|
5825
|
+
return await promise;
|
|
5826
|
+
} finally {
|
|
5827
|
+
this.activePreloads.delete(placement);
|
|
5828
|
+
}
|
|
5829
|
+
}
|
|
5830
|
+
async preloadMany(apiClient, placements) {
|
|
5831
|
+
this.apiClientRef = apiClient;
|
|
5832
|
+
if (placements.length === 0) return;
|
|
5833
|
+
const debug = PaywalloClient.getConfig()?.debug;
|
|
5834
|
+
if (debug) console.log(`[Paywallo PRELOAD] paywalls: ${placements.length} placements`);
|
|
5835
|
+
for (let i = 0; i < placements.length; i++) {
|
|
5836
|
+
if (i > 0) await new Promise((r) => setTimeout(r, 200));
|
|
5837
|
+
void this.preload(apiClient, placements[i]).catch((err) => {
|
|
5838
|
+
if (debug) console.log(`[Paywallo PRELOAD] paywall failed ${placements[i]}:`, err);
|
|
5839
|
+
});
|
|
5840
|
+
}
|
|
5841
|
+
}
|
|
5842
|
+
getPreloaded(placement) {
|
|
5843
|
+
const cached2 = this.preloaded.get(placement);
|
|
5844
|
+
if (!cached2) return null;
|
|
5845
|
+
const age = Date.now() - cached2.preloadedAt;
|
|
5846
|
+
if (age >= PRELOAD_TTL_MS) {
|
|
5847
|
+
this.preloaded.delete(placement);
|
|
5848
|
+
return null;
|
|
5849
|
+
}
|
|
5850
|
+
if (age >= PRELOAD_TTL_MS * STALE_THRESHOLD && this.apiClientRef) {
|
|
5851
|
+
void this.preload(this.apiClientRef, placement).catch(() => {
|
|
5852
|
+
});
|
|
5853
|
+
}
|
|
5854
|
+
return { config: cached2.config, products: new Map(cached2.products) };
|
|
5855
|
+
}
|
|
5856
|
+
isPreloaded(placement) {
|
|
5857
|
+
return this.getPreloaded(placement) !== null;
|
|
5858
|
+
}
|
|
5859
|
+
clear() {
|
|
5860
|
+
this.preloaded.clear();
|
|
5861
|
+
this.activePreloads.clear();
|
|
5862
|
+
}
|
|
5863
|
+
async doPreload(apiClient, placement) {
|
|
5864
|
+
try {
|
|
5865
|
+
const config = await apiClient.getPaywall(placement);
|
|
5866
|
+
if (!config) {
|
|
5867
|
+
return {
|
|
5868
|
+
success: false,
|
|
5869
|
+
error: new PaywallError(
|
|
5870
|
+
PAYWALL_ERROR_CODES.NOT_FOUND,
|
|
5871
|
+
`Paywall not found for placement: ${placement}`
|
|
5872
|
+
)
|
|
5873
|
+
};
|
|
5874
|
+
}
|
|
5875
|
+
const products = await this.loadProductsFor(config);
|
|
5876
|
+
this.preloaded.set(placement, { config, products, preloadedAt: Date.now() });
|
|
5877
|
+
if (PaywalloClient.getConfig()?.debug) {
|
|
5878
|
+
console.log(`[Paywallo PRELOAD] paywall cached \u2014 placement: ${placement}`);
|
|
5879
|
+
}
|
|
5880
|
+
return { success: true };
|
|
5881
|
+
} catch (error) {
|
|
5882
|
+
return {
|
|
5883
|
+
success: false,
|
|
5884
|
+
error: error instanceof Error ? error : new PaywallError(PAYWALL_ERROR_CODES.LOAD_FAILED, String(error))
|
|
5885
|
+
};
|
|
5886
|
+
}
|
|
5887
|
+
}
|
|
5888
|
+
async loadProductsFor(config) {
|
|
5889
|
+
const productIds = [];
|
|
5890
|
+
if (config.primaryProductId) productIds.push(config.primaryProductId);
|
|
5891
|
+
if (config.secondaryProductId) productIds.push(config.secondaryProductId);
|
|
5892
|
+
if (config.tertiaryProductId) productIds.push(config.tertiaryProductId);
|
|
5893
|
+
if (productIds.length === 0) return /* @__PURE__ */ new Map();
|
|
5894
|
+
try {
|
|
5895
|
+
const loaded = await getIAPService().loadProducts(productIds);
|
|
5896
|
+
const map = /* @__PURE__ */ new Map();
|
|
5897
|
+
for (const p of loaded) map.set(p.productId, p);
|
|
5898
|
+
return map;
|
|
5899
|
+
} catch (err) {
|
|
5900
|
+
if (PaywalloClient.getConfig()?.debug) {
|
|
5901
|
+
console.log("[Paywallo PRELOAD] products failed, caching config only:", err);
|
|
5902
|
+
}
|
|
5903
|
+
return /* @__PURE__ */ new Map();
|
|
5904
|
+
}
|
|
5905
|
+
}
|
|
5906
|
+
};
|
|
5907
|
+
paywallPreloadService = new PaywallPreloadService();
|
|
5908
|
+
}
|
|
5909
|
+
});
|
|
5910
|
+
|
|
5911
|
+
// src/domains/paywall/PaywallWebViewPrewarmer.tsx
|
|
5912
|
+
function getNativeWebView2() {
|
|
5913
|
+
if (NativeWebViewComponent2) return NativeWebViewComponent2;
|
|
5914
|
+
if (nativeLookupFailed) return null;
|
|
5915
|
+
try {
|
|
5916
|
+
NativeWebViewComponent2 = (0, import_react_native22.requireNativeComponent)("PaywalloWebView");
|
|
5917
|
+
return NativeWebViewComponent2;
|
|
5918
|
+
} catch {
|
|
5919
|
+
nativeLookupFailed = true;
|
|
5920
|
+
return null;
|
|
5921
|
+
}
|
|
5922
|
+
}
|
|
5923
|
+
function PaywallWebViewPrewarmer({
|
|
5924
|
+
webUrl,
|
|
5925
|
+
durationMs = DEFAULT_DURATION_MS
|
|
5926
|
+
}) {
|
|
5927
|
+
const NativeWebView = (0, import_react9.useMemo)(() => getNativeWebView2(), []);
|
|
5928
|
+
const [mounted, setMounted] = (0, import_react9.useState)(true);
|
|
5929
|
+
(0, import_react9.useEffect)(() => {
|
|
5930
|
+
if (!NativeWebView) return;
|
|
5931
|
+
const timer = setTimeout(() => setMounted(false), durationMs);
|
|
5932
|
+
return () => clearTimeout(timer);
|
|
5933
|
+
}, [NativeWebView, durationMs]);
|
|
5934
|
+
if (!NativeWebView || !mounted) return null;
|
|
5935
|
+
const preheatUrl = `${webUrl}/paywall/preheat`;
|
|
5936
|
+
if (PaywalloClient.getConfig()?.debug) {
|
|
5937
|
+
console.log(`[Paywallo PREWARM] mounting hidden WebView: ${preheatUrl}`);
|
|
5938
|
+
}
|
|
5939
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native22.View, { pointerEvents: "none", style: styles4.hidden, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NativeWebView, { sourceUrl: preheatUrl, style: styles4.fill }) });
|
|
5940
|
+
}
|
|
5941
|
+
var import_react9, import_react_native22, import_jsx_runtime4, NativeWebViewComponent2, nativeLookupFailed, DEFAULT_DURATION_MS, styles4;
|
|
5942
|
+
var init_PaywallWebViewPrewarmer = __esm({
|
|
5943
|
+
"src/domains/paywall/PaywallWebViewPrewarmer.tsx"() {
|
|
5944
|
+
"use strict";
|
|
5945
|
+
import_react9 = require("react");
|
|
5946
|
+
import_react_native22 = require("react-native");
|
|
5947
|
+
init_PaywalloClient();
|
|
5948
|
+
import_jsx_runtime4 = require("react/jsx-runtime");
|
|
5949
|
+
NativeWebViewComponent2 = null;
|
|
5950
|
+
nativeLookupFailed = false;
|
|
5951
|
+
DEFAULT_DURATION_MS = 60 * 1e3;
|
|
5952
|
+
styles4 = import_react_native22.StyleSheet.create({
|
|
5953
|
+
hidden: {
|
|
5954
|
+
height: 1,
|
|
5955
|
+
left: -9999,
|
|
5956
|
+
opacity: 0,
|
|
5957
|
+
position: "absolute",
|
|
5958
|
+
top: -9999,
|
|
5959
|
+
width: 1
|
|
5960
|
+
},
|
|
5961
|
+
fill: { flex: 1 }
|
|
5962
|
+
});
|
|
5963
|
+
}
|
|
5964
|
+
});
|
|
5965
|
+
|
|
5670
5966
|
// src/domains/paywall/usePaywallSession.ts
|
|
5671
5967
|
function usePaywallSession(options) {
|
|
5672
|
-
const closedRef = (0,
|
|
5673
|
-
const optsRef = (0,
|
|
5968
|
+
const closedRef = (0, import_react10.useRef)(false);
|
|
5969
|
+
const optsRef = (0, import_react10.useRef)(options);
|
|
5674
5970
|
optsRef.current = options;
|
|
5675
|
-
(0,
|
|
5971
|
+
(0, import_react10.useEffect)(() => {
|
|
5676
5972
|
if (!options) return;
|
|
5677
5973
|
closedRef.current = false;
|
|
5678
5974
|
startHeartbeat({
|
|
@@ -5702,16 +5998,16 @@ function usePaywallSession(options) {
|
|
|
5702
5998
|
});
|
|
5703
5999
|
};
|
|
5704
6000
|
}, [options?.paywallId, options?.placement]);
|
|
5705
|
-
const markClosed = (0,
|
|
6001
|
+
const markClosed = (0, import_react10.useCallback)(() => {
|
|
5706
6002
|
closedRef.current = true;
|
|
5707
6003
|
}, []);
|
|
5708
6004
|
return { markClosed };
|
|
5709
6005
|
}
|
|
5710
|
-
var
|
|
6006
|
+
var import_react10;
|
|
5711
6007
|
var init_usePaywallSession = __esm({
|
|
5712
6008
|
"src/domains/paywall/usePaywallSession.ts"() {
|
|
5713
6009
|
"use strict";
|
|
5714
|
-
|
|
6010
|
+
import_react10 = require("react");
|
|
5715
6011
|
init_emitPaywallClosed();
|
|
5716
6012
|
init_paywallHeartbeat();
|
|
5717
6013
|
}
|
|
@@ -5719,9 +6015,9 @@ var init_usePaywallSession = __esm({
|
|
|
5719
6015
|
|
|
5720
6016
|
// src/domains/paywall/usePaywallPresenter.ts
|
|
5721
6017
|
function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
5722
|
-
const [showingPreloadedWebView, setShowingPreloadedWebView] = (0,
|
|
5723
|
-
const resolverRef = (0,
|
|
5724
|
-
const presentedAtRef = (0,
|
|
6018
|
+
const [showingPreloadedWebView, setShowingPreloadedWebView] = (0, import_react11.useState)(false);
|
|
6019
|
+
const resolverRef = (0, import_react11.useRef)(null);
|
|
6020
|
+
const presentedAtRef = (0, import_react11.useRef)(Date.now());
|
|
5725
6021
|
const sessionOpts = showingPreloadedWebView && preloadedWebView ? {
|
|
5726
6022
|
placement: preloadedWebView.placement,
|
|
5727
6023
|
paywallId: preloadedWebView.paywallId,
|
|
@@ -5731,7 +6027,7 @@ function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
|
5731
6027
|
...preloadedWebView.campaignId && { campaignId: preloadedWebView.campaignId }
|
|
5732
6028
|
} : null;
|
|
5733
6029
|
const { markClosed } = usePaywallSession(sessionOpts);
|
|
5734
|
-
(0,
|
|
6030
|
+
(0, import_react11.useEffect)(() => {
|
|
5735
6031
|
return () => {
|
|
5736
6032
|
if (resolverRef.current) {
|
|
5737
6033
|
resolverRef.current({ presented: false, purchased: false, cancelled: true, restored: false });
|
|
@@ -5740,7 +6036,7 @@ function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
|
5740
6036
|
setShowingPreloadedWebView(false);
|
|
5741
6037
|
};
|
|
5742
6038
|
}, []);
|
|
5743
|
-
const presentPreloadedWebView = (0,
|
|
6039
|
+
const presentPreloadedWebView = (0, import_react11.useCallback)(() => {
|
|
5744
6040
|
return new Promise((resolve) => {
|
|
5745
6041
|
resolverRef.current = resolve;
|
|
5746
6042
|
presentedAtRef.current = Date.now();
|
|
@@ -5774,16 +6070,16 @@ function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
|
5774
6070
|
}
|
|
5775
6071
|
});
|
|
5776
6072
|
}, [preloadedWebView]);
|
|
5777
|
-
const resolvePreloadedPaywall = (0,
|
|
6073
|
+
const resolvePreloadedPaywall = (0, import_react11.useCallback)((result) => {
|
|
5778
6074
|
if (resolverRef.current) {
|
|
5779
6075
|
resolverRef.current(result);
|
|
5780
6076
|
resolverRef.current = null;
|
|
5781
6077
|
}
|
|
5782
6078
|
}, []);
|
|
5783
|
-
const handlePreloadedWebViewReady = (0,
|
|
6079
|
+
const handlePreloadedWebViewReady = (0, import_react11.useCallback)(() => {
|
|
5784
6080
|
setPreloadedWebView((prev) => prev ? { ...prev, loaded: true } : null);
|
|
5785
6081
|
}, [setPreloadedWebView]);
|
|
5786
|
-
const handlePreloadedClose = (0,
|
|
6082
|
+
const handlePreloadedClose = (0, import_react11.useCallback)(() => {
|
|
5787
6083
|
if (preloadedWebView) {
|
|
5788
6084
|
markClosed();
|
|
5789
6085
|
void emitPaywallClosed({
|
|
@@ -5801,11 +6097,11 @@ function usePaywallPresenter(preloadedWebView, setPreloadedWebView) {
|
|
|
5801
6097
|
}, [preloadedWebView, markClosed, resolvePreloadedPaywall]);
|
|
5802
6098
|
return { showingPreloadedWebView, presentPreloadedWebView, resolvePreloadedPaywall, handlePreloadedWebViewReady, handlePreloadedClose, setShowingPreloadedWebView, presentedAtRef };
|
|
5803
6099
|
}
|
|
5804
|
-
var
|
|
6100
|
+
var import_react11;
|
|
5805
6101
|
var init_usePaywallPresenter = __esm({
|
|
5806
6102
|
"src/domains/paywall/usePaywallPresenter.ts"() {
|
|
5807
6103
|
"use strict";
|
|
5808
|
-
|
|
6104
|
+
import_react11 = require("react");
|
|
5809
6105
|
init_PaywalloClient();
|
|
5810
6106
|
init_emitPaywallClosed();
|
|
5811
6107
|
init_usePaywallSession();
|
|
@@ -5820,7 +6116,9 @@ var init_paywall = __esm({
|
|
|
5820
6116
|
init_PaywallError();
|
|
5821
6117
|
init_PaywallErrorBoundary();
|
|
5822
6118
|
init_PaywallModal();
|
|
6119
|
+
init_PaywallPreloadService();
|
|
5823
6120
|
init_PaywallWebView();
|
|
6121
|
+
init_PaywallWebViewPrewarmer();
|
|
5824
6122
|
init_usePaywallPresenter();
|
|
5825
6123
|
init_usePaywallTracking();
|
|
5826
6124
|
}
|
|
@@ -7146,7 +7444,7 @@ function buildV2Envelope(events, providerContext) {
|
|
|
7146
7444
|
};
|
|
7147
7445
|
});
|
|
7148
7446
|
if (context.sdk_version === void 0) context.sdk_version = SDK_VERSION;
|
|
7149
|
-
if (context.platform === void 0) context.platform =
|
|
7447
|
+
if (context.platform === void 0) context.platform = import_react_native23.Platform.OS;
|
|
7150
7448
|
if (context.distinct_id === void 0 && events.length > 0) {
|
|
7151
7449
|
context.distinct_id = events[0].distinctId;
|
|
7152
7450
|
}
|
|
@@ -7186,11 +7484,11 @@ function splitPayloadAndContext(properties) {
|
|
|
7186
7484
|
}
|
|
7187
7485
|
return { payload, promoted };
|
|
7188
7486
|
}
|
|
7189
|
-
var
|
|
7487
|
+
var import_react_native23, import_zod2, v2EventSchema, v2ContextSchema, v2EnvelopeSchema, CONTEXT_KEY_ALIASES;
|
|
7190
7488
|
var init_eventEnvelopeV2 = __esm({
|
|
7191
7489
|
"src/core/eventEnvelopeV2.ts"() {
|
|
7192
7490
|
"use strict";
|
|
7193
|
-
|
|
7491
|
+
import_react_native23 = require("react-native");
|
|
7194
7492
|
import_zod2 = require("zod");
|
|
7195
7493
|
init_uuid();
|
|
7196
7494
|
init_eventFamilies();
|
|
@@ -7260,11 +7558,11 @@ var init_events = __esm({
|
|
|
7260
7558
|
});
|
|
7261
7559
|
|
|
7262
7560
|
// src/core/EventBatcher.ts
|
|
7263
|
-
var
|
|
7561
|
+
var import_react_native24, BATCH_MAX_SIZE, BATCH_FLUSH_MS, EVENT_NAME_REGEX, V2_BATCH_ENDPOINT, EventBatcher;
|
|
7264
7562
|
var init_EventBatcher = __esm({
|
|
7265
7563
|
"src/core/EventBatcher.ts"() {
|
|
7266
7564
|
"use strict";
|
|
7267
|
-
|
|
7565
|
+
import_react_native24 = require("react-native");
|
|
7268
7566
|
init_eventEnvelopeV2();
|
|
7269
7567
|
init_events();
|
|
7270
7568
|
BATCH_MAX_SIZE = 25;
|
|
@@ -7313,7 +7611,7 @@ var init_EventBatcher = __esm({
|
|
|
7313
7611
|
const event = {
|
|
7314
7612
|
eventName,
|
|
7315
7613
|
distinctId,
|
|
7316
|
-
properties: { ...properties, platform:
|
|
7614
|
+
properties: { ...properties, platform: import_react_native24.Platform.OS },
|
|
7317
7615
|
timestamp: timestamp ?? Date.now(),
|
|
7318
7616
|
environment: environment.toLowerCase()
|
|
7319
7617
|
};
|
|
@@ -7639,11 +7937,11 @@ var init_http = __esm({
|
|
|
7639
7937
|
});
|
|
7640
7938
|
|
|
7641
7939
|
// src/core/ApiClient.ts
|
|
7642
|
-
var
|
|
7940
|
+
var import_react_native25, ApiClient;
|
|
7643
7941
|
var init_ApiClient = __esm({
|
|
7644
7942
|
"src/core/ApiClient.ts"() {
|
|
7645
7943
|
"use strict";
|
|
7646
|
-
|
|
7944
|
+
import_react_native25 = require("react-native");
|
|
7647
7945
|
init_apiPurchaseMethods();
|
|
7648
7946
|
init_ApiCache();
|
|
7649
7947
|
init_ApiClientFlags();
|
|
@@ -7745,7 +8043,7 @@ var init_ApiClient = __esm({
|
|
|
7745
8043
|
buildSdkHeaders() {
|
|
7746
8044
|
return {
|
|
7747
8045
|
"x-sdk-version": SDK_VERSION,
|
|
7748
|
-
"x-sdk-platform":
|
|
8046
|
+
"x-sdk-platform": import_react_native25.Platform.OS,
|
|
7749
8047
|
"x-sdk-environment": this.environment
|
|
7750
8048
|
};
|
|
7751
8049
|
}
|
|
@@ -7775,7 +8073,7 @@ var init_ApiClient = __esm({
|
|
|
7775
8073
|
message,
|
|
7776
8074
|
context,
|
|
7777
8075
|
sdkVersion: SDK_VERSION,
|
|
7778
|
-
platform:
|
|
8076
|
+
platform: import_react_native25.Platform.OS
|
|
7779
8077
|
}, true);
|
|
7780
8078
|
} catch (err) {
|
|
7781
8079
|
if (this.debug) console.log("[Paywallo:ApiClient] reportError failed", err);
|
|
@@ -7793,7 +8091,7 @@ var init_ApiClient = __esm({
|
|
|
7793
8091
|
async identify(distinctId, properties, email, deviceId, pii) {
|
|
7794
8092
|
const rawTraits = {
|
|
7795
8093
|
email: email || void 0,
|
|
7796
|
-
platform:
|
|
8094
|
+
platform: import_react_native25.Platform.OS,
|
|
7797
8095
|
name: properties?.name,
|
|
7798
8096
|
country: properties?.country,
|
|
7799
8097
|
locale: properties?.locale,
|
|
@@ -7811,6 +8109,8 @@ var init_ApiClient = __esm({
|
|
|
7811
8109
|
}
|
|
7812
8110
|
}
|
|
7813
8111
|
const attribution = Object.keys(rawAttribution).length > 0 ? rawAttribution : void 0;
|
|
8112
|
+
const rawUserId = properties?.["userId"];
|
|
8113
|
+
const externalUserId = typeof rawUserId === "string" && rawUserId.length > 0 ? rawUserId : void 0;
|
|
7814
8114
|
await postWithQueue(
|
|
7815
8115
|
{
|
|
7816
8116
|
isOfflineQueueEnabled: () => this.offlineQueueEnabled,
|
|
@@ -7821,6 +8121,7 @@ var init_ApiClient = __esm({
|
|
|
7821
8121
|
"/sdk/identity/identify",
|
|
7822
8122
|
{
|
|
7823
8123
|
distinct_id: distinctId,
|
|
8124
|
+
...externalUserId && { external_user_id: externalUserId },
|
|
7824
8125
|
traits,
|
|
7825
8126
|
...attribution && { attribution },
|
|
7826
8127
|
...deviceId && { deviceId },
|
|
@@ -8089,12 +8390,12 @@ async function detectEnvironment() {
|
|
|
8089
8390
|
return cached;
|
|
8090
8391
|
}
|
|
8091
8392
|
}
|
|
8092
|
-
var
|
|
8393
|
+
var import_react_native26, nativeModule, cached;
|
|
8093
8394
|
var init_detectEnvironment = __esm({
|
|
8094
8395
|
"src/utils/detectEnvironment.ts"() {
|
|
8095
8396
|
"use strict";
|
|
8096
|
-
|
|
8097
|
-
nativeModule =
|
|
8397
|
+
import_react_native26 = require("react-native");
|
|
8398
|
+
nativeModule = import_react_native26.NativeModules.PaywalloEnv ?? null;
|
|
8098
8399
|
cached = null;
|
|
8099
8400
|
}
|
|
8100
8401
|
});
|
|
@@ -8276,10 +8577,10 @@ async function doInit(state, config) {
|
|
|
8276
8577
|
let screenHeight;
|
|
8277
8578
|
let screenDensity;
|
|
8278
8579
|
try {
|
|
8279
|
-
const screen =
|
|
8580
|
+
const screen = import_react_native27.Dimensions.get("screen");
|
|
8280
8581
|
screenWidth = Math.round(screen.width) || void 0;
|
|
8281
8582
|
screenHeight = Math.round(screen.height) || void 0;
|
|
8282
|
-
screenDensity =
|
|
8583
|
+
screenDensity = import_react_native27.PixelRatio.get() || void 0;
|
|
8283
8584
|
} catch {
|
|
8284
8585
|
}
|
|
8285
8586
|
return {
|
|
@@ -8346,11 +8647,11 @@ async function doInit(state, config) {
|
|
|
8346
8647
|
setupAutoPreload(state, apiClient, config, distinctId);
|
|
8347
8648
|
startBatchPreload(apiClient, config.debug);
|
|
8348
8649
|
}
|
|
8349
|
-
var
|
|
8650
|
+
var import_react_native27;
|
|
8350
8651
|
var init_PaywalloInitializer = __esm({
|
|
8351
8652
|
"src/core/PaywalloInitializer.ts"() {
|
|
8352
8653
|
"use strict";
|
|
8353
|
-
|
|
8654
|
+
import_react_native27 = require("react-native");
|
|
8354
8655
|
init_identity();
|
|
8355
8656
|
init_AdvertisingIdManager();
|
|
8356
8657
|
init_DeepLinkAttributionCapture();
|
|
@@ -8393,6 +8694,7 @@ async function doFullReset(state) {
|
|
|
8393
8694
|
offlineQueue.dispose();
|
|
8394
8695
|
networkMonitor.dispose();
|
|
8395
8696
|
campaignGateService.clearPreloaded();
|
|
8697
|
+
paywallPreloadService.clear();
|
|
8396
8698
|
await notificationsManager.invalidateLocalToken().catch(() => void 0);
|
|
8397
8699
|
notificationsManager.destroy();
|
|
8398
8700
|
deepLinkAttributionCapture.stop();
|
|
@@ -8427,6 +8729,7 @@ var init_PaywalloLifecycle = __esm({
|
|
|
8427
8729
|
init_identity();
|
|
8428
8730
|
init_DeepLinkAttributionCapture();
|
|
8429
8731
|
init_notifications();
|
|
8732
|
+
init_paywall();
|
|
8430
8733
|
init_session();
|
|
8431
8734
|
init_SubscriptionCache();
|
|
8432
8735
|
init_network();
|
|
@@ -8730,6 +9033,15 @@ var init_PaywalloClient = __esm({
|
|
|
8730
9033
|
isPreloaded(placement) {
|
|
8731
9034
|
return campaignGateService.getPreloadedCampaign(placement) !== null;
|
|
8732
9035
|
}
|
|
9036
|
+
async preloadPaywall(placement) {
|
|
9037
|
+
return paywallPreloadService.preload(this.getApiClientOrThrow(), placement);
|
|
9038
|
+
}
|
|
9039
|
+
async preloadPaywalls(placements) {
|
|
9040
|
+
return paywallPreloadService.preloadMany(this.getApiClientOrThrow(), placements);
|
|
9041
|
+
}
|
|
9042
|
+
isPaywallPreloaded(placement) {
|
|
9043
|
+
return paywallPreloadService.isPreloaded(placement);
|
|
9044
|
+
}
|
|
8733
9045
|
getAutoPreloadedPlacement() {
|
|
8734
9046
|
return this.state.autoPreloadedPlacement;
|
|
8735
9047
|
}
|
|
@@ -8775,7 +9087,7 @@ __export(OfferingService_exports, {
|
|
|
8775
9087
|
offeringService: () => offeringService
|
|
8776
9088
|
});
|
|
8777
9089
|
function resolveProductId(raw) {
|
|
8778
|
-
const isIos =
|
|
9090
|
+
const isIos = import_react_native28.Platform.OS === "ios";
|
|
8779
9091
|
const productId = isIos ? raw.apple_product_id : raw.google_product_id;
|
|
8780
9092
|
return productId ?? "";
|
|
8781
9093
|
}
|
|
@@ -8794,7 +9106,7 @@ function mapProduct2(raw) {
|
|
|
8794
9106
|
};
|
|
8795
9107
|
}
|
|
8796
9108
|
function pickPlatformProduct(products) {
|
|
8797
|
-
const isIos =
|
|
9109
|
+
const isIos = import_react_native28.Platform.OS === "ios";
|
|
8798
9110
|
const match = products.find((p) => isIos ? p.apple_product_id : p.google_product_id);
|
|
8799
9111
|
return match ?? products[0] ?? null;
|
|
8800
9112
|
}
|
|
@@ -8810,11 +9122,11 @@ function mapOffering(raw) {
|
|
|
8810
9122
|
product: mapProduct2(rawProduct)
|
|
8811
9123
|
};
|
|
8812
9124
|
}
|
|
8813
|
-
var
|
|
9125
|
+
var import_react_native28, OFFERINGS_CACHE_KEY, DEFAULT_TTL3, OfferingService, offeringService;
|
|
8814
9126
|
var init_OfferingService = __esm({
|
|
8815
9127
|
"src/domains/offering/OfferingService.ts"() {
|
|
8816
9128
|
"use strict";
|
|
8817
|
-
|
|
9129
|
+
import_react_native28 = require("react-native");
|
|
8818
9130
|
init_SecureStorage();
|
|
8819
9131
|
OFFERINGS_CACHE_KEY = "@paywallo:offerings_cache";
|
|
8820
9132
|
DEFAULT_TTL3 = 5 * 60 * 1e3;
|
|
@@ -8975,8 +9287,8 @@ module.exports = __toCommonJS(index_exports);
|
|
|
8975
9287
|
init_PaywalloClient();
|
|
8976
9288
|
|
|
8977
9289
|
// src/context/PaywalloContext.ts
|
|
8978
|
-
var
|
|
8979
|
-
var PaywalloContext = (0,
|
|
9290
|
+
var import_react12 = require("react");
|
|
9291
|
+
var PaywalloContext = (0, import_react12.createContext)(null);
|
|
8980
9292
|
|
|
8981
9293
|
// src/index.ts
|
|
8982
9294
|
init_ApiClient();
|
|
@@ -9021,7 +9333,7 @@ init_session();
|
|
|
9021
9333
|
init_PaywalloError();
|
|
9022
9334
|
|
|
9023
9335
|
// src/hooks/useOfferingPurchase.ts
|
|
9024
|
-
var
|
|
9336
|
+
var import_react13 = require("react");
|
|
9025
9337
|
|
|
9026
9338
|
// src/domains/plan/invalidateCache.ts
|
|
9027
9339
|
async function invalidatePlanCache() {
|
|
@@ -9034,8 +9346,8 @@ async function invalidatePlanCache() {
|
|
|
9034
9346
|
|
|
9035
9347
|
// src/hooks/useOfferingPurchase.ts
|
|
9036
9348
|
function useOfferingPurchase() {
|
|
9037
|
-
const [state, setState] = (0,
|
|
9038
|
-
const purchase = (0,
|
|
9349
|
+
const [state, setState] = (0, import_react13.useState)("idle");
|
|
9350
|
+
const purchase = (0, import_react13.useCallback)(async (productId) => {
|
|
9039
9351
|
setState("purchasing");
|
|
9040
9352
|
try {
|
|
9041
9353
|
const iapService = getIAPService();
|
|
@@ -9059,7 +9371,7 @@ function useOfferingPurchase() {
|
|
|
9059
9371
|
}
|
|
9060
9372
|
|
|
9061
9373
|
// src/hooks/useOfferings.ts
|
|
9062
|
-
var
|
|
9374
|
+
var import_react14 = require("react");
|
|
9063
9375
|
async function getOfferingService() {
|
|
9064
9376
|
try {
|
|
9065
9377
|
const mod = await Promise.resolve().then(() => (init_OfferingService(), OfferingService_exports));
|
|
@@ -9069,10 +9381,10 @@ async function getOfferingService() {
|
|
|
9069
9381
|
}
|
|
9070
9382
|
}
|
|
9071
9383
|
function useOfferings(ids) {
|
|
9072
|
-
const [offerings, setOfferings] = (0,
|
|
9073
|
-
const [isLoading, setIsLoading] = (0,
|
|
9384
|
+
const [offerings, setOfferings] = (0, import_react14.useState)([]);
|
|
9385
|
+
const [isLoading, setIsLoading] = (0, import_react14.useState)(true);
|
|
9074
9386
|
const idsKey = ids?.join(",") ?? "";
|
|
9075
|
-
const fetchOfferings = (0,
|
|
9387
|
+
const fetchOfferings = (0, import_react14.useCallback)(async () => {
|
|
9076
9388
|
setIsLoading(true);
|
|
9077
9389
|
try {
|
|
9078
9390
|
const service = await getOfferingService();
|
|
@@ -9088,25 +9400,25 @@ function useOfferings(ids) {
|
|
|
9088
9400
|
setIsLoading(false);
|
|
9089
9401
|
}
|
|
9090
9402
|
}, [idsKey]);
|
|
9091
|
-
(0,
|
|
9403
|
+
(0, import_react14.useEffect)(() => {
|
|
9092
9404
|
void fetchOfferings();
|
|
9093
9405
|
}, [fetchOfferings]);
|
|
9094
9406
|
return { offerings, isLoading };
|
|
9095
9407
|
}
|
|
9096
9408
|
|
|
9097
9409
|
// src/hooks/useOnboarding.ts
|
|
9098
|
-
var
|
|
9410
|
+
var import_react15 = require("react");
|
|
9099
9411
|
init_onboarding();
|
|
9100
9412
|
function useOnboarding() {
|
|
9101
|
-
const step = (0,
|
|
9413
|
+
const step = (0, import_react15.useCallback)(
|
|
9102
9414
|
(stepName) => onboardingManager.step(stepName),
|
|
9103
9415
|
[]
|
|
9104
9416
|
);
|
|
9105
|
-
const complete = (0,
|
|
9417
|
+
const complete = (0, import_react15.useCallback)(
|
|
9106
9418
|
() => onboardingManager.complete(),
|
|
9107
9419
|
[]
|
|
9108
9420
|
);
|
|
9109
|
-
const drop = (0,
|
|
9421
|
+
const drop = (0, import_react15.useCallback)(
|
|
9110
9422
|
(stepName) => onboardingManager.drop(stepName),
|
|
9111
9423
|
[]
|
|
9112
9424
|
);
|
|
@@ -9114,10 +9426,10 @@ function useOnboarding() {
|
|
|
9114
9426
|
}
|
|
9115
9427
|
|
|
9116
9428
|
// src/hooks/usePaywallo.ts
|
|
9117
|
-
var
|
|
9429
|
+
var import_react16 = require("react");
|
|
9118
9430
|
init_ClientError();
|
|
9119
9431
|
function usePaywallo() {
|
|
9120
|
-
const context = (0,
|
|
9432
|
+
const context = (0, import_react16.useContext)(PaywalloContext);
|
|
9121
9433
|
if (!context) {
|
|
9122
9434
|
throw new ClientError(CLIENT_ERROR_CODES.PROVIDER_MISSING, "usePaywallo must be used within a PaywalloProvider");
|
|
9123
9435
|
}
|
|
@@ -9125,11 +9437,11 @@ function usePaywallo() {
|
|
|
9125
9437
|
}
|
|
9126
9438
|
|
|
9127
9439
|
// src/hooks/usePlanPurchase.ts
|
|
9128
|
-
var
|
|
9440
|
+
var import_react17 = require("react");
|
|
9129
9441
|
function usePlanPurchase() {
|
|
9130
|
-
const [state, setState] = (0,
|
|
9131
|
-
const [error, setError] = (0,
|
|
9132
|
-
const purchase = (0,
|
|
9442
|
+
const [state, setState] = (0, import_react17.useState)("idle");
|
|
9443
|
+
const [error, setError] = (0, import_react17.useState)(null);
|
|
9444
|
+
const purchase = (0, import_react17.useCallback)(async (productId) => {
|
|
9133
9445
|
setState("purchasing");
|
|
9134
9446
|
setError(null);
|
|
9135
9447
|
try {
|
|
@@ -9152,7 +9464,7 @@ function usePlanPurchase() {
|
|
|
9152
9464
|
return { success: false, error: purchaseError };
|
|
9153
9465
|
}
|
|
9154
9466
|
}, []);
|
|
9155
|
-
const restore = (0,
|
|
9467
|
+
const restore = (0, import_react17.useCallback)(async () => {
|
|
9156
9468
|
setState("restoring");
|
|
9157
9469
|
setError(null);
|
|
9158
9470
|
try {
|
|
@@ -9181,7 +9493,7 @@ function usePlanPurchase() {
|
|
|
9181
9493
|
}
|
|
9182
9494
|
|
|
9183
9495
|
// src/hooks/usePlans.ts
|
|
9184
|
-
var
|
|
9496
|
+
var import_react18 = require("react");
|
|
9185
9497
|
async function getPlanService() {
|
|
9186
9498
|
try {
|
|
9187
9499
|
const mod = await Promise.resolve().then(() => (init_PlanService(), PlanService_exports));
|
|
@@ -9191,11 +9503,11 @@ async function getPlanService() {
|
|
|
9191
9503
|
}
|
|
9192
9504
|
}
|
|
9193
9505
|
function usePlans() {
|
|
9194
|
-
const [allPlans, setAllPlans] = (0,
|
|
9195
|
-
const [currentPlan, setCurrentPlan] = (0,
|
|
9196
|
-
const [isLoading, setIsLoading] = (0,
|
|
9197
|
-
const [error, setError] = (0,
|
|
9198
|
-
const fetchPlans = (0,
|
|
9506
|
+
const [allPlans, setAllPlans] = (0, import_react18.useState)([]);
|
|
9507
|
+
const [currentPlan, setCurrentPlan] = (0, import_react18.useState)(null);
|
|
9508
|
+
const [isLoading, setIsLoading] = (0, import_react18.useState)(true);
|
|
9509
|
+
const [error, setError] = (0, import_react18.useState)(null);
|
|
9510
|
+
const fetchPlans = (0, import_react18.useCallback)(async (forceRefresh = false) => {
|
|
9199
9511
|
setIsLoading(true);
|
|
9200
9512
|
setError(null);
|
|
9201
9513
|
try {
|
|
@@ -9216,17 +9528,17 @@ function usePlans() {
|
|
|
9216
9528
|
setIsLoading(false);
|
|
9217
9529
|
}
|
|
9218
9530
|
}, []);
|
|
9219
|
-
const refresh = (0,
|
|
9531
|
+
const refresh = (0, import_react18.useCallback)(() => {
|
|
9220
9532
|
return fetchPlans(true);
|
|
9221
9533
|
}, [fetchPlans]);
|
|
9222
|
-
(0,
|
|
9534
|
+
(0, import_react18.useEffect)(() => {
|
|
9223
9535
|
void fetchPlans(false);
|
|
9224
9536
|
}, [fetchPlans]);
|
|
9225
9537
|
return { currentPlan, allPlans, isLoading, error, refresh };
|
|
9226
9538
|
}
|
|
9227
9539
|
|
|
9228
9540
|
// src/hooks/useProducts.ts
|
|
9229
|
-
var
|
|
9541
|
+
var import_react19 = require("react");
|
|
9230
9542
|
|
|
9231
9543
|
// src/utils/productMappers.ts
|
|
9232
9544
|
function mapToIAPProduct(product) {
|
|
@@ -9265,11 +9577,11 @@ function mapToFormattedProduct(product) {
|
|
|
9265
9577
|
|
|
9266
9578
|
// src/hooks/useProducts.ts
|
|
9267
9579
|
function useProducts(initialProductIds) {
|
|
9268
|
-
const [products, setProducts] = (0,
|
|
9269
|
-
const [formattedProducts, setFormattedProducts] = (0,
|
|
9270
|
-
const [isLoading, setIsLoading] = (0,
|
|
9271
|
-
const [error, setError] = (0,
|
|
9272
|
-
const loadProducts = (0,
|
|
9580
|
+
const [products, setProducts] = (0, import_react19.useState)([]);
|
|
9581
|
+
const [formattedProducts, setFormattedProducts] = (0, import_react19.useState)([]);
|
|
9582
|
+
const [isLoading, setIsLoading] = (0, import_react19.useState)(false);
|
|
9583
|
+
const [error, setError] = (0, import_react19.useState)(null);
|
|
9584
|
+
const loadProducts = (0, import_react19.useCallback)(async (productIds) => {
|
|
9273
9585
|
setIsLoading(true);
|
|
9274
9586
|
setError(null);
|
|
9275
9587
|
try {
|
|
@@ -9283,24 +9595,24 @@ function useProducts(initialProductIds) {
|
|
|
9283
9595
|
setIsLoading(false);
|
|
9284
9596
|
}
|
|
9285
9597
|
}, []);
|
|
9286
|
-
(0,
|
|
9598
|
+
(0, import_react19.useEffect)(() => {
|
|
9287
9599
|
if (initialProductIds && initialProductIds.length > 0) {
|
|
9288
9600
|
void loadProducts(initialProductIds);
|
|
9289
9601
|
}
|
|
9290
9602
|
}, []);
|
|
9291
|
-
const getProduct = (0,
|
|
9603
|
+
const getProduct = (0, import_react19.useCallback)(
|
|
9292
9604
|
(productId) => {
|
|
9293
9605
|
return products.find((p) => p.productId === productId);
|
|
9294
9606
|
},
|
|
9295
9607
|
[products]
|
|
9296
9608
|
);
|
|
9297
|
-
const getFormattedProduct = (0,
|
|
9609
|
+
const getFormattedProduct = (0, import_react19.useCallback)(
|
|
9298
9610
|
(productId) => {
|
|
9299
9611
|
return formattedProducts.find((p) => p.productId === productId);
|
|
9300
9612
|
},
|
|
9301
9613
|
[formattedProducts]
|
|
9302
9614
|
);
|
|
9303
|
-
const getPriceInfo = (0,
|
|
9615
|
+
const getPriceInfo = (0, import_react19.useCallback)(
|
|
9304
9616
|
(productId) => {
|
|
9305
9617
|
const p = formattedProducts.find((fp) => fp.productId === productId);
|
|
9306
9618
|
if (!p) return void 0;
|
|
@@ -9329,14 +9641,14 @@ function useProducts(initialProductIds) {
|
|
|
9329
9641
|
}
|
|
9330
9642
|
|
|
9331
9643
|
// src/hooks/usePurchase.ts
|
|
9332
|
-
var
|
|
9644
|
+
var import_react20 = require("react");
|
|
9333
9645
|
function toIAPPurchase(p) {
|
|
9334
9646
|
return { productId: p.productId, transactionId: p.transactionId, transactionDate: p.transactionDate, transactionReceipt: p.receipt };
|
|
9335
9647
|
}
|
|
9336
9648
|
function usePurchase() {
|
|
9337
|
-
const [state, setState] = (0,
|
|
9338
|
-
const [error, setError] = (0,
|
|
9339
|
-
const purchase = (0,
|
|
9649
|
+
const [state, setState] = (0, import_react20.useState)("idle");
|
|
9650
|
+
const [error, setError] = (0, import_react20.useState)(null);
|
|
9651
|
+
const purchase = (0, import_react20.useCallback)(async (productId) => {
|
|
9340
9652
|
setState("purchasing");
|
|
9341
9653
|
setError(null);
|
|
9342
9654
|
try {
|
|
@@ -9364,7 +9676,7 @@ function usePurchase() {
|
|
|
9364
9676
|
return { status: "failed", error: purchaseError };
|
|
9365
9677
|
}
|
|
9366
9678
|
}, []);
|
|
9367
|
-
const restore = (0,
|
|
9679
|
+
const restore = (0, import_react20.useCallback)(async () => {
|
|
9368
9680
|
setState("restoring");
|
|
9369
9681
|
setError(null);
|
|
9370
9682
|
try {
|
|
@@ -9383,14 +9695,14 @@ function usePurchase() {
|
|
|
9383
9695
|
}
|
|
9384
9696
|
|
|
9385
9697
|
// src/hooks/useSubscription.ts
|
|
9386
|
-
var
|
|
9698
|
+
var import_react21 = require("react");
|
|
9387
9699
|
init_SubscriptionManager();
|
|
9388
9700
|
var EMPTY_ENTITLEMENTS = [];
|
|
9389
9701
|
function useSubscription() {
|
|
9390
|
-
const [status, setStatus] = (0,
|
|
9391
|
-
const [isLoading, setIsLoading] = (0,
|
|
9392
|
-
const [error, setError] = (0,
|
|
9393
|
-
const refresh = (0,
|
|
9702
|
+
const [status, setStatus] = (0, import_react21.useState)(null);
|
|
9703
|
+
const [isLoading, setIsLoading] = (0, import_react21.useState)(true);
|
|
9704
|
+
const [error, setError] = (0, import_react21.useState)(null);
|
|
9705
|
+
const refresh = (0, import_react21.useCallback)(async () => {
|
|
9394
9706
|
setIsLoading(true);
|
|
9395
9707
|
setError(null);
|
|
9396
9708
|
try {
|
|
@@ -9403,7 +9715,7 @@ function useSubscription() {
|
|
|
9403
9715
|
setIsLoading(false);
|
|
9404
9716
|
}
|
|
9405
9717
|
}, []);
|
|
9406
|
-
const restore = (0,
|
|
9718
|
+
const restore = (0, import_react21.useCallback)(async () => {
|
|
9407
9719
|
setIsLoading(true);
|
|
9408
9720
|
setError(null);
|
|
9409
9721
|
try {
|
|
@@ -9416,7 +9728,7 @@ function useSubscription() {
|
|
|
9416
9728
|
setIsLoading(false);
|
|
9417
9729
|
}
|
|
9418
9730
|
}, []);
|
|
9419
|
-
(0,
|
|
9731
|
+
(0, import_react21.useEffect)(() => {
|
|
9420
9732
|
void subscriptionManager.getSubscriptionStatus().then((s) => {
|
|
9421
9733
|
setStatus(s);
|
|
9422
9734
|
setIsLoading(false);
|
|
@@ -9444,63 +9756,257 @@ function useSubscription() {
|
|
|
9444
9756
|
}
|
|
9445
9757
|
|
|
9446
9758
|
// src/PaywalloProvider.tsx
|
|
9447
|
-
var
|
|
9448
|
-
var
|
|
9759
|
+
var import_react27 = require("react");
|
|
9760
|
+
var import_react_native29 = require("react-native");
|
|
9449
9761
|
init_PaywalloClient();
|
|
9450
|
-
init_SecureStorage();
|
|
9451
9762
|
init_NativeStorage();
|
|
9763
|
+
init_SecureStorage();
|
|
9452
9764
|
init_campaign();
|
|
9453
9765
|
init_paywall();
|
|
9454
9766
|
init_paywall();
|
|
9455
9767
|
init_paywall();
|
|
9456
9768
|
init_paywall();
|
|
9457
|
-
|
|
9458
|
-
|
|
9769
|
+
init_paywall();
|
|
9770
|
+
init_paywall();
|
|
9459
9771
|
|
|
9460
|
-
// src/
|
|
9461
|
-
|
|
9772
|
+
// src/domains/paywall/SuperwallAutoBridge.ts
|
|
9773
|
+
init_PaywalloClient();
|
|
9462
9774
|
|
|
9463
|
-
// src/utils/
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9775
|
+
// src/core/utils/eventId.ts
|
|
9776
|
+
function hashString(input) {
|
|
9777
|
+
let h1 = 3735928559;
|
|
9778
|
+
let h2 = 1103547991;
|
|
9779
|
+
for (let i = 0; i < input.length; i++) {
|
|
9780
|
+
const ch = input.charCodeAt(i);
|
|
9781
|
+
h1 = Math.imul(h1 ^ ch, 2654435769);
|
|
9782
|
+
h2 = Math.imul(h2 ^ ch, 1598716949);
|
|
9470
9783
|
}
|
|
9784
|
+
h1 = Math.imul(h1 ^ h1 >>> 16, 73244475);
|
|
9785
|
+
h1 ^= Math.imul(h2 ^ h2 >>> 13, 351452291);
|
|
9786
|
+
h2 = Math.imul(h2 ^ h2 >>> 16, 73244475);
|
|
9787
|
+
h2 ^= Math.imul(h1 ^ h1 >>> 13, 351452291);
|
|
9788
|
+
const toHex = (n) => (n >>> 0).toString(16).padStart(8, "0");
|
|
9789
|
+
return toHex(h1) + toHex(h2);
|
|
9471
9790
|
}
|
|
9472
|
-
|
|
9473
|
-
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
|
|
9478
|
-
|
|
9479
|
-
}
|
|
9791
|
+
function buildDeterministicEventId(parts) {
|
|
9792
|
+
const raw = hashString(parts.join("|"));
|
|
9793
|
+
const p1 = raw.slice(0, 8);
|
|
9794
|
+
const p2 = raw.slice(8, 12);
|
|
9795
|
+
const p3 = "4" + raw.slice(13, 16);
|
|
9796
|
+
const p4 = (parseInt(raw[16], 16) & 3 | 8).toString(16) + raw.slice(17, 20);
|
|
9797
|
+
const p5 = raw.padEnd(32, "0").slice(20, 32);
|
|
9798
|
+
return `${p1}-${p2}-${p3}-${p4}-${p5}`;
|
|
9480
9799
|
}
|
|
9481
9800
|
|
|
9482
|
-
// src/
|
|
9483
|
-
var
|
|
9484
|
-
var
|
|
9485
|
-
|
|
9486
|
-
|
|
9487
|
-
|
|
9488
|
-
(0
|
|
9489
|
-
|
|
9490
|
-
|
|
9491
|
-
|
|
9492
|
-
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
|
|
9503
|
-
|
|
9801
|
+
// src/domains/paywall/SuperwallAutoBridge.ts
|
|
9802
|
+
var bridgeStarted = false;
|
|
9803
|
+
var unsubscribe = null;
|
|
9804
|
+
var debugEnabled = false;
|
|
9805
|
+
function log(msg, data) {
|
|
9806
|
+
if (!debugEnabled) return;
|
|
9807
|
+
if (data !== void 0) {
|
|
9808
|
+
console.log(`[Paywallo:SuperwallBridge] ${msg}`, data);
|
|
9809
|
+
} else {
|
|
9810
|
+
console.log(`[Paywallo:SuperwallBridge] ${msg}`);
|
|
9811
|
+
}
|
|
9812
|
+
}
|
|
9813
|
+
function minuteBucket(ts) {
|
|
9814
|
+
return String(Math.floor(ts / 6e4));
|
|
9815
|
+
}
|
|
9816
|
+
function buildEventId(type, identifier, ts) {
|
|
9817
|
+
return buildDeterministicEventId(["sw", type, identifier, minuteBucket(ts)]);
|
|
9818
|
+
}
|
|
9819
|
+
async function trackPaywallEvent(type, identifier, ts, extra) {
|
|
9820
|
+
const _eventId = buildEventId(type, identifier, ts);
|
|
9821
|
+
try {
|
|
9822
|
+
const cleanExtra = {};
|
|
9823
|
+
if (extra) {
|
|
9824
|
+
for (const [k, v] of Object.entries(extra)) if (v !== void 0) cleanExtra[k] = v;
|
|
9825
|
+
}
|
|
9826
|
+
await PaywalloClient.track("paywall", {
|
|
9827
|
+
priority: "critical",
|
|
9828
|
+
properties: {
|
|
9829
|
+
type,
|
|
9830
|
+
paywall_id: identifier,
|
|
9831
|
+
...cleanExtra
|
|
9832
|
+
}
|
|
9833
|
+
});
|
|
9834
|
+
} catch (err) {
|
|
9835
|
+
log("track error", { type, identifier, eventId: _eventId, err: String(err) });
|
|
9836
|
+
}
|
|
9837
|
+
}
|
|
9838
|
+
function mapDismissToCloseReason(resultType) {
|
|
9839
|
+
switch (resultType) {
|
|
9840
|
+
case "purchased":
|
|
9841
|
+
return "purchased";
|
|
9842
|
+
case "restored":
|
|
9843
|
+
return "purchased";
|
|
9844
|
+
// restore counts as a purchase outcome for funnel
|
|
9845
|
+
case "declined":
|
|
9846
|
+
return "dismissed";
|
|
9847
|
+
default:
|
|
9848
|
+
return void 0;
|
|
9849
|
+
}
|
|
9850
|
+
}
|
|
9851
|
+
function buildCallbacks() {
|
|
9852
|
+
return {
|
|
9853
|
+
onPaywallPresent: (info) => {
|
|
9854
|
+
const ts = Date.now();
|
|
9855
|
+
log("onPaywallPresent", { identifier: info.identifier });
|
|
9856
|
+
void trackPaywallEvent("viewed", info.identifier, ts, {
|
|
9857
|
+
placement: info.presentedByEventWithName,
|
|
9858
|
+
variant_id: info.experiment?.variant?.id,
|
|
9859
|
+
campaign_id: info.experiment?.id
|
|
9860
|
+
});
|
|
9861
|
+
},
|
|
9862
|
+
onPaywallDismiss: (info, result) => {
|
|
9863
|
+
const ts = Date.now();
|
|
9864
|
+
log("onPaywallDismiss", { identifier: info.identifier, result: result.type });
|
|
9865
|
+
void trackPaywallEvent("closed", info.identifier, ts, {
|
|
9866
|
+
placement: info.presentedByEventWithName,
|
|
9867
|
+
variant_id: info.experiment?.variant?.id,
|
|
9868
|
+
campaign_id: info.experiment?.id,
|
|
9869
|
+
close_reason: mapDismissToCloseReason(result.type),
|
|
9870
|
+
closed_at: new Date(ts).toISOString()
|
|
9871
|
+
});
|
|
9872
|
+
},
|
|
9873
|
+
onPurchase: (params) => {
|
|
9874
|
+
const ts = Date.now();
|
|
9875
|
+
const safe = params !== null && typeof params === "object" ? params : {};
|
|
9876
|
+
const productId = "productId" in safe && typeof safe.productId === "string" ? safe.productId : "unknown";
|
|
9877
|
+
const identifier = "paywallIdentifier" in safe && typeof safe.paywallIdentifier === "string" ? safe.paywallIdentifier : productId;
|
|
9878
|
+
log("onPurchase", { productId, identifier });
|
|
9879
|
+
void trackPaywallEvent("purchased", identifier, ts, { product_id: productId });
|
|
9880
|
+
},
|
|
9881
|
+
// Global Superwall event listener — used specifically for `transactionComplete`
|
|
9882
|
+
// which is the only event that exposes the full product (currency/price) +
|
|
9883
|
+
// transaction (storeTransactionId) shape needed to create a server-side
|
|
9884
|
+
// `transactions` row. Other events are skipped (paywallOpen/Dismiss already
|
|
9885
|
+
// handled above with their typed callbacks).
|
|
9886
|
+
onSuperwallEvent: (info) => {
|
|
9887
|
+
const ev = info?.event;
|
|
9888
|
+
if (!ev || ev.event !== "transactionComplete") return;
|
|
9889
|
+
const ts = Date.now();
|
|
9890
|
+
const product = ev.product;
|
|
9891
|
+
const transaction = ev.transaction;
|
|
9892
|
+
if (!product) {
|
|
9893
|
+
log("transactionComplete missing product \u2014 skipping transaction track");
|
|
9894
|
+
return;
|
|
9895
|
+
}
|
|
9896
|
+
const productId = product.productIdentifier ?? product.id ?? "unknown";
|
|
9897
|
+
const currency = product.currencyCode ?? "USD";
|
|
9898
|
+
const price = product.price ?? 0;
|
|
9899
|
+
const transactionId = transaction?.storeTransactionId ?? transaction?.originalTransactionIdentifier ?? `${productId}_${String(ts)}`;
|
|
9900
|
+
const isTrial = product.hasFreeTrial === true || (product.trialPeriodPrice ?? 0) > 0;
|
|
9901
|
+
const paywallIdentifier = ev.paywallInfo?.identifier;
|
|
9902
|
+
log("onSuperwallEvent: transactionComplete", { productId, currency, price, transactionId, isTrial });
|
|
9903
|
+
void (async () => {
|
|
9904
|
+
try {
|
|
9905
|
+
await PaywalloClient.track("transaction", {
|
|
9906
|
+
priority: "critical",
|
|
9907
|
+
properties: {
|
|
9908
|
+
type: isTrial ? "trial_started" : "completed",
|
|
9909
|
+
// Server's IngestTranslator looks for `transaction_id`/`product_id`
|
|
9910
|
+
// /`amount`/`currency`/`paywall_id` keys (not `tx_id`). PurchaseHandler
|
|
9911
|
+
// then resolves type=trial/new/renewal based on amount being 0 vs >0.
|
|
9912
|
+
transaction_id: transactionId,
|
|
9913
|
+
product_id: productId,
|
|
9914
|
+
amount: price,
|
|
9915
|
+
currency,
|
|
9916
|
+
...paywallIdentifier ? { paywall_id: paywallIdentifier } : {}
|
|
9917
|
+
}
|
|
9918
|
+
});
|
|
9919
|
+
} catch (err) {
|
|
9920
|
+
log("transactionComplete track error", { err: String(err) });
|
|
9921
|
+
}
|
|
9922
|
+
})();
|
|
9923
|
+
}
|
|
9924
|
+
};
|
|
9925
|
+
}
|
|
9926
|
+
function startSuperwallAutoBridge(debug = false) {
|
|
9927
|
+
debugEnabled = debug;
|
|
9928
|
+
if (bridgeStarted) {
|
|
9929
|
+
log("already started, skipping");
|
|
9930
|
+
return;
|
|
9931
|
+
}
|
|
9932
|
+
void detectAndStart();
|
|
9933
|
+
}
|
|
9934
|
+
async function detectAndStart() {
|
|
9935
|
+
let subscribeFn;
|
|
9936
|
+
try {
|
|
9937
|
+
const mod = await import("expo-superwall");
|
|
9938
|
+
if (!mod || typeof mod.subscribeToSuperwallEvents !== "function") {
|
|
9939
|
+
const internal = await import("expo-superwall/build/src/internal/superwallEventBridge");
|
|
9940
|
+
if (typeof internal.subscribeToSuperwallEvents !== "function") {
|
|
9941
|
+
log("expo-superwall subscribeToSuperwallEvents not found \u2014 bridge inactive");
|
|
9942
|
+
return;
|
|
9943
|
+
}
|
|
9944
|
+
subscribeFn = internal.subscribeToSuperwallEvents;
|
|
9945
|
+
} else {
|
|
9946
|
+
subscribeFn = mod.subscribeToSuperwallEvents;
|
|
9947
|
+
}
|
|
9948
|
+
} catch {
|
|
9949
|
+
log("expo-superwall not installed \u2014 bridge inactive");
|
|
9950
|
+
return;
|
|
9951
|
+
}
|
|
9952
|
+
try {
|
|
9953
|
+
const callbacks = buildCallbacks();
|
|
9954
|
+
unsubscribe = subscribeFn(void 0, () => callbacks);
|
|
9955
|
+
bridgeStarted = true;
|
|
9956
|
+
log("bridge started");
|
|
9957
|
+
} catch (err) {
|
|
9958
|
+
log("subscribe failed", { err: String(err) });
|
|
9959
|
+
}
|
|
9960
|
+
}
|
|
9961
|
+
|
|
9962
|
+
// src/PaywalloProvider.tsx
|
|
9963
|
+
init_session();
|
|
9964
|
+
init_ClientError();
|
|
9965
|
+
|
|
9966
|
+
// src/hooks/useAppAutoEvents.ts
|
|
9967
|
+
var import_react22 = require("react");
|
|
9968
|
+
|
|
9969
|
+
// src/utils/platformDetection.ts
|
|
9970
|
+
async function detectPlatform3() {
|
|
9971
|
+
try {
|
|
9972
|
+
const rn = await import("react-native");
|
|
9973
|
+
return rn.Platform?.OS === "ios" ? "ios" : "android";
|
|
9974
|
+
} catch {
|
|
9975
|
+
return "android";
|
|
9976
|
+
}
|
|
9977
|
+
}
|
|
9978
|
+
async function detectOsVersion() {
|
|
9979
|
+
try {
|
|
9980
|
+
const rn = await import("react-native");
|
|
9981
|
+
const version = rn.Platform?.Version;
|
|
9982
|
+
return version != null ? String(version) : "unknown";
|
|
9983
|
+
} catch {
|
|
9984
|
+
return "unknown";
|
|
9985
|
+
}
|
|
9986
|
+
}
|
|
9987
|
+
|
|
9988
|
+
// src/hooks/useAppAutoEvents.ts
|
|
9989
|
+
var FIRST_SEEN_KEY = "@paywallo:firstSeen_v226";
|
|
9990
|
+
var DEBOUNCE_MS = 1e3;
|
|
9991
|
+
function useAppAutoEvents(config) {
|
|
9992
|
+
const { isInitialized, getAppVersion: getAppVersion2, getSessionId, emitLifecycle, storageGet, storageSet, debug } = config;
|
|
9993
|
+
const didRunRef = (0, import_react22.useRef)(false);
|
|
9994
|
+
(0, import_react22.useEffect)(() => {
|
|
9995
|
+
if (debug) console.log("[Paywallo EVENTS] useEffect fired", { isInitialized, didRunRefCurrent: didRunRef.current });
|
|
9996
|
+
if (!isInitialized || didRunRef.current) return;
|
|
9997
|
+
const timer = setTimeout(() => {
|
|
9998
|
+
if (didRunRef.current) return;
|
|
9999
|
+
didRunRef.current = true;
|
|
10000
|
+
void (async () => {
|
|
10001
|
+
const sessionId = getSessionId();
|
|
10002
|
+
const appVersion = getAppVersion2();
|
|
10003
|
+
const deviceType = await detectPlatform3();
|
|
10004
|
+
const osVersion = await detectOsVersion();
|
|
10005
|
+
if (debug) console.log("[Paywallo EVENTS] computed device context", { deviceType, osVersion, appVersion, sessionId, hasSessionId: !!sessionId });
|
|
10006
|
+
try {
|
|
10007
|
+
if (debug) console.log("[Paywallo EVENTS] checking install \u2014 about to read FIRST_SEEN_KEY");
|
|
10008
|
+
const firstSeen = await storageGet(FIRST_SEEN_KEY);
|
|
10009
|
+
if (!firstSeen) {
|
|
9504
10010
|
await emitLifecycle({ type: "install", device_type: deviceType, os_version: osVersion, app_version: appVersion, ...sessionId ? { session_id: sessionId } : {} }, "critical");
|
|
9505
10011
|
await storageSet(FIRST_SEEN_KEY, (/* @__PURE__ */ new Date()).toISOString());
|
|
9506
10012
|
if (debug) console.log("[Paywallo EVENTS] install event emitted (first time)");
|
|
@@ -9525,7 +10031,7 @@ function useAppAutoEvents(config) {
|
|
|
9525
10031
|
}
|
|
9526
10032
|
|
|
9527
10033
|
// src/hooks/useCampaignPreload.ts
|
|
9528
|
-
var
|
|
10034
|
+
var import_react23 = require("react");
|
|
9529
10035
|
init_PaywalloClient();
|
|
9530
10036
|
init_CampaignError();
|
|
9531
10037
|
|
|
@@ -9596,17 +10102,17 @@ function getCacheEntry(cache, placement) {
|
|
|
9596
10102
|
|
|
9597
10103
|
// src/hooks/useCampaignPreload.ts
|
|
9598
10104
|
function useCampaignPreload() {
|
|
9599
|
-
const [preloadedWebView, setPreloadedWebView] = (0,
|
|
9600
|
-
const preloadedCampaignsRef = (0,
|
|
9601
|
-
const isPreloadValid = (0,
|
|
10105
|
+
const [preloadedWebView, setPreloadedWebView] = (0, import_react23.useState)(null);
|
|
10106
|
+
const preloadedCampaignsRef = (0, import_react23.useRef)(/* @__PURE__ */ new Map());
|
|
10107
|
+
const isPreloadValid = (0, import_react23.useCallback)(
|
|
9602
10108
|
(placement) => isCacheEntryValid(preloadedCampaignsRef.current.get(placement)),
|
|
9603
10109
|
[]
|
|
9604
10110
|
);
|
|
9605
|
-
const consumePreloadedCampaign = (0,
|
|
10111
|
+
const consumePreloadedCampaign = (0, import_react23.useCallback)(
|
|
9606
10112
|
(placement) => getCacheEntry(preloadedCampaignsRef.current, placement),
|
|
9607
10113
|
[]
|
|
9608
10114
|
);
|
|
9609
|
-
const preloadCampaign = (0,
|
|
10115
|
+
const preloadCampaign = (0, import_react23.useCallback)(
|
|
9610
10116
|
async (placement, context) => {
|
|
9611
10117
|
try {
|
|
9612
10118
|
const campaign = await PaywalloClient.getCampaign(placement, context);
|
|
@@ -9675,11 +10181,11 @@ function useCampaignPreload() {
|
|
|
9675
10181
|
}
|
|
9676
10182
|
|
|
9677
10183
|
// src/hooks/useProductLoader.ts
|
|
9678
|
-
var
|
|
10184
|
+
var import_react24 = require("react");
|
|
9679
10185
|
function useProductLoader() {
|
|
9680
|
-
const [products, setProducts] = (0,
|
|
9681
|
-
const [isLoadingProducts, setIsLoadingProducts] = (0,
|
|
9682
|
-
const refreshProducts = (0,
|
|
10186
|
+
const [products, setProducts] = (0, import_react24.useState)(/* @__PURE__ */ new Map());
|
|
10187
|
+
const [isLoadingProducts, setIsLoadingProducts] = (0, import_react24.useState)(false);
|
|
10188
|
+
const refreshProducts = (0, import_react24.useCallback)(async (productIds) => {
|
|
9683
10189
|
setIsLoadingProducts(true);
|
|
9684
10190
|
try {
|
|
9685
10191
|
const iapService = getIAPService();
|
|
@@ -9697,11 +10203,11 @@ function useProductLoader() {
|
|
|
9697
10203
|
}
|
|
9698
10204
|
|
|
9699
10205
|
// src/hooks/usePurchaseOrchestrator.ts
|
|
9700
|
-
var
|
|
10206
|
+
var import_react25 = require("react");
|
|
9701
10207
|
init_paywall();
|
|
9702
10208
|
function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clearPreloadedWebView, setShowingPreloadedWebView, presentedAtRef, invalidateSubscriptionCache) {
|
|
9703
10209
|
const { trackDismissed, trackProductSelected, trackPurchased } = usePaywallTracking();
|
|
9704
|
-
const handlePreloadedPurchase = (0,
|
|
10210
|
+
const handlePreloadedPurchase = (0, import_react25.useCallback)(
|
|
9705
10211
|
async (productId) => {
|
|
9706
10212
|
try {
|
|
9707
10213
|
if (preloadedWebView) {
|
|
@@ -9739,7 +10245,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
|
|
|
9739
10245
|
},
|
|
9740
10246
|
[preloadedWebView, resolvePreloadedPaywall, clearPreloadedWebView, setShowingPreloadedWebView, presentedAtRef, trackDismissed, trackProductSelected, trackPurchased, invalidateSubscriptionCache]
|
|
9741
10247
|
);
|
|
9742
|
-
const handlePreloadedRestore = (0,
|
|
10248
|
+
const handlePreloadedRestore = (0, import_react25.useCallback)(async () => {
|
|
9743
10249
|
try {
|
|
9744
10250
|
const transactions = await getIAPService().restore();
|
|
9745
10251
|
if (transactions.length === 0) return;
|
|
@@ -9762,7 +10268,7 @@ function usePurchaseOrchestrator(preloadedWebView, resolvePreloadedPaywall, clea
|
|
|
9762
10268
|
}
|
|
9763
10269
|
|
|
9764
10270
|
// src/hooks/useSubscriptionSync.ts
|
|
9765
|
-
var
|
|
10271
|
+
var import_react26 = require("react");
|
|
9766
10272
|
init_PaywalloClient();
|
|
9767
10273
|
init_SubscriptionCache();
|
|
9768
10274
|
|
|
@@ -9872,18 +10378,18 @@ async function checkPersistedCache(distinctId, onHit) {
|
|
|
9872
10378
|
|
|
9873
10379
|
// src/hooks/useSubscriptionSync.ts
|
|
9874
10380
|
function useSubscriptionSync() {
|
|
9875
|
-
const [subscription, setSubscription] = (0,
|
|
9876
|
-
const cacheRef = (0,
|
|
9877
|
-
const setCacheAndState = (0,
|
|
10381
|
+
const [subscription, setSubscription] = (0, import_react26.useState)(null);
|
|
10382
|
+
const cacheRef = (0, import_react26.useRef)(null);
|
|
10383
|
+
const setCacheAndState = (0, import_react26.useCallback)((sub) => {
|
|
9878
10384
|
cacheRef.current = { data: sub, expiresAt: Date.now() + CACHE_TTL_MS2 };
|
|
9879
10385
|
setSubscription(sub);
|
|
9880
10386
|
}, []);
|
|
9881
|
-
const invalidateCache = (0,
|
|
10387
|
+
const invalidateCache = (0, import_react26.useCallback)(() => {
|
|
9882
10388
|
cacheRef.current = null;
|
|
9883
10389
|
const distinctId = PaywalloClient.getDistinctId();
|
|
9884
10390
|
if (distinctId) void subscriptionCache.invalidate(distinctId);
|
|
9885
10391
|
}, []);
|
|
9886
|
-
const fetchAndCache = (0,
|
|
10392
|
+
const fetchAndCache = (0, import_react26.useCallback)(async () => {
|
|
9887
10393
|
const apiClient = PaywalloClient.getApiClient();
|
|
9888
10394
|
const distinctId = PaywalloClient.getDistinctId();
|
|
9889
10395
|
if (!apiClient || !distinctId) return null;
|
|
@@ -9893,7 +10399,7 @@ function useSubscriptionSync() {
|
|
|
9893
10399
|
void subscriptionCache.set(distinctId, toDomainResponse(status));
|
|
9894
10400
|
return sub;
|
|
9895
10401
|
}, [setCacheAndState]);
|
|
9896
|
-
const hasActiveSubscription = (0,
|
|
10402
|
+
const hasActiveSubscription = (0, import_react26.useCallback)(async () => {
|
|
9897
10403
|
const apiClient = PaywalloClient.getApiClient();
|
|
9898
10404
|
const distinctId = PaywalloClient.getDistinctId();
|
|
9899
10405
|
if (!apiClient || !distinctId) return false;
|
|
@@ -9913,7 +10419,7 @@ function useSubscriptionSync() {
|
|
|
9913
10419
|
return resolveOfflineFromCache(distinctId);
|
|
9914
10420
|
}
|
|
9915
10421
|
}, [setCacheAndState]);
|
|
9916
|
-
const getSubscription = (0,
|
|
10422
|
+
const getSubscription = (0, import_react26.useCallback)(async () => {
|
|
9917
10423
|
const apiClient = PaywalloClient.getApiClient();
|
|
9918
10424
|
const distinctId = PaywalloClient.getDistinctId();
|
|
9919
10425
|
if (!apiClient || !distinctId) return null;
|
|
@@ -9934,214 +10440,24 @@ function useSubscriptionSync() {
|
|
|
9934
10440
|
return { subscription, hasActiveSubscription, getSubscription, invalidateCache };
|
|
9935
10441
|
}
|
|
9936
10442
|
|
|
9937
|
-
// src/domains/paywall/SuperwallAutoBridge.ts
|
|
9938
|
-
init_PaywalloClient();
|
|
9939
|
-
|
|
9940
|
-
// src/core/utils/eventId.ts
|
|
9941
|
-
function hashString(input) {
|
|
9942
|
-
let h1 = 3735928559;
|
|
9943
|
-
let h2 = 1103547991;
|
|
9944
|
-
for (let i = 0; i < input.length; i++) {
|
|
9945
|
-
const ch = input.charCodeAt(i);
|
|
9946
|
-
h1 = Math.imul(h1 ^ ch, 2654435769);
|
|
9947
|
-
h2 = Math.imul(h2 ^ ch, 1598716949);
|
|
9948
|
-
}
|
|
9949
|
-
h1 = Math.imul(h1 ^ h1 >>> 16, 73244475);
|
|
9950
|
-
h1 ^= Math.imul(h2 ^ h2 >>> 13, 351452291);
|
|
9951
|
-
h2 = Math.imul(h2 ^ h2 >>> 16, 73244475);
|
|
9952
|
-
h2 ^= Math.imul(h1 ^ h1 >>> 13, 351452291);
|
|
9953
|
-
const toHex = (n) => (n >>> 0).toString(16).padStart(8, "0");
|
|
9954
|
-
return toHex(h1) + toHex(h2);
|
|
9955
|
-
}
|
|
9956
|
-
function buildDeterministicEventId(parts) {
|
|
9957
|
-
const raw = hashString(parts.join("|"));
|
|
9958
|
-
const p1 = raw.slice(0, 8);
|
|
9959
|
-
const p2 = raw.slice(8, 12);
|
|
9960
|
-
const p3 = "4" + raw.slice(13, 16);
|
|
9961
|
-
const p4 = (parseInt(raw[16], 16) & 3 | 8).toString(16) + raw.slice(17, 20);
|
|
9962
|
-
const p5 = raw.padEnd(32, "0").slice(20, 32);
|
|
9963
|
-
return `${p1}-${p2}-${p3}-${p4}-${p5}`;
|
|
9964
|
-
}
|
|
9965
|
-
|
|
9966
|
-
// src/domains/paywall/SuperwallAutoBridge.ts
|
|
9967
|
-
var bridgeStarted = false;
|
|
9968
|
-
var unsubscribe = null;
|
|
9969
|
-
var debugEnabled = false;
|
|
9970
|
-
function log(msg, data) {
|
|
9971
|
-
if (!debugEnabled) return;
|
|
9972
|
-
if (data !== void 0) {
|
|
9973
|
-
console.log(`[Paywallo:SuperwallBridge] ${msg}`, data);
|
|
9974
|
-
} else {
|
|
9975
|
-
console.log(`[Paywallo:SuperwallBridge] ${msg}`);
|
|
9976
|
-
}
|
|
9977
|
-
}
|
|
9978
|
-
function minuteBucket(ts) {
|
|
9979
|
-
return String(Math.floor(ts / 6e4));
|
|
9980
|
-
}
|
|
9981
|
-
function buildEventId(type, identifier, ts) {
|
|
9982
|
-
return buildDeterministicEventId(["sw", type, identifier, minuteBucket(ts)]);
|
|
9983
|
-
}
|
|
9984
|
-
async function trackPaywallEvent(type, identifier, ts, extra) {
|
|
9985
|
-
const _eventId = buildEventId(type, identifier, ts);
|
|
9986
|
-
try {
|
|
9987
|
-
const cleanExtra = {};
|
|
9988
|
-
if (extra) {
|
|
9989
|
-
for (const [k, v] of Object.entries(extra)) if (v !== void 0) cleanExtra[k] = v;
|
|
9990
|
-
}
|
|
9991
|
-
await PaywalloClient.track("paywall", {
|
|
9992
|
-
priority: "critical",
|
|
9993
|
-
properties: {
|
|
9994
|
-
type,
|
|
9995
|
-
paywall_id: identifier,
|
|
9996
|
-
...cleanExtra
|
|
9997
|
-
}
|
|
9998
|
-
});
|
|
9999
|
-
} catch (err) {
|
|
10000
|
-
log("track error", { type, identifier, eventId: _eventId, err: String(err) });
|
|
10001
|
-
}
|
|
10002
|
-
}
|
|
10003
|
-
function mapDismissToCloseReason(resultType) {
|
|
10004
|
-
switch (resultType) {
|
|
10005
|
-
case "purchased":
|
|
10006
|
-
return "purchased";
|
|
10007
|
-
case "restored":
|
|
10008
|
-
return "purchased";
|
|
10009
|
-
// restore counts as a purchase outcome for funnel
|
|
10010
|
-
case "declined":
|
|
10011
|
-
return "dismissed";
|
|
10012
|
-
default:
|
|
10013
|
-
return void 0;
|
|
10014
|
-
}
|
|
10015
|
-
}
|
|
10016
|
-
function buildCallbacks() {
|
|
10017
|
-
return {
|
|
10018
|
-
onPaywallPresent: (info) => {
|
|
10019
|
-
const ts = Date.now();
|
|
10020
|
-
log("onPaywallPresent", { identifier: info.identifier });
|
|
10021
|
-
void trackPaywallEvent("viewed", info.identifier, ts, {
|
|
10022
|
-
placement: info.presentedByEventWithName,
|
|
10023
|
-
variant_id: info.experiment?.variant?.id,
|
|
10024
|
-
campaign_id: info.experiment?.id
|
|
10025
|
-
});
|
|
10026
|
-
},
|
|
10027
|
-
onPaywallDismiss: (info, result) => {
|
|
10028
|
-
const ts = Date.now();
|
|
10029
|
-
log("onPaywallDismiss", { identifier: info.identifier, result: result.type });
|
|
10030
|
-
void trackPaywallEvent("closed", info.identifier, ts, {
|
|
10031
|
-
placement: info.presentedByEventWithName,
|
|
10032
|
-
variant_id: info.experiment?.variant?.id,
|
|
10033
|
-
campaign_id: info.experiment?.id,
|
|
10034
|
-
close_reason: mapDismissToCloseReason(result.type),
|
|
10035
|
-
closed_at: new Date(ts).toISOString()
|
|
10036
|
-
});
|
|
10037
|
-
},
|
|
10038
|
-
onPurchase: (params) => {
|
|
10039
|
-
const ts = Date.now();
|
|
10040
|
-
const safe = params !== null && typeof params === "object" ? params : {};
|
|
10041
|
-
const productId = "productId" in safe && typeof safe.productId === "string" ? safe.productId : "unknown";
|
|
10042
|
-
const identifier = "paywallIdentifier" in safe && typeof safe.paywallIdentifier === "string" ? safe.paywallIdentifier : productId;
|
|
10043
|
-
log("onPurchase", { productId, identifier });
|
|
10044
|
-
void trackPaywallEvent("purchased", identifier, ts, { product_id: productId });
|
|
10045
|
-
},
|
|
10046
|
-
// Global Superwall event listener — used specifically for `transactionComplete`
|
|
10047
|
-
// which is the only event that exposes the full product (currency/price) +
|
|
10048
|
-
// transaction (storeTransactionId) shape needed to create a server-side
|
|
10049
|
-
// `transactions` row. Other events are skipped (paywallOpen/Dismiss already
|
|
10050
|
-
// handled above with their typed callbacks).
|
|
10051
|
-
onSuperwallEvent: (info) => {
|
|
10052
|
-
const ev = info?.event;
|
|
10053
|
-
if (!ev || ev.event !== "transactionComplete") return;
|
|
10054
|
-
const ts = Date.now();
|
|
10055
|
-
const product = ev.product;
|
|
10056
|
-
const transaction = ev.transaction;
|
|
10057
|
-
if (!product) {
|
|
10058
|
-
log("transactionComplete missing product \u2014 skipping transaction track");
|
|
10059
|
-
return;
|
|
10060
|
-
}
|
|
10061
|
-
const productId = product.productIdentifier ?? product.id ?? "unknown";
|
|
10062
|
-
const currency = product.currencyCode ?? "USD";
|
|
10063
|
-
const price = product.price ?? 0;
|
|
10064
|
-
const transactionId = transaction?.storeTransactionId ?? transaction?.originalTransactionIdentifier ?? `${productId}_${String(ts)}`;
|
|
10065
|
-
const isTrial = product.hasFreeTrial === true || (product.trialPeriodPrice ?? 0) > 0;
|
|
10066
|
-
const paywallIdentifier = ev.paywallInfo?.identifier;
|
|
10067
|
-
log("onSuperwallEvent: transactionComplete", { productId, currency, price, transactionId, isTrial });
|
|
10068
|
-
void (async () => {
|
|
10069
|
-
try {
|
|
10070
|
-
await PaywalloClient.track("transaction", {
|
|
10071
|
-
priority: "critical",
|
|
10072
|
-
properties: {
|
|
10073
|
-
type: isTrial ? "trial_started" : "completed",
|
|
10074
|
-
// Server's IngestTranslator looks for `transaction_id`/`product_id`
|
|
10075
|
-
// /`amount`/`currency`/`paywall_id` keys (not `tx_id`). PurchaseHandler
|
|
10076
|
-
// then resolves type=trial/new/renewal based on amount being 0 vs >0.
|
|
10077
|
-
transaction_id: transactionId,
|
|
10078
|
-
product_id: productId,
|
|
10079
|
-
amount: price,
|
|
10080
|
-
currency,
|
|
10081
|
-
...paywallIdentifier ? { paywall_id: paywallIdentifier } : {}
|
|
10082
|
-
}
|
|
10083
|
-
});
|
|
10084
|
-
} catch (err) {
|
|
10085
|
-
log("transactionComplete track error", { err: String(err) });
|
|
10086
|
-
}
|
|
10087
|
-
})();
|
|
10088
|
-
}
|
|
10089
|
-
};
|
|
10090
|
-
}
|
|
10091
|
-
function startSuperwallAutoBridge(debug = false) {
|
|
10092
|
-
debugEnabled = debug;
|
|
10093
|
-
if (bridgeStarted) {
|
|
10094
|
-
log("already started, skipping");
|
|
10095
|
-
return;
|
|
10096
|
-
}
|
|
10097
|
-
void detectAndStart();
|
|
10098
|
-
}
|
|
10099
|
-
async function detectAndStart() {
|
|
10100
|
-
let subscribeFn;
|
|
10101
|
-
try {
|
|
10102
|
-
const mod = await import("expo-superwall");
|
|
10103
|
-
if (!mod || typeof mod.subscribeToSuperwallEvents !== "function") {
|
|
10104
|
-
const internal = await import("expo-superwall/build/src/internal/superwallEventBridge");
|
|
10105
|
-
if (typeof internal.subscribeToSuperwallEvents !== "function") {
|
|
10106
|
-
log("expo-superwall subscribeToSuperwallEvents not found \u2014 bridge inactive");
|
|
10107
|
-
return;
|
|
10108
|
-
}
|
|
10109
|
-
subscribeFn = internal.subscribeToSuperwallEvents;
|
|
10110
|
-
} else {
|
|
10111
|
-
subscribeFn = mod.subscribeToSuperwallEvents;
|
|
10112
|
-
}
|
|
10113
|
-
} catch {
|
|
10114
|
-
log("expo-superwall not installed \u2014 bridge inactive");
|
|
10115
|
-
return;
|
|
10116
|
-
}
|
|
10117
|
-
try {
|
|
10118
|
-
const callbacks = buildCallbacks();
|
|
10119
|
-
unsubscribe = subscribeFn(void 0, () => callbacks);
|
|
10120
|
-
bridgeStarted = true;
|
|
10121
|
-
log("bridge started");
|
|
10122
|
-
} catch (err) {
|
|
10123
|
-
log("subscribe failed", { err: String(err) });
|
|
10124
|
-
}
|
|
10125
|
-
}
|
|
10126
|
-
|
|
10127
10443
|
// src/PaywalloProvider.tsx
|
|
10128
10444
|
init_localization();
|
|
10129
|
-
var
|
|
10445
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
10130
10446
|
function PaywalloProvider({ children, config }) {
|
|
10131
|
-
const [isInitialized, setIsInitialized] = (0,
|
|
10132
|
-
const [initError, setInitError] = (0,
|
|
10133
|
-
const [distinctId, setDistinctId] = (0,
|
|
10134
|
-
const [activePaywall, setActivePaywall] = (0,
|
|
10447
|
+
const [isInitialized, setIsInitialized] = (0, import_react27.useState)(false);
|
|
10448
|
+
const [initError, setInitError] = (0, import_react27.useState)(null);
|
|
10449
|
+
const [distinctId, setDistinctId] = (0, import_react27.useState)(null);
|
|
10450
|
+
const [activePaywall, setActivePaywall] = (0, import_react27.useState)(null);
|
|
10135
10451
|
const { products, isLoadingProducts, refreshProducts } = useProductLoader();
|
|
10136
10452
|
const { subscription, hasActiveSubscription, getSubscription, invalidateCache } = useSubscriptionSync();
|
|
10137
10453
|
const { preloadedWebView, setPreloadedWebView, preloadCampaign, consumePreloadedCampaign, isPreloadValid } = useCampaignPreload();
|
|
10138
|
-
const clearPreloadedWebView = (0,
|
|
10139
|
-
const autoPreloadTriggeredRef = (0,
|
|
10140
|
-
const preloadedWebViewRef = (0,
|
|
10141
|
-
const pollTimerRef = (0,
|
|
10142
|
-
const pollCancelledRef = (0,
|
|
10143
|
-
const secureStorageRef = (0,
|
|
10144
|
-
(0,
|
|
10454
|
+
const clearPreloadedWebView = (0, import_react27.useCallback)(() => setPreloadedWebView(null), [setPreloadedWebView]);
|
|
10455
|
+
const autoPreloadTriggeredRef = (0, import_react27.useRef)(false);
|
|
10456
|
+
const preloadedWebViewRef = (0, import_react27.useRef)(preloadedWebView);
|
|
10457
|
+
const pollTimerRef = (0, import_react27.useRef)(null);
|
|
10458
|
+
const pollCancelledRef = (0, import_react27.useRef)(false);
|
|
10459
|
+
const secureStorageRef = (0, import_react27.useRef)(new SecureStorage(config.debug));
|
|
10460
|
+
(0, import_react27.useEffect)(() => {
|
|
10145
10461
|
preloadedWebViewRef.current = preloadedWebView;
|
|
10146
10462
|
}, [preloadedWebView]);
|
|
10147
10463
|
useAppAutoEvents({
|
|
@@ -10167,22 +10483,22 @@ function PaywalloProvider({ children, config }) {
|
|
|
10167
10483
|
},
|
|
10168
10484
|
debug: config.debug
|
|
10169
10485
|
});
|
|
10170
|
-
const triggerRepreload = (0,
|
|
10486
|
+
const triggerRepreload = (0, import_react27.useCallback)((placement) => {
|
|
10171
10487
|
void PaywalloClient.preloadCampaign(placement).catch(() => {
|
|
10172
10488
|
});
|
|
10173
10489
|
}, []);
|
|
10174
10490
|
const { showingPreloadedWebView, presentPreloadedWebView, resolvePreloadedPaywall, handlePreloadedWebViewReady: baseHandlePreloadedWebViewReady, handlePreloadedClose: baseHandlePreloadedClose, setShowingPreloadedWebView, presentedAtRef } = usePaywallPresenter(preloadedWebView, setPreloadedWebView);
|
|
10175
|
-
const SCREEN_HEIGHT = (0,
|
|
10176
|
-
const slideAnim = (0,
|
|
10177
|
-
const handlePreloadedWebViewReady = (0,
|
|
10491
|
+
const SCREEN_HEIGHT = (0, import_react27.useMemo)(() => import_react_native29.Dimensions.get("window").height, []);
|
|
10492
|
+
const slideAnim = (0, import_react27.useRef)(new import_react_native29.Animated.Value(SCREEN_HEIGHT)).current;
|
|
10493
|
+
const handlePreloadedWebViewReady = (0, import_react27.useCallback)(() => {
|
|
10178
10494
|
if (PaywalloClient.getConfig()?.debug) {
|
|
10179
10495
|
console.log(`[Paywallo WEBVIEW] loaded \u2014 placement: ${preloadedWebView?.placement}`);
|
|
10180
10496
|
}
|
|
10181
10497
|
baseHandlePreloadedWebViewReady();
|
|
10182
10498
|
}, [preloadedWebView?.placement, baseHandlePreloadedWebViewReady]);
|
|
10183
|
-
const handlePreloadedClose = (0,
|
|
10499
|
+
const handlePreloadedClose = (0, import_react27.useCallback)(() => {
|
|
10184
10500
|
const placement = preloadedWebView?.placement;
|
|
10185
|
-
|
|
10501
|
+
import_react_native29.Animated.timing(slideAnim, { toValue: SCREEN_HEIGHT, duration: 200, easing: import_react_native29.Easing.in(import_react_native29.Easing.cubic), useNativeDriver: true }).start(() => {
|
|
10186
10502
|
baseHandlePreloadedClose();
|
|
10187
10503
|
if (placement) triggerRepreload(placement);
|
|
10188
10504
|
});
|
|
@@ -10195,8 +10511,8 @@ function PaywalloProvider({ children, config }) {
|
|
|
10195
10511
|
presentedAtRef,
|
|
10196
10512
|
invalidateCache
|
|
10197
10513
|
);
|
|
10198
|
-
const [isPreloadPurchasing, setIsPreloadPurchasing] = (0,
|
|
10199
|
-
const handlePreloadedPurchase = (0,
|
|
10514
|
+
const [isPreloadPurchasing, setIsPreloadPurchasing] = (0, import_react27.useState)(false);
|
|
10515
|
+
const handlePreloadedPurchase = (0, import_react27.useCallback)(async (productId) => {
|
|
10200
10516
|
setIsPreloadPurchasing(true);
|
|
10201
10517
|
try {
|
|
10202
10518
|
await rawPreloadedPurchase(productId);
|
|
@@ -10204,8 +10520,8 @@ function PaywalloProvider({ children, config }) {
|
|
|
10204
10520
|
setIsPreloadPurchasing(false);
|
|
10205
10521
|
}
|
|
10206
10522
|
}, [rawPreloadedPurchase]);
|
|
10207
|
-
const configRef = (0,
|
|
10208
|
-
(0,
|
|
10523
|
+
const configRef = (0, import_react27.useRef)(config);
|
|
10524
|
+
(0, import_react27.useEffect)(() => {
|
|
10209
10525
|
let mounted = true;
|
|
10210
10526
|
initLocalization({ detectDevice: true });
|
|
10211
10527
|
PaywalloClient.init(configRef.current).then(async () => {
|
|
@@ -10218,6 +10534,11 @@ function PaywalloProvider({ children, config }) {
|
|
|
10218
10534
|
const placement = await PaywalloClient.waitForAutoPreloadedPlacement();
|
|
10219
10535
|
if (mounted && placement) void preloadCampaign(placement).catch(() => {
|
|
10220
10536
|
});
|
|
10537
|
+
const preloadPlacements = configRef.current.preloadPaywalls;
|
|
10538
|
+
if (mounted && preloadPlacements && preloadPlacements.length > 0) {
|
|
10539
|
+
void PaywalloClient.preloadPaywalls(preloadPlacements).catch(() => {
|
|
10540
|
+
});
|
|
10541
|
+
}
|
|
10221
10542
|
}
|
|
10222
10543
|
}).catch((err) => {
|
|
10223
10544
|
if (!mounted) return;
|
|
@@ -10227,14 +10548,29 @@ function PaywalloProvider({ children, config }) {
|
|
|
10227
10548
|
mounted = false;
|
|
10228
10549
|
};
|
|
10229
10550
|
}, [preloadCampaign]);
|
|
10230
|
-
const getPaywallConfig = (0,
|
|
10551
|
+
const getPaywallConfig = (0, import_react27.useCallback)(async (p) => {
|
|
10231
10552
|
const api = PaywalloClient.getApiClient();
|
|
10232
10553
|
return api ? api.getPaywall(p) : null;
|
|
10233
10554
|
}, []);
|
|
10234
|
-
const presentPaywall = (0,
|
|
10235
|
-
|
|
10555
|
+
const presentPaywall = (0, import_react27.useCallback)((placement) => {
|
|
10556
|
+
const preloaded = paywallPreloadService.getPreloaded(placement);
|
|
10557
|
+
return new Promise((resolve) => setActivePaywall({
|
|
10558
|
+
placement,
|
|
10559
|
+
resolver: resolve,
|
|
10560
|
+
...preloaded && {
|
|
10561
|
+
paywallConfig: {
|
|
10562
|
+
id: preloaded.config.id,
|
|
10563
|
+
placement: preloaded.config.placement,
|
|
10564
|
+
config: preloaded.config.config,
|
|
10565
|
+
primaryProductId: preloaded.config.primaryProductId,
|
|
10566
|
+
secondaryProductId: preloaded.config.secondaryProductId,
|
|
10567
|
+
tertiaryProductId: preloaded.config.tertiaryProductId
|
|
10568
|
+
},
|
|
10569
|
+
preloadedProducts: preloaded.products
|
|
10570
|
+
}
|
|
10571
|
+
}));
|
|
10236
10572
|
}, []);
|
|
10237
|
-
const trackCampaignImpression = (0,
|
|
10573
|
+
const trackCampaignImpression = (0, import_react27.useCallback)((placement, variantKey, campaignId) => {
|
|
10238
10574
|
const api = PaywalloClient.getApiClient();
|
|
10239
10575
|
if (!api) return;
|
|
10240
10576
|
const sessionId = PaywalloClient.getSessionId();
|
|
@@ -10248,7 +10584,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10248
10584
|
}).catch(() => {
|
|
10249
10585
|
});
|
|
10250
10586
|
}, []);
|
|
10251
|
-
const presentCampaign = (0,
|
|
10587
|
+
const presentCampaign = (0, import_react27.useCallback)(
|
|
10252
10588
|
async (placement, context) => {
|
|
10253
10589
|
try {
|
|
10254
10590
|
if (preloadedWebView?.placement === placement && preloadedWebView.loaded && isPreloadValid(placement)) {
|
|
@@ -10322,7 +10658,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10322
10658
|
},
|
|
10323
10659
|
[preloadedWebView, isPreloadValid, consumePreloadedCampaign, presentPreloadedWebView, trackCampaignImpression]
|
|
10324
10660
|
);
|
|
10325
|
-
const restorePurchases = (0,
|
|
10661
|
+
const restorePurchases = (0, import_react27.useCallback)(async () => {
|
|
10326
10662
|
invalidateCache();
|
|
10327
10663
|
try {
|
|
10328
10664
|
const txs = await getIAPService().restore();
|
|
@@ -10331,13 +10667,13 @@ function PaywalloProvider({ children, config }) {
|
|
|
10331
10667
|
return { success: false, restoredProducts: [], error: error instanceof Error ? error : new PurchaseError(PURCHASE_ERROR_CODES.RESTORE_FAILED, String(error)) };
|
|
10332
10668
|
}
|
|
10333
10669
|
}, [invalidateCache]);
|
|
10334
|
-
const handlePaywallResult = (0,
|
|
10670
|
+
const handlePaywallResult = (0, import_react27.useCallback)((result) => {
|
|
10335
10671
|
if (activePaywall) {
|
|
10336
10672
|
activePaywall.resolver(result);
|
|
10337
10673
|
setActivePaywall(null);
|
|
10338
10674
|
}
|
|
10339
10675
|
}, [activePaywall]);
|
|
10340
|
-
const bridgePaywallPresenter = (0,
|
|
10676
|
+
const bridgePaywallPresenter = (0, import_react27.useCallback)((placement) => {
|
|
10341
10677
|
if (PaywalloClient.getConfig()?.debug) {
|
|
10342
10678
|
console.log(`[Paywallo PRESENT] called \u2014 preloaded: ${preloadedWebViewRef.current?.loaded === true} placement: ${placement}`);
|
|
10343
10679
|
}
|
|
@@ -10366,7 +10702,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10366
10702
|
}
|
|
10367
10703
|
return presentCampaign(placement);
|
|
10368
10704
|
}, [presentPreloadedWebView, presentCampaign]);
|
|
10369
|
-
(0,
|
|
10705
|
+
(0, import_react27.useEffect)(() => {
|
|
10370
10706
|
if (!isInitialized) return;
|
|
10371
10707
|
const onEmergency = async (id) => {
|
|
10372
10708
|
try {
|
|
@@ -10393,9 +10729,9 @@ function PaywalloProvider({ children, config }) {
|
|
|
10393
10729
|
};
|
|
10394
10730
|
}, [isInitialized, bridgePaywallPresenter, getSubscription, hasActiveSubscription, restorePurchases]);
|
|
10395
10731
|
const isReady = isInitialized && !isLoadingProducts;
|
|
10396
|
-
const noOp = (0,
|
|
10732
|
+
const noOp = (0, import_react27.useCallback)(() => {
|
|
10397
10733
|
}, []);
|
|
10398
|
-
const contextValue = (0,
|
|
10734
|
+
const contextValue = (0, import_react27.useMemo)(() => ({
|
|
10399
10735
|
config: PaywalloClient.getConfig(),
|
|
10400
10736
|
isInitialized,
|
|
10401
10737
|
isReady,
|
|
@@ -10429,20 +10765,20 @@ function PaywalloProvider({ children, config }) {
|
|
|
10429
10765
|
getPaywallConfig,
|
|
10430
10766
|
refreshProducts
|
|
10431
10767
|
]);
|
|
10432
|
-
(0,
|
|
10768
|
+
(0, import_react27.useLayoutEffect)(() => {
|
|
10433
10769
|
if (showingPreloadedWebView) {
|
|
10434
10770
|
slideAnim.setValue(SCREEN_HEIGHT);
|
|
10435
|
-
|
|
10771
|
+
import_react_native29.Animated.timing(slideAnim, { toValue: 0, duration: 200, easing: import_react_native29.Easing.out(import_react_native29.Easing.cubic), useNativeDriver: true }).start();
|
|
10436
10772
|
}
|
|
10437
10773
|
}, [showingPreloadedWebView, slideAnim, SCREEN_HEIGHT]);
|
|
10438
10774
|
const preloadStyle = [
|
|
10439
|
-
|
|
10440
|
-
showingPreloadedWebView ?
|
|
10775
|
+
styles5.preloadOverlay,
|
|
10776
|
+
showingPreloadedWebView ? styles5.visible : styles5.hidden,
|
|
10441
10777
|
showingPreloadedWebView ? { transform: [{ translateY: slideAnim }] } : void 0
|
|
10442
10778
|
];
|
|
10443
|
-
return /* @__PURE__ */ (0,
|
|
10779
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(PaywalloContext.Provider, { value: contextValue, children: [
|
|
10444
10780
|
children,
|
|
10445
|
-
/* @__PURE__ */ (0,
|
|
10781
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PaywallErrorBoundary, { children: !!preloadedWebView?.craftData && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native29.Animated.View, { style: preloadStyle, pointerEvents: showingPreloadedWebView ? "auto" : "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
10446
10782
|
PaywallWebView,
|
|
10447
10783
|
{
|
|
10448
10784
|
paywallId: preloadedWebView.paywallId,
|
|
@@ -10458,7 +10794,7 @@ function PaywalloProvider({ children, config }) {
|
|
|
10458
10794
|
onRestore: showingPreloadedWebView ? handlePreloadedRestore : noOp
|
|
10459
10795
|
}
|
|
10460
10796
|
) }) }),
|
|
10461
|
-
/* @__PURE__ */ (0,
|
|
10797
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PaywallErrorBoundary, { children: activePaywall && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
10462
10798
|
PaywallModal,
|
|
10463
10799
|
{
|
|
10464
10800
|
placement: activePaywall.placement,
|
|
@@ -10470,10 +10806,11 @@ function PaywalloProvider({ children, config }) {
|
|
|
10470
10806
|
campaignId: activePaywall.campaignId,
|
|
10471
10807
|
variantId: activePaywall.variantId
|
|
10472
10808
|
}
|
|
10473
|
-
) })
|
|
10809
|
+
) }),
|
|
10810
|
+
isInitialized && (config.preloadPaywalls?.length ?? 0) > 0 && PaywalloClient.getWebUrl() !== null && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PaywallWebViewPrewarmer, { webUrl: PaywalloClient.getWebUrl() })
|
|
10474
10811
|
] });
|
|
10475
10812
|
}
|
|
10476
|
-
var
|
|
10813
|
+
var styles5 = import_react_native29.StyleSheet.create({
|
|
10477
10814
|
preloadOverlay: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: "#ffffff" },
|
|
10478
10815
|
hidden: { zIndex: -1, opacity: 0, width: 1, height: 1, overflow: "hidden" },
|
|
10479
10816
|
visible: { zIndex: 9999, opacity: 1 }
|
|
@@ -10529,6 +10866,9 @@ function resolveProductsVariable(parts, context) {
|
|
|
10529
10866
|
if (parts[1] === "secondary" && context.secondaryProductId) {
|
|
10530
10867
|
return getProductVariable(context.products.get(context.secondaryProductId), parts[2]);
|
|
10531
10868
|
}
|
|
10869
|
+
if (parts[1] === "tertiary" && context.tertiaryProductId) {
|
|
10870
|
+
return getProductVariable(context.products.get(context.tertiaryProductId), parts[2]);
|
|
10871
|
+
}
|
|
10532
10872
|
if (parts[1] === "hasIntroductoryOffer") {
|
|
10533
10873
|
return Array.from(context.products.values()).some((p) => p.introductoryPrice) ? "true" : "false";
|
|
10534
10874
|
}
|