@billdog.io/react-native 1.0.0-beta.2
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/BillDogReactNative.podspec +30 -0
- package/LICENSE +21 -0
- package/README.md +330 -0
- package/android/build.gradle +99 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogABTestModule.kt +317 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogAnalyticsModule.kt +389 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogModule.kt +817 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogPaywallViewManager.kt +383 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogSurveyModule.kt +427 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogVirtualCurrencyModule.kt +407 -0
- package/android/src/main/kotlin/io/billdog/virtualcurrency/BillDogVirtualCurrencyPackage.kt +44 -0
- package/dist/AdvancedPaywallCache.d.ts +70 -0
- package/dist/AdvancedPaywallCache.js +344 -0
- package/dist/BillDog.d.ts +255 -0
- package/dist/BillDog.js +918 -0
- package/dist/BillDogConfiguration.d.ts +145 -0
- package/dist/BillDogConfiguration.js +229 -0
- package/dist/ComponentRenderer.d.ts +17 -0
- package/dist/ComponentRenderer.js +886 -0
- package/dist/LayoutEngine.d.ts +101 -0
- package/dist/LayoutEngine.js +394 -0
- package/dist/LocalizationResolver.d.ts +99 -0
- package/dist/LocalizationResolver.js +266 -0
- package/dist/NativePaywallView.d.ts +36 -0
- package/dist/NativePaywallView.js +59 -0
- package/dist/PaywallCache.d.ts +74 -0
- package/dist/PaywallCache.js +293 -0
- package/dist/PaywallStateManager.d.ts +62 -0
- package/dist/PaywallStateManager.js +147 -0
- package/dist/PaywallView.d.ts +42 -0
- package/dist/PaywallView.js +275 -0
- package/dist/ProductVariableProvider.d.ts +60 -0
- package/dist/ProductVariableProvider.js +239 -0
- package/dist/VariableResolver.d.ts +120 -0
- package/dist/VariableResolver.js +379 -0
- package/dist/WebViewPaywall.d.ts +75 -0
- package/dist/WebViewPaywall.js +360 -0
- package/dist/animations/presets.d.ts +49 -0
- package/dist/animations/presets.js +367 -0
- package/dist/components/AccoladeCpsComponent.d.ts +13 -0
- package/dist/components/AccoladeCpsComponent.js +248 -0
- package/dist/components/AccordionComponent.d.ts +10 -0
- package/dist/components/AccordionComponent.js +187 -0
- package/dist/components/AnimatedWrapper.d.ts +35 -0
- package/dist/components/AnimatedWrapper.js +277 -0
- package/dist/components/CarouselComponent.d.ts +23 -0
- package/dist/components/CarouselComponent.js +484 -0
- package/dist/components/ChartCurveComponent.d.ts +13 -0
- package/dist/components/ChartCurveComponent.js +333 -0
- package/dist/components/CheckboxComponent.d.ts +9 -0
- package/dist/components/CheckboxComponent.js +172 -0
- package/dist/components/ConfettiComponent.d.ts +9 -0
- package/dist/components/ConfettiComponent.js +172 -0
- package/dist/components/CountdownComponent.d.ts +16 -0
- package/dist/components/CountdownComponent.js +414 -0
- package/dist/components/DelayedXComponent.d.ts +12 -0
- package/dist/components/DelayedXComponent.js +240 -0
- package/dist/components/DrawerModalComponent.d.ts +20 -0
- package/dist/components/DrawerModalComponent.js +286 -0
- package/dist/components/GradientView.d.ts +38 -0
- package/dist/components/GradientView.js +126 -0
- package/dist/components/HapticFeedbackComponent.d.ts +16 -0
- package/dist/components/HapticFeedbackComponent.js +64 -0
- package/dist/components/HorizontalProductsComponent.d.ts +17 -0
- package/dist/components/HorizontalProductsComponent.js +284 -0
- package/dist/components/MultiChoiceGridComponent.d.ts +13 -0
- package/dist/components/MultiChoiceGridComponent.js +234 -0
- package/dist/components/NPSScaleComponent.d.ts +16 -0
- package/dist/components/NPSScaleComponent.js +260 -0
- package/dist/components/NavigationComponent.d.ts +26 -0
- package/dist/components/NavigationComponent.js +302 -0
- package/dist/components/OAuthButtonComponent.d.ts +20 -0
- package/dist/components/OAuthButtonComponent.js +237 -0
- package/dist/components/ProgressLoaderComponent.d.ts +13 -0
- package/dist/components/ProgressLoaderComponent.js +308 -0
- package/dist/components/ProgressStepperComponent.d.ts +18 -0
- package/dist/components/ProgressStepperComponent.js +228 -0
- package/dist/components/SegmentedPickerComponent.d.ts +10 -0
- package/dist/components/SegmentedPickerComponent.js +221 -0
- package/dist/components/ShareButtonsComponent.d.ts +21 -0
- package/dist/components/ShareButtonsComponent.js +265 -0
- package/dist/components/ShareCodeComponent.d.ts +16 -0
- package/dist/components/ShareCodeComponent.js +274 -0
- package/dist/components/SingleChoiceGridComponent.d.ts +13 -0
- package/dist/components/SingleChoiceGridComponent.js +210 -0
- package/dist/components/SliderComponent.d.ts +9 -0
- package/dist/components/SliderComponent.js +263 -0
- package/dist/components/StarRatingInputComponent.d.ts +20 -0
- package/dist/components/StarRatingInputComponent.js +198 -0
- package/dist/components/StickerCompositeComponent.d.ts +13 -0
- package/dist/components/StickerCompositeComponent.js +136 -0
- package/dist/components/TabsComponent.d.ts +19 -0
- package/dist/components/TabsComponent.js +431 -0
- package/dist/components/TextInputComponent.d.ts +18 -0
- package/dist/components/TextInputComponent.js +227 -0
- package/dist/components/TimelineComponent.d.ts +19 -0
- package/dist/components/TimelineComponent.js +104 -0
- package/dist/components/ToggleComponent.d.ts +14 -0
- package/dist/components/ToggleComponent.js +132 -0
- package/dist/components/VerticalProductsComponent.d.ts +17 -0
- package/dist/components/VerticalProductsComponent.js +311 -0
- package/dist/dynamicValues.d.ts +36 -0
- package/dist/dynamicValues.js +142 -0
- package/dist/filters/dateFilters.d.ts +50 -0
- package/dist/filters/dateFilters.js +390 -0
- package/dist/filters/index.d.ts +18 -0
- package/dist/filters/index.js +253 -0
- package/dist/hooks/useOfferings.d.ts +76 -0
- package/dist/hooks/useOfferings.js +99 -0
- package/dist/hooks/usePaywall.d.ts +27 -0
- package/dist/hooks/usePaywall.js +114 -0
- package/dist/hooks/usePlacement.d.ts +34 -0
- package/dist/hooks/usePlacement.js +89 -0
- package/dist/hooks/useSubscription.d.ts +40 -0
- package/dist/hooks/useSubscription.js +97 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.js +198 -0
- package/dist/models/BillDogError.d.ts +40 -0
- package/dist/models/BillDogError.js +11 -0
- package/dist/models/CacheFetchPolicy.d.ts +8 -0
- package/dist/models/CacheFetchPolicy.js +4 -0
- package/dist/models/CustomProduct.d.ts +32 -0
- package/dist/models/CustomProduct.js +15 -0
- package/dist/models/CustomerInfo.d.ts +17 -0
- package/dist/models/CustomerInfo.js +11 -0
- package/dist/models/Delegate.d.ts +20 -0
- package/dist/models/Delegate.js +11 -0
- package/dist/models/EntitlementInfo.d.ts +19 -0
- package/dist/models/EntitlementInfo.js +2 -0
- package/dist/models/Placement.d.ts +54 -0
- package/dist/models/Placement.js +15 -0
- package/dist/models/PurchaseParams.d.ts +39 -0
- package/dist/models/PurchaseParams.js +60 -0
- package/dist/models/PurchaseResult.d.ts +30 -0
- package/dist/models/PurchaseResult.js +15 -0
- package/dist/models/RestoreResult.d.ts +30 -0
- package/dist/models/RestoreResult.js +22 -0
- package/dist/models/RestoredItem.d.ts +26 -0
- package/dist/models/RestoredItem.js +13 -0
- package/dist/modules/ABTest.d.ts +65 -0
- package/dist/modules/ABTest.js +113 -0
- package/dist/modules/Analytics.d.ts +91 -0
- package/dist/modules/Analytics.js +182 -0
- package/dist/modules/Survey.d.ts +65 -0
- package/dist/modules/Survey.js +82 -0
- package/dist/modules/VirtualCurrency.d.ts +63 -0
- package/dist/modules/VirtualCurrency.js +147 -0
- package/dist/murmur.d.ts +23 -0
- package/dist/murmur.js +104 -0
- package/dist/notifications/LiveActivitiesManager.d.ts +47 -0
- package/dist/notifications/LiveActivitiesManager.js +106 -0
- package/dist/notifications/NotificationScheduler.d.ts +55 -0
- package/dist/notifications/NotificationScheduler.js +199 -0
- package/dist/notifications/PurchaseNotificationHandler.d.ts +24 -0
- package/dist/notifications/PurchaseNotificationHandler.js +55 -0
- package/dist/notifications/useDeviceToken.d.ts +36 -0
- package/dist/notifications/useDeviceToken.js +97 -0
- package/dist/notifications/useLiveActivity.d.ts +39 -0
- package/dist/notifications/useLiveActivity.js +104 -0
- package/dist/review/ReviewAnalytics.d.ts +34 -0
- package/dist/review/ReviewAnalytics.js +73 -0
- package/dist/review/ReviewManager.d.ts +83 -0
- package/dist/review/ReviewManager.js +339 -0
- package/dist/review/ReviewTimingManager.d.ts +82 -0
- package/dist/review/ReviewTimingManager.js +224 -0
- package/dist/survey-core/types.d.ts +215 -0
- package/dist/survey-core/types.js +8 -0
- package/dist/types.d.ts +438 -0
- package/dist/types.js +158 -0
- package/dist/utils/ApiClient.d.ts +65 -0
- package/dist/utils/ApiClient.js +132 -0
- package/dist/utils/CSSConverter.d.ts +49 -0
- package/dist/utils/CSSConverter.js +470 -0
- package/dist/utils/animations.d.ts +41 -0
- package/dist/utils/animations.js +194 -0
- package/dist/utils/calendarIntegration.d.ts +36 -0
- package/dist/utils/calendarIntegration.js +89 -0
- package/dist/utils/configurationResolver.d.ts +23 -0
- package/dist/utils/configurationResolver.js +78 -0
- package/dist/utils/deviceDetection.d.ts +38 -0
- package/dist/utils/deviceDetection.js +59 -0
- package/dist/utils/hapticFeedback.d.ts +17 -0
- package/dist/utils/hapticFeedback.js +53 -0
- package/dist/utils/iconMapper.d.ts +26 -0
- package/dist/utils/iconMapper.js +113 -0
- package/dist/utils/notificationPermissions.d.ts +13 -0
- package/dist/utils/notificationPermissions.js +51 -0
- package/dist/utils/priceFormatting.d.ts +19 -0
- package/dist/utils/priceFormatting.js +99 -0
- package/dist/utils/shareSheet.d.ts +17 -0
- package/dist/utils/shareSheet.js +42 -0
- package/dist/utils/subscriptionUpgrade.d.ts +84 -0
- package/dist/utils/subscriptionUpgrade.js +100 -0
- package/dist/valueUtils.d.ts +48 -0
- package/dist/valueUtils.js +129 -0
- package/dist/xFlowTags.d.ts +18 -0
- package/dist/xFlowTags.js +385 -0
- package/ios/BillDogABTest.m +50 -0
- package/ios/BillDogABTest.swift +188 -0
- package/ios/BillDogAnalytics.m +105 -0
- package/ios/BillDogAnalytics.swift +324 -0
- package/ios/BillDogBridge.m +222 -0
- package/ios/BillDogBridge.swift +715 -0
- package/ios/BillDogLiveActivities.m +41 -0
- package/ios/BillDogLiveActivities.swift +104 -0
- package/ios/BillDogPaywallViewManager.m +39 -0
- package/ios/BillDogPaywallViewManager.swift +361 -0
- package/ios/BillDogSurvey.m +34 -0
- package/ios/BillDogSurvey.swift +257 -0
- package/ios/BillDogVirtualCurrencyBridge.m +63 -0
- package/ios/BillDogVirtualCurrencyBridge.swift +511 -0
- package/junit.xml +25 -0
- package/package.json +61 -0
- package/react-native.config.js +13 -0
- package/src/AdvancedPaywallCache.ts +433 -0
- package/src/BillDog.ts +983 -0
- package/src/BillDogConfiguration.ts +318 -0
- package/src/ComponentRenderer.tsx +1325 -0
- package/src/LayoutEngine.ts +459 -0
- package/src/LocalizationResolver.ts +311 -0
- package/src/NativePaywallView.tsx +132 -0
- package/src/PaywallCache.ts +358 -0
- package/src/PaywallStateManager.ts +154 -0
- package/src/PaywallView.tsx +328 -0
- package/src/ProductVariableProvider.ts +282 -0
- package/src/VariableResolver.ts +516 -0
- package/src/WebViewPaywall.tsx +454 -0
- package/src/animations/presets.ts +421 -0
- package/src/components/AccoladeCpsComponent.tsx +259 -0
- package/src/components/AccordionComponent.tsx +213 -0
- package/src/components/AnimatedWrapper.tsx +316 -0
- package/src/components/CarouselComponent.tsx +615 -0
- package/src/components/ChartCurveComponent.tsx +452 -0
- package/src/components/CheckboxComponent.tsx +185 -0
- package/src/components/ConfettiComponent.tsx +178 -0
- package/src/components/CountdownComponent.tsx +454 -0
- package/src/components/DelayedXComponent.tsx +266 -0
- package/src/components/DrawerModalComponent.tsx +324 -0
- package/src/components/GradientView.tsx +129 -0
- package/src/components/HapticFeedbackComponent.tsx +39 -0
- package/src/components/HorizontalProductsComponent.tsx +329 -0
- package/src/components/MultiChoiceGridComponent.tsx +265 -0
- package/src/components/NPSScaleComponent.tsx +294 -0
- package/src/components/NavigationComponent.tsx +329 -0
- package/src/components/OAuthButtonComponent.tsx +266 -0
- package/src/components/ProgressLoaderComponent.tsx +366 -0
- package/src/components/ProgressStepperComponent.tsx +250 -0
- package/src/components/SegmentedPickerComponent.tsx +245 -0
- package/src/components/ShareButtonsComponent.tsx +299 -0
- package/src/components/ShareCodeComponent.tsx +303 -0
- package/src/components/SingleChoiceGridComponent.tsx +229 -0
- package/src/components/SliderComponent.tsx +280 -0
- package/src/components/StarRatingInputComponent.tsx +223 -0
- package/src/components/StickerCompositeComponent.tsx +168 -0
- package/src/components/TabsComponent.tsx +496 -0
- package/src/components/TextInputComponent.tsx +258 -0
- package/src/components/TimelineComponent.tsx +129 -0
- package/src/components/ToggleComponent.tsx +142 -0
- package/src/components/VerticalProductsComponent.tsx +357 -0
- package/src/dynamicValues.ts +180 -0
- package/src/filters/dateFilters.ts +411 -0
- package/src/filters/index.ts +281 -0
- package/src/hooks/useOfferings.ts +192 -0
- package/src/hooks/usePaywall.ts +154 -0
- package/src/hooks/usePlacement.ts +143 -0
- package/src/hooks/useSubscription.ts +154 -0
- package/src/index.ts +245 -0
- package/src/models/BillDogError.ts +24 -0
- package/src/models/CacheFetchPolicy.ts +13 -0
- package/src/models/CustomProduct.ts +33 -0
- package/src/models/CustomerInfo.ts +26 -0
- package/src/models/Delegate.ts +22 -0
- package/src/models/EntitlementInfo.ts +27 -0
- package/src/models/Placement.ts +50 -0
- package/src/models/PurchaseParams.ts +81 -0
- package/src/models/PurchaseResult.ts +32 -0
- package/src/models/RestoreResult.ts +27 -0
- package/src/models/RestoredItem.ts +25 -0
- package/src/modules/ABTest.ts +131 -0
- package/src/modules/Analytics.ts +227 -0
- package/src/modules/Survey.ts +126 -0
- package/src/modules/VirtualCurrency.ts +223 -0
- package/src/murmur.ts +102 -0
- package/src/notifications/LiveActivitiesManager.ts +140 -0
- package/src/notifications/NotificationScheduler.ts +292 -0
- package/src/notifications/PurchaseNotificationHandler.ts +67 -0
- package/src/notifications/useDeviceToken.ts +116 -0
- package/src/notifications/useLiveActivity.ts +125 -0
- package/src/review/ReviewAnalytics.ts +89 -0
- package/src/review/ReviewManager.ts +355 -0
- package/src/review/ReviewTimingManager.ts +265 -0
- package/src/survey-core/types.ts +244 -0
- package/src/types/ambient.d.ts +9 -0
- package/src/types.ts +680 -0
- package/src/utils/ApiClient.ts +163 -0
- package/src/utils/CSSConverter.ts +552 -0
- package/src/utils/animations.ts +232 -0
- package/src/utils/calendarIntegration.ts +113 -0
- package/src/utils/configurationResolver.ts +106 -0
- package/src/utils/deviceDetection.ts +83 -0
- package/src/utils/hapticFeedback.ts +55 -0
- package/src/utils/iconMapper.ts +102 -0
- package/src/utils/notificationPermissions.ts +48 -0
- package/src/utils/priceFormatting.ts +119 -0
- package/src/utils/shareSheet.ts +55 -0
- package/src/utils/subscriptionUpgrade.ts +183 -0
- package/src/valueUtils.ts +108 -0
- package/src/xFlowTags.ts +463 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LocalizationResolver = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const BillDogConfiguration_1 = require("./BillDogConfiguration");
|
|
6
|
+
/**
|
|
7
|
+
* Properties that can be localized
|
|
8
|
+
*/
|
|
9
|
+
const LOCALIZABLE_PROPERTIES = new Set([
|
|
10
|
+
'text', 'title', 'subtitle', 'label', 'placeholder',
|
|
11
|
+
'buttonText', 'ctaText', 'description', 'content',
|
|
12
|
+
'headerText', 'footerText', 'disclaimer'
|
|
13
|
+
]);
|
|
14
|
+
/**
|
|
15
|
+
* Right-to-left languages. CLDR-aligned 11-code set — kept identical to
|
|
16
|
+
* iOS `PaywallRenderer.swift rtlLocales` and Android
|
|
17
|
+
* `PaywallScreen.kt rtlLocales` so layout direction is consistent across
|
|
18
|
+
* every platform.
|
|
19
|
+
*/
|
|
20
|
+
const RTL_LOCALES = new Set([
|
|
21
|
+
'ar', 'he', 'fa', 'ur', 'ps', 'sd', 'yi', 'ku', 'ckb', 'dv', 'ug',
|
|
22
|
+
]);
|
|
23
|
+
/**
|
|
24
|
+
* Client-side localization resolver for React Native SDK
|
|
25
|
+
* Resolves localized text based on device locale with fallback to baseLocale
|
|
26
|
+
*/
|
|
27
|
+
class LocalizationResolver {
|
|
28
|
+
constructor(localizations, baseLocale = 'en', explicitLocale) {
|
|
29
|
+
this.localizations = localizations;
|
|
30
|
+
this.baseLocale = baseLocale;
|
|
31
|
+
// Priority: explicit locale > global config override > device locale
|
|
32
|
+
this.selectedLocale = explicitLocale !== null && explicitLocale !== void 0 ? explicitLocale : this.getEffectiveLocale();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get the effective locale. Precedence mirrors Android
|
|
36
|
+
* `BillDogConfig.getEffectiveLocale` (BillDogConfig.kt:150-152):
|
|
37
|
+
* runtime locale override > device locale > "en".
|
|
38
|
+
*
|
|
39
|
+
* Public + static so callers (e.g. WebViewPaywall's locale bridge) can
|
|
40
|
+
* resolve the active locale without constructing a resolver.
|
|
41
|
+
*/
|
|
42
|
+
static getEffectiveLocale() {
|
|
43
|
+
const configOverride = BillDogConfiguration_1.BillDogConfiguration.getLocaleOverride();
|
|
44
|
+
if (configOverride && configOverride.trim()) {
|
|
45
|
+
return configOverride;
|
|
46
|
+
}
|
|
47
|
+
return LocalizationResolver.detectDeviceLocale();
|
|
48
|
+
}
|
|
49
|
+
/** Instance accessor — defers to the canonical static resolver. */
|
|
50
|
+
getEffectiveLocale() {
|
|
51
|
+
return LocalizationResolver.getEffectiveLocale();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Returns true when `locale`'s language belongs to a right-to-left
|
|
55
|
+
* script. Matches against the language portion only (e.g. `ar-EG` → `ar`),
|
|
56
|
+
* mirroring Android `PaywallScreen.kt:431-458`.
|
|
57
|
+
*/
|
|
58
|
+
static isRtlLocale(locale) {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
if (!locale)
|
|
61
|
+
return false;
|
|
62
|
+
const language = (_b = (_a = locale.split(/[-_]/)[0]) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : '';
|
|
63
|
+
return RTL_LOCALES.has(language);
|
|
64
|
+
}
|
|
65
|
+
/** Detect the device locale from the platform native modules. */
|
|
66
|
+
static detectDeviceLocale() {
|
|
67
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
68
|
+
try {
|
|
69
|
+
if (react_native_1.Platform.OS === 'ios') {
|
|
70
|
+
return (((_c = (_b = (_a = react_native_1.NativeModules.SettingsManager) === null || _a === void 0 ? void 0 : _a.settings) === null || _b === void 0 ? void 0 : _b.AppleLocale) === null || _c === void 0 ? void 0 : _c.split('_')[0]) ||
|
|
71
|
+
((_g = (_f = (_e = (_d = react_native_1.NativeModules.SettingsManager) === null || _d === void 0 ? void 0 : _d.settings) === null || _e === void 0 ? void 0 : _e.AppleLanguages) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.split('-')[0]) ||
|
|
72
|
+
'en');
|
|
73
|
+
}
|
|
74
|
+
else if (react_native_1.Platform.OS === 'android') {
|
|
75
|
+
return ((_j = (_h = react_native_1.NativeModules.I18nManager) === null || _h === void 0 ? void 0 : _h.localeIdentifier) === null || _j === void 0 ? void 0 : _j.split('_')[0]) || 'en';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// Fall through to default.
|
|
80
|
+
}
|
|
81
|
+
return 'en';
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Set the active locale for resolution
|
|
85
|
+
*/
|
|
86
|
+
setLocale(locale) {
|
|
87
|
+
this.selectedLocale = locale;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get the currently selected locale
|
|
91
|
+
*/
|
|
92
|
+
getSelectedLocale() {
|
|
93
|
+
return this.selectedLocale;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get the base locale (source language)
|
|
97
|
+
*/
|
|
98
|
+
getBaseLocale() {
|
|
99
|
+
return this.baseLocale;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Find the matching locale key using the canonical 4-step matcher.
|
|
103
|
+
* Mirrors Android `LocalizationResolver.findLocaleKey` (LocalizationResolver.kt:50-86)
|
|
104
|
+
* and iOS `LocalizationResolver.findLocaleKey` exactly:
|
|
105
|
+
* 1. exact match
|
|
106
|
+
* 2. case-insensitive match
|
|
107
|
+
* 3. separator-normalized match (en-US ↔ en_US)
|
|
108
|
+
* 4. language-only fallback (en-US → en, or en → first en-* regional)
|
|
109
|
+
*/
|
|
110
|
+
findLocaleKey(locale) {
|
|
111
|
+
var _a;
|
|
112
|
+
if (!this.localizations || !locale)
|
|
113
|
+
return undefined;
|
|
114
|
+
const keys = Object.keys(this.localizations);
|
|
115
|
+
// Step 1: exact match
|
|
116
|
+
if (this.localizations[locale])
|
|
117
|
+
return locale;
|
|
118
|
+
// Step 2: case-insensitive match
|
|
119
|
+
const lower = locale.toLowerCase();
|
|
120
|
+
const ciMatch = keys.find(k => k.toLowerCase() === lower);
|
|
121
|
+
if (ciMatch)
|
|
122
|
+
return ciMatch;
|
|
123
|
+
// Step 3: separator-normalized match
|
|
124
|
+
const alt = locale.includes('-')
|
|
125
|
+
? locale.replace(/-/g, '_')
|
|
126
|
+
: locale.replace(/_/g, '-');
|
|
127
|
+
if (alt !== locale) {
|
|
128
|
+
if (this.localizations[alt])
|
|
129
|
+
return alt;
|
|
130
|
+
const altLower = alt.toLowerCase();
|
|
131
|
+
const altMatch = keys.find(k => k.toLowerCase() === altLower);
|
|
132
|
+
if (altMatch)
|
|
133
|
+
return altMatch;
|
|
134
|
+
}
|
|
135
|
+
// Step 4: language-only fallback
|
|
136
|
+
const languageOnly = (_a = locale.split(/[-_]/)[0]) !== null && _a !== void 0 ? _a : '';
|
|
137
|
+
if (languageOnly) {
|
|
138
|
+
const langLower = languageOnly.toLowerCase();
|
|
139
|
+
// Prefer an exact-language key (e.g. "en") over a regional variant
|
|
140
|
+
const exactLang = keys.find(k => k.toLowerCase() === langLower);
|
|
141
|
+
if (exactLang)
|
|
142
|
+
return exactLang;
|
|
143
|
+
// Otherwise any regional variant matching the language
|
|
144
|
+
const regional = keys.find(k => { var _a; return ((_a = k.split(/[-_]/)[0]) !== null && _a !== void 0 ? _a : '').toLowerCase() === langLower; });
|
|
145
|
+
if (regional)
|
|
146
|
+
return regional;
|
|
147
|
+
}
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Check if current locale is the base locale
|
|
152
|
+
*/
|
|
153
|
+
isBaseLocale() {
|
|
154
|
+
return this.selectedLocale.toLowerCase() === this.baseLocale.toLowerCase();
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get available locales from the localization data
|
|
158
|
+
*/
|
|
159
|
+
getAvailableLocales() {
|
|
160
|
+
const locales = new Set([this.baseLocale]);
|
|
161
|
+
if (this.localizations) {
|
|
162
|
+
Object.keys(this.localizations).forEach(key => locales.add(key));
|
|
163
|
+
}
|
|
164
|
+
return locales;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Resolve a localization key to its translated value
|
|
168
|
+
* Falls back to defaultValue if translation not found
|
|
169
|
+
*/
|
|
170
|
+
resolve(key, defaultValue) {
|
|
171
|
+
// If selected locale is base locale, return default (original) value
|
|
172
|
+
if (this.isBaseLocale()) {
|
|
173
|
+
return defaultValue;
|
|
174
|
+
}
|
|
175
|
+
// Try to find translation for selected locale (case-insensitive)
|
|
176
|
+
const matchedKey = this.findLocaleKey(this.selectedLocale);
|
|
177
|
+
const translations = matchedKey ? this.localizations[matchedKey] : undefined;
|
|
178
|
+
const translated = translations === null || translations === void 0 ? void 0 : translations[key];
|
|
179
|
+
if (translated !== undefined) {
|
|
180
|
+
return translated;
|
|
181
|
+
}
|
|
182
|
+
// Log missing translation for debugging
|
|
183
|
+
console.debug(`[LocalizationResolver] Translation not found for key '${key}' in locale '${this.selectedLocale}', using default`);
|
|
184
|
+
return defaultValue;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Resolve a variable value with localization support
|
|
188
|
+
* Variable keys are prefixed with locale for lookup
|
|
189
|
+
*/
|
|
190
|
+
resolveVariable(variableKey, defaultValue) {
|
|
191
|
+
var _a, _b;
|
|
192
|
+
if (this.isBaseLocale()) {
|
|
193
|
+
return defaultValue;
|
|
194
|
+
}
|
|
195
|
+
// Try locale-prefixed key first (e.g., "es.headline" for Spanish)
|
|
196
|
+
const localizedKey = `${this.selectedLocale}.${variableKey}`;
|
|
197
|
+
const matchedKey = this.findLocaleKey(this.selectedLocale);
|
|
198
|
+
const translations = matchedKey ? this.localizations[matchedKey] : undefined;
|
|
199
|
+
return ((_b = (_a = translations === null || translations === void 0 ? void 0 : translations[localizedKey]) !== null && _a !== void 0 ? _a : translations === null || translations === void 0 ? void 0 : translations[variableKey]) !== null && _b !== void 0 ? _b : defaultValue);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Resolve all localizable properties in a component.
|
|
203
|
+
*
|
|
204
|
+
* Lookup keys are componentId-prefixed (`<componentId>.<propertyName>`),
|
|
205
|
+
* matching the shape the dashboard `LocalizationPanel` writes and the
|
|
206
|
+
* Android `VariableResolver.resolveComponent` runtime path
|
|
207
|
+
* (VariableResolver.kt:124-156) + iOS `LocalizationResolver.swift:194-198`.
|
|
208
|
+
* Previously this looked up the source string itself as the key, which
|
|
209
|
+
* never matched the dashboard-authored translation maps.
|
|
210
|
+
*/
|
|
211
|
+
resolveComponent(component) {
|
|
212
|
+
var _a, _b;
|
|
213
|
+
const resolvedProperties = {};
|
|
214
|
+
const componentId = (_a = component.id) !== null && _a !== void 0 ? _a : '';
|
|
215
|
+
for (const [key, value] of Object.entries(component.properties || {})) {
|
|
216
|
+
if (typeof value === 'string' && LOCALIZABLE_PROPERTIES.has(key)) {
|
|
217
|
+
const localizationKey = componentId ? `${componentId}.${key}` : key;
|
|
218
|
+
resolvedProperties[key] = this.resolve(localizationKey, value);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
resolvedProperties[key] = value;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Recursively resolve children
|
|
225
|
+
const resolvedChildren = (_b = component.children) === null || _b === void 0 ? void 0 : _b.map(child => this.resolveComponent(child));
|
|
226
|
+
return {
|
|
227
|
+
...component,
|
|
228
|
+
properties: resolvedProperties,
|
|
229
|
+
children: resolvedChildren,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Resolve all components in a configuration
|
|
234
|
+
*/
|
|
235
|
+
resolveConfiguration(config) {
|
|
236
|
+
return {
|
|
237
|
+
...config,
|
|
238
|
+
components: config.components.map(c => this.resolveComponent(c)),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
// Factory Methods
|
|
242
|
+
/**
|
|
243
|
+
* Create resolver from PaywallConfiguration
|
|
244
|
+
* Respects global locale override from BillDogConfiguration
|
|
245
|
+
*/
|
|
246
|
+
static fromConfiguration(config) {
|
|
247
|
+
var _a;
|
|
248
|
+
return new LocalizationResolver(config.localizations, (_a = config.baseLocale) !== null && _a !== void 0 ? _a : 'en');
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Create resolver with device locale auto-detected
|
|
252
|
+
* Respects global locale override from BillDogConfiguration
|
|
253
|
+
*/
|
|
254
|
+
static withDeviceLocale(config) {
|
|
255
|
+
var _a;
|
|
256
|
+
return new LocalizationResolver(config.localizations, (_a = config.baseLocale) !== null && _a !== void 0 ? _a : 'en');
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Create resolver with specific locale (overrides global config)
|
|
260
|
+
*/
|
|
261
|
+
static withLocale(config, locale) {
|
|
262
|
+
var _a;
|
|
263
|
+
return new LocalizationResolver(config.localizations, (_a = config.baseLocale) !== null && _a !== void 0 ? _a : 'en', locale);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
exports.LocalizationResolver = LocalizationResolver;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NativePaywallView — renders a BillDog paywall by embedding the NATIVE paywall view
|
|
3
|
+
* (SwiftUI/UIKit on iOS, Jetpack Compose on Android) via a legacy (Paper) native
|
|
4
|
+
* component (`BDPaywallView`). This is the thin-bridge "Option 2" inline path: the
|
|
5
|
+
* native BillDog SDK renders the paywall and handles purchases; this component only
|
|
6
|
+
* hosts it and forwards its events.
|
|
7
|
+
*
|
|
8
|
+
* The pure-JS `PaywallView`/`ComponentRenderer` and `WebViewPaywall` remain available
|
|
9
|
+
* as alternative rendering strategies (e.g. for environments without the native module).
|
|
10
|
+
*/
|
|
11
|
+
import React from 'react';
|
|
12
|
+
import { type ViewStyle } from 'react-native';
|
|
13
|
+
export interface NativePaywallViewProps {
|
|
14
|
+
/** Placement / paywall identifier to load. */
|
|
15
|
+
identifier: string;
|
|
16
|
+
style?: ViewStyle;
|
|
17
|
+
/** Fired after a completed purchase (productId + native result fields). */
|
|
18
|
+
onPurchase?: (productId: string, data?: Record<string, unknown>) => void;
|
|
19
|
+
onDismiss?: () => void;
|
|
20
|
+
onRestore?: () => void;
|
|
21
|
+
onOpenUrl?: (url: string) => void;
|
|
22
|
+
onTrackEvent?: (event: string, data?: Record<string, unknown>) => void;
|
|
23
|
+
onLoaded?: () => void;
|
|
24
|
+
onError?: (message: string) => void;
|
|
25
|
+
/** Rendered when the native paywall component is unavailable on this platform. */
|
|
26
|
+
fallback?: React.ReactNode;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Inline native paywall. Requires the `BDPaywallView` native component (iOS
|
|
30
|
+
* `BillDogPaywallViewManager`, Android `BillDogPaywallViewManager`). When it is not
|
|
31
|
+
* registered, renders `fallback` (or nothing) instead of crashing.
|
|
32
|
+
*/
|
|
33
|
+
export declare function NativePaywallView(props: NativePaywallViewProps): React.ReactElement | null;
|
|
34
|
+
/** Whether the native paywall component is available on the current platform. */
|
|
35
|
+
export declare const isNativePaywallAvailable: boolean;
|
|
36
|
+
export default NativePaywallView;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
var _a;
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.isNativePaywallAvailable = void 0;
|
|
8
|
+
exports.NativePaywallView = NativePaywallView;
|
|
9
|
+
/**
|
|
10
|
+
* NativePaywallView — renders a BillDog paywall by embedding the NATIVE paywall view
|
|
11
|
+
* (SwiftUI/UIKit on iOS, Jetpack Compose on Android) via a legacy (Paper) native
|
|
12
|
+
* component (`BDPaywallView`). This is the thin-bridge "Option 2" inline path: the
|
|
13
|
+
* native BillDog SDK renders the paywall and handles purchases; this component only
|
|
14
|
+
* hosts it and forwards its events.
|
|
15
|
+
*
|
|
16
|
+
* The pure-JS `PaywallView`/`ComponentRenderer` and `WebViewPaywall` remain available
|
|
17
|
+
* as alternative rendering strategies (e.g. for environments without the native module).
|
|
18
|
+
*/
|
|
19
|
+
const react_1 = __importDefault(require("react"));
|
|
20
|
+
const react_native_1 = require("react-native");
|
|
21
|
+
const COMPONENT_NAME = 'BDPaywallView';
|
|
22
|
+
/** True only when the native view manager is actually registered on this platform. */
|
|
23
|
+
const isNativeComponentAvailable = ((_a = react_native_1.UIManager.getViewManagerConfig) === null || _a === void 0 ? void 0 : _a.call(react_native_1.UIManager, COMPONENT_NAME)) != null;
|
|
24
|
+
// Only bind the native component when it exists — requireNativeComponent otherwise
|
|
25
|
+
// logs a hard error on some RN versions.
|
|
26
|
+
const BDPaywallViewNative = isNativeComponentAvailable
|
|
27
|
+
? (0, react_native_1.requireNativeComponent)(COMPONENT_NAME)
|
|
28
|
+
: null;
|
|
29
|
+
/**
|
|
30
|
+
* Inline native paywall. Requires the `BDPaywallView` native component (iOS
|
|
31
|
+
* `BillDogPaywallViewManager`, Android `BillDogPaywallViewManager`). When it is not
|
|
32
|
+
* registered, renders `fallback` (or nothing) instead of crashing.
|
|
33
|
+
*/
|
|
34
|
+
function NativePaywallView(props) {
|
|
35
|
+
const { identifier, style, onPurchase, onDismiss, onRestore, onOpenUrl, onTrackEvent, onLoaded, onError, fallback, } = props;
|
|
36
|
+
if (BDPaywallViewNative == null) {
|
|
37
|
+
if (fallback != null)
|
|
38
|
+
return <>{fallback}</>;
|
|
39
|
+
if (__DEV__) {
|
|
40
|
+
return (<react_native_1.View style={[styles.fill, styles.center, style]}>
|
|
41
|
+
<react_native_1.Text style={styles.warn}>
|
|
42
|
+
BillDog: native paywall component "{COMPONENT_NAME}" is not registered
|
|
43
|
+
on {react_native_1.Platform.OS}. Ensure the native SDK is linked, or use PaywallView /
|
|
44
|
+
WebViewPaywall.
|
|
45
|
+
</react_native_1.Text>
|
|
46
|
+
</react_native_1.View>);
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
return (<BDPaywallViewNative paywallIdentifier={identifier} style={[styles.fill, style]} onLoaded={() => onLoaded === null || onLoaded === void 0 ? void 0 : onLoaded()} onError={(e) => { var _a, _b; return onError === null || onError === void 0 ? void 0 : onError((_b = (_a = e.nativeEvent) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : 'Unknown paywall error'); }} onPurchase={(e) => { var _a, _b, _c; return onPurchase === null || onPurchase === void 0 ? void 0 : onPurchase((_b = (_a = e.nativeEvent) === null || _a === void 0 ? void 0 : _a.productId) !== null && _b !== void 0 ? _b : '', (_c = e.nativeEvent) === null || _c === void 0 ? void 0 : _c.data); }} onDismiss={() => onDismiss === null || onDismiss === void 0 ? void 0 : onDismiss()} onRestore={() => onRestore === null || onRestore === void 0 ? void 0 : onRestore()} onOpenUrl={(e) => { var _a, _b; return onOpenUrl === null || onOpenUrl === void 0 ? void 0 : onOpenUrl((_b = (_a = e.nativeEvent) === null || _a === void 0 ? void 0 : _a.url) !== null && _b !== void 0 ? _b : ''); }} onTrackEvent={(e) => { var _a, _b, _c; return onTrackEvent === null || onTrackEvent === void 0 ? void 0 : onTrackEvent((_b = (_a = e.nativeEvent) === null || _a === void 0 ? void 0 : _a.event) !== null && _b !== void 0 ? _b : '', (_c = e.nativeEvent) === null || _c === void 0 ? void 0 : _c.data); }}/>);
|
|
51
|
+
}
|
|
52
|
+
/** Whether the native paywall component is available on the current platform. */
|
|
53
|
+
exports.isNativePaywallAvailable = isNativeComponentAvailable;
|
|
54
|
+
const styles = react_native_1.StyleSheet.create({
|
|
55
|
+
fill: { flex: 1 },
|
|
56
|
+
center: { alignItems: 'center', justifyContent: 'center', padding: 16 },
|
|
57
|
+
warn: { color: '#B00020', textAlign: 'center', fontSize: 13 },
|
|
58
|
+
});
|
|
59
|
+
exports.default = NativePaywallView;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PaywallCache - Smart caching layer for React Native
|
|
3
|
+
* Uses AsyncStorage for metadata and RNFS for asset caching
|
|
4
|
+
* Supports server-provided cache configuration
|
|
5
|
+
*/
|
|
6
|
+
export interface CacheConfig {
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
maxCacheAge: number;
|
|
9
|
+
backgroundUpdateEnabled: boolean;
|
|
10
|
+
preloadAssets: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare const DEFAULT_CACHE_CONFIG: CacheConfig;
|
|
13
|
+
export interface CachedPaywall {
|
|
14
|
+
paywall: {
|
|
15
|
+
id: string;
|
|
16
|
+
identifier: string;
|
|
17
|
+
name: string;
|
|
18
|
+
configuration: any;
|
|
19
|
+
version: number;
|
|
20
|
+
};
|
|
21
|
+
version: number;
|
|
22
|
+
cachedAt: number;
|
|
23
|
+
expiresAt: number;
|
|
24
|
+
etag?: string;
|
|
25
|
+
isFallback?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare class PaywallCache {
|
|
28
|
+
private config;
|
|
29
|
+
private cacheDir;
|
|
30
|
+
private fallbackCache;
|
|
31
|
+
constructor(config?: Partial<CacheConfig>);
|
|
32
|
+
/**
|
|
33
|
+
* Update cache configuration from server response
|
|
34
|
+
*/
|
|
35
|
+
configureFromServer(serverConfig: CacheConfig): void;
|
|
36
|
+
/**
|
|
37
|
+
* Get current cache configuration
|
|
38
|
+
*/
|
|
39
|
+
getConfig(): CacheConfig;
|
|
40
|
+
get(identifier: string): Promise<CachedPaywall | null>;
|
|
41
|
+
set(identifier: string, paywall: CachedPaywall): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Set a fallback paywall that will never be cleared
|
|
44
|
+
*/
|
|
45
|
+
setFallback(identifier: string, paywall: CachedPaywall): Promise<void>;
|
|
46
|
+
delete(identifier: string, includeFallback?: boolean): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Check if background update is needed and trigger if enabled
|
|
49
|
+
*/
|
|
50
|
+
shouldTriggerBackgroundUpdate(identifier: string): boolean;
|
|
51
|
+
markBackgroundUpdateStarted(identifier: string): void;
|
|
52
|
+
markBackgroundUpdateCompleted(identifier: string): void;
|
|
53
|
+
cacheAsset(url: string): Promise<string | null>;
|
|
54
|
+
/**
|
|
55
|
+
* Preload all assets from a paywall configuration
|
|
56
|
+
*/
|
|
57
|
+
preloadPaywallAssets(configuration: any): Promise<void>;
|
|
58
|
+
private extractAssetUrls;
|
|
59
|
+
getCachedAssetPath(url: string): Promise<string | null>;
|
|
60
|
+
/**
|
|
61
|
+
* Clear regular cache (preserves fallbacks)
|
|
62
|
+
*/
|
|
63
|
+
clearAll(): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Clear all cache including fallbacks
|
|
66
|
+
*/
|
|
67
|
+
clearAllIncludingFallbacks(): Promise<void>;
|
|
68
|
+
getStats(): Promise<{
|
|
69
|
+
paywallCount: number;
|
|
70
|
+
assetCount: number;
|
|
71
|
+
fallbackCount: number;
|
|
72
|
+
config: CacheConfig;
|
|
73
|
+
}>;
|
|
74
|
+
}
|