@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
package/dist/murmur.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MurmurHash3 (x86_32) — the ONE canonical deterministic bucketing hash.
|
|
4
|
+
*
|
|
5
|
+
* React Native port of the backend canonical `murmurhash3`
|
|
6
|
+
* (`supabase/functions/_shared/edge-serving/pure.ts`) and the dashboard copy
|
|
7
|
+
* (`src/lib/murmur.ts`). Used to derive the render-time `user.seed` Dynamic
|
|
8
|
+
* Values variable so a user buckets IDENTICALLY on every surface.
|
|
9
|
+
*
|
|
10
|
+
* RN-SPECIFIC: uses a manual UTF-8 encoder instead of `TextEncoder`, because
|
|
11
|
+
* Hermes historically ships without `TextEncoder`. The bytes it produces are
|
|
12
|
+
* identical to `TextEncoder().encode(...)` for the fixture inputs (incl.
|
|
13
|
+
* surrogate-pair emoji), so it stays pinned to the same corpus.
|
|
14
|
+
*
|
|
15
|
+
* CONTRACT (do not change without regenerating the fixture on ALL ports):
|
|
16
|
+
* user.seed = murmurhash3(appUserId) % 1000 → range 0..999
|
|
17
|
+
*
|
|
18
|
+
* Conformance-pinned to `native-sdks/_test-fixtures/conformance/core_user_seed.json`.
|
|
19
|
+
* Never validated against another SDK port.
|
|
20
|
+
*/
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.USER_SEED_MODULUS = void 0;
|
|
23
|
+
exports.murmurhash3 = murmurhash3;
|
|
24
|
+
exports.userSeedBucket = userSeedBucket;
|
|
25
|
+
/** UTF-8 encode without depending on TextEncoder (Hermes-safe). */
|
|
26
|
+
function utf8Bytes(str) {
|
|
27
|
+
const bytes = [];
|
|
28
|
+
for (let i = 0; i < str.length; i++) {
|
|
29
|
+
let code = str.charCodeAt(i);
|
|
30
|
+
if (code < 0x80) {
|
|
31
|
+
bytes.push(code);
|
|
32
|
+
}
|
|
33
|
+
else if (code < 0x800) {
|
|
34
|
+
bytes.push(0xc0 | (code >> 6), 0x80 | (code & 0x3f));
|
|
35
|
+
}
|
|
36
|
+
else if (code >= 0xd800 && code <= 0xdbff) {
|
|
37
|
+
// High surrogate — must be followed by a low surrogate.
|
|
38
|
+
const lo = str.charCodeAt(i + 1);
|
|
39
|
+
if (lo >= 0xdc00 && lo <= 0xdfff) {
|
|
40
|
+
i++;
|
|
41
|
+
code = 0x10000 + ((code - 0xd800) << 10) + (lo - 0xdc00);
|
|
42
|
+
bytes.push(0xf0 | (code >> 18), 0x80 | ((code >> 12) & 0x3f), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// Lone high surrogate → U+FFFD replacement char, matching TextEncoder.
|
|
46
|
+
bytes.push(0xef, 0xbf, 0xbd);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else if (code >= 0xdc00 && code <= 0xdfff) {
|
|
50
|
+
// Lone low surrogate → U+FFFD, matching TextEncoder.
|
|
51
|
+
bytes.push(0xef, 0xbf, 0xbd);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
bytes.push(0xe0 | (code >> 12), 0x80 | ((code >> 6) & 0x3f), 0x80 | (code & 0x3f));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return bytes;
|
|
58
|
+
}
|
|
59
|
+
function murmurhash3(key, seed = 0) {
|
|
60
|
+
const keyBytes = utf8Bytes(key);
|
|
61
|
+
let h1 = seed;
|
|
62
|
+
const c1 = 0xcc9e2d51;
|
|
63
|
+
const c2 = 0x1b873593;
|
|
64
|
+
const blocks = Math.floor(keyBytes.length / 4);
|
|
65
|
+
for (let i = 0; i < blocks; i++) {
|
|
66
|
+
let k1 = keyBytes[i * 4] | (keyBytes[i * 4 + 1] << 8) | (keyBytes[i * 4 + 2] << 16) | (keyBytes[i * 4 + 3] << 24);
|
|
67
|
+
k1 = Math.imul(k1, c1);
|
|
68
|
+
k1 = (k1 << 15) | (k1 >>> 17);
|
|
69
|
+
k1 = Math.imul(k1, c2);
|
|
70
|
+
h1 ^= k1;
|
|
71
|
+
h1 = (h1 << 13) | (h1 >>> 19);
|
|
72
|
+
h1 = Math.imul(h1, 5) + 0xe6546b64;
|
|
73
|
+
}
|
|
74
|
+
let k1 = 0;
|
|
75
|
+
const offset = blocks * 4;
|
|
76
|
+
switch (keyBytes.length % 4) {
|
|
77
|
+
case 3:
|
|
78
|
+
k1 ^= keyBytes[offset + 2] << 16;
|
|
79
|
+
/* falls through */
|
|
80
|
+
case 2:
|
|
81
|
+
k1 ^= keyBytes[offset + 1] << 8;
|
|
82
|
+
/* falls through */
|
|
83
|
+
case 1:
|
|
84
|
+
k1 ^= keyBytes[offset];
|
|
85
|
+
k1 = Math.imul(k1, c1);
|
|
86
|
+
k1 = (k1 << 15) | (k1 >>> 17);
|
|
87
|
+
k1 = Math.imul(k1, c2);
|
|
88
|
+
h1 ^= k1;
|
|
89
|
+
}
|
|
90
|
+
h1 ^= keyBytes.length;
|
|
91
|
+
h1 ^= h1 >>> 16;
|
|
92
|
+
h1 = Math.imul(h1, 0x85ebca6b);
|
|
93
|
+
h1 ^= h1 >>> 13;
|
|
94
|
+
h1 = Math.imul(h1, 0xc2b2ae35);
|
|
95
|
+
h1 ^= h1 >>> 16;
|
|
96
|
+
return h1 >>> 0;
|
|
97
|
+
}
|
|
98
|
+
exports.USER_SEED_MODULUS = 1000;
|
|
99
|
+
/** Canonical `user.seed` derivation: 0..999 bucket from a stable user id. */
|
|
100
|
+
function userSeedBucket(appUserId) {
|
|
101
|
+
if (!appUserId)
|
|
102
|
+
return 0;
|
|
103
|
+
return murmurhash3(appUserId) % exports.USER_SEED_MODULUS;
|
|
104
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface LiveActivityConfig {
|
|
2
|
+
activityType: string;
|
|
3
|
+
attributes: Record<string, any>;
|
|
4
|
+
contentState: Record<string, any>;
|
|
5
|
+
staleDate?: Date;
|
|
6
|
+
dismissalDate?: Date;
|
|
7
|
+
}
|
|
8
|
+
export interface LiveActivityUpdate {
|
|
9
|
+
contentState: Record<string, any>;
|
|
10
|
+
staleDate?: Date;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Manager for iOS Live Activities
|
|
14
|
+
* Only available on iOS 16.1+
|
|
15
|
+
*/
|
|
16
|
+
export declare class LiveActivitiesManager {
|
|
17
|
+
private static instance;
|
|
18
|
+
private constructor();
|
|
19
|
+
static getInstance(): LiveActivitiesManager;
|
|
20
|
+
/**
|
|
21
|
+
* Check if Live Activities are supported
|
|
22
|
+
*/
|
|
23
|
+
isSupported(): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Check if Live Activities are enabled by the user
|
|
26
|
+
*/
|
|
27
|
+
areActivitiesEnabled(): Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Start a new Live Activity
|
|
30
|
+
* Returns the activity ID
|
|
31
|
+
*/
|
|
32
|
+
startActivity(config: LiveActivityConfig): Promise<string>;
|
|
33
|
+
/**
|
|
34
|
+
* Update an existing Live Activity
|
|
35
|
+
*/
|
|
36
|
+
updateActivity(activityId: string, update: LiveActivityUpdate): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* End a Live Activity
|
|
39
|
+
*/
|
|
40
|
+
endActivity(activityId: string, finalState?: Record<string, any>, dismissalPolicy?: 'default' | 'immediate' | 'after'): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Get all active Live Activities
|
|
43
|
+
* Returns array of activity IDs
|
|
44
|
+
*/
|
|
45
|
+
getActiveActivities(): Promise<string[]>;
|
|
46
|
+
}
|
|
47
|
+
export declare const liveActivities: LiveActivitiesManager;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.liveActivities = exports.LiveActivitiesManager = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const { BillDogLiveActivities } = react_native_1.NativeModules;
|
|
6
|
+
/**
|
|
7
|
+
* Manager for iOS Live Activities
|
|
8
|
+
* Only available on iOS 16.1+
|
|
9
|
+
*/
|
|
10
|
+
class LiveActivitiesManager {
|
|
11
|
+
constructor() { }
|
|
12
|
+
static getInstance() {
|
|
13
|
+
if (!LiveActivitiesManager.instance) {
|
|
14
|
+
LiveActivitiesManager.instance = new LiveActivitiesManager();
|
|
15
|
+
}
|
|
16
|
+
return LiveActivitiesManager.instance;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Check if Live Activities are supported
|
|
20
|
+
*/
|
|
21
|
+
isSupported() {
|
|
22
|
+
return react_native_1.Platform.OS === 'ios' && react_native_1.Platform.Version >= '16.2' && !!BillDogLiveActivities;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Check if Live Activities are enabled by the user
|
|
26
|
+
*/
|
|
27
|
+
async areActivitiesEnabled() {
|
|
28
|
+
if (!this.isSupported()) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return await BillDogLiveActivities.areActivitiesEnabled();
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.error('[LiveActivitiesManager] Error checking enabled status:', error);
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Start a new Live Activity
|
|
41
|
+
* Returns the activity ID
|
|
42
|
+
*/
|
|
43
|
+
async startActivity(config) {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
if (!this.isSupported()) {
|
|
46
|
+
throw new Error('Live Activities are not supported on this platform');
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const activityId = await BillDogLiveActivities.startActivity(config.activityType, config.attributes, config.contentState, (_a = config.staleDate) === null || _a === void 0 ? void 0 : _a.toISOString(), (_b = config.dismissalDate) === null || _b === void 0 ? void 0 : _b.toISOString());
|
|
50
|
+
return activityId;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.error('[LiveActivitiesManager] Error starting activity:', error);
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Update an existing Live Activity
|
|
59
|
+
*/
|
|
60
|
+
async updateActivity(activityId, update) {
|
|
61
|
+
var _a;
|
|
62
|
+
if (!this.isSupported()) {
|
|
63
|
+
throw new Error('Live Activities are not supported on this platform');
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
await BillDogLiveActivities.updateActivity(activityId, update.contentState, (_a = update.staleDate) === null || _a === void 0 ? void 0 : _a.toISOString());
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error('[LiveActivitiesManager] Error updating activity:', error);
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* End a Live Activity
|
|
75
|
+
*/
|
|
76
|
+
async endActivity(activityId, finalState, dismissalPolicy = 'default') {
|
|
77
|
+
if (!this.isSupported()) {
|
|
78
|
+
throw new Error('Live Activities are not supported on this platform');
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
await BillDogLiveActivities.endActivity(activityId, finalState, dismissalPolicy);
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error('[LiveActivitiesManager] Error ending activity:', error);
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get all active Live Activities
|
|
90
|
+
* Returns array of activity IDs
|
|
91
|
+
*/
|
|
92
|
+
async getActiveActivities() {
|
|
93
|
+
if (!this.isSupported()) {
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
return await BillDogLiveActivities.getActiveActivities();
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.error('[LiveActivitiesManager] Error getting active activities:', error);
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.LiveActivitiesManager = LiveActivitiesManager;
|
|
106
|
+
exports.liveActivities = LiveActivitiesManager.getInstance();
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles scheduling and managing trial reminder notifications for React Native.
|
|
3
|
+
*
|
|
4
|
+
* All API calls route through `ApiClient` → `BillDogConfiguration.apiBaseUrl`
|
|
5
|
+
* (the single branded host, `https://api.billdog.io/v1`).
|
|
6
|
+
*/
|
|
7
|
+
export declare class NotificationScheduler {
|
|
8
|
+
private static instance;
|
|
9
|
+
private constructor();
|
|
10
|
+
static getInstance(): NotificationScheduler;
|
|
11
|
+
private configure;
|
|
12
|
+
requestPermissions(): Promise<boolean>;
|
|
13
|
+
checkPermissions(): Promise<boolean>;
|
|
14
|
+
/**
|
|
15
|
+
* Schedule a trial reminder notification.
|
|
16
|
+
*
|
|
17
|
+
* @param apiKey - @deprecated Resolved from BillDogConfiguration if omitted
|
|
18
|
+
*/
|
|
19
|
+
scheduleTrialNotification(subscription: Subscription, config: NotificationConfig, apiKey?: string): Promise<void>;
|
|
20
|
+
cancelNotification(subscriptionId: string, apiKey?: string): Promise<void>;
|
|
21
|
+
getScheduledNotifications(): Promise<any[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Update subscription notification status via ApiClient.
|
|
24
|
+
*/
|
|
25
|
+
private updateSubscriptionNotificationStatus;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Type definitions
|
|
29
|
+
*/
|
|
30
|
+
export interface NotificationConfig {
|
|
31
|
+
enabled: boolean;
|
|
32
|
+
dayOfTrial: number;
|
|
33
|
+
title: string;
|
|
34
|
+
subtitle?: string;
|
|
35
|
+
body: string;
|
|
36
|
+
requestPermissions: boolean;
|
|
37
|
+
removeNotificationEnabled?: boolean;
|
|
38
|
+
sound?: string;
|
|
39
|
+
badge?: number;
|
|
40
|
+
}
|
|
41
|
+
export interface Subscription {
|
|
42
|
+
id: string;
|
|
43
|
+
isTrial: boolean;
|
|
44
|
+
purchasedAt?: string;
|
|
45
|
+
expiresAt?: string;
|
|
46
|
+
notificationScheduledAt?: string;
|
|
47
|
+
notificationSentAt?: string;
|
|
48
|
+
notificationCancelledAt?: string;
|
|
49
|
+
}
|
|
50
|
+
export declare const requestNotificationPermissions: () => Promise<boolean>;
|
|
51
|
+
export declare const checkNotificationPermissions: () => Promise<boolean>;
|
|
52
|
+
export declare const scheduleTrialNotification: (subscription: Subscription, config: NotificationConfig, apiKey?: string) => Promise<void>;
|
|
53
|
+
export declare const cancelTrialNotification: (subscriptionId: string, apiKey?: string) => Promise<void>;
|
|
54
|
+
export declare const getScheduledNotifications: () => Promise<any[]>;
|
|
55
|
+
export { useDeviceToken, registerDeviceToken } from './useDeviceToken';
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerDeviceToken = exports.useDeviceToken = exports.getScheduledNotifications = exports.cancelTrialNotification = exports.scheduleTrialNotification = exports.checkNotificationPermissions = exports.requestNotificationPermissions = exports.NotificationScheduler = void 0;
|
|
7
|
+
const react_native_1 = require("react-native");
|
|
8
|
+
const react_native_push_notification_1 = __importDefault(require("react-native-push-notification"));
|
|
9
|
+
const push_notification_ios_1 = __importDefault(require("@react-native-community/push-notification-ios"));
|
|
10
|
+
const ApiClient_1 = require("../utils/ApiClient");
|
|
11
|
+
/**
|
|
12
|
+
* Handles scheduling and managing trial reminder notifications for React Native.
|
|
13
|
+
*
|
|
14
|
+
* All API calls route through `ApiClient` → `BillDogConfiguration.apiBaseUrl`
|
|
15
|
+
* (the single branded host, `https://api.billdog.io/v1`).
|
|
16
|
+
*/
|
|
17
|
+
class NotificationScheduler {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.configure();
|
|
20
|
+
}
|
|
21
|
+
static getInstance() {
|
|
22
|
+
if (!NotificationScheduler.instance) {
|
|
23
|
+
NotificationScheduler.instance = new NotificationScheduler();
|
|
24
|
+
}
|
|
25
|
+
return NotificationScheduler.instance;
|
|
26
|
+
}
|
|
27
|
+
configure() {
|
|
28
|
+
react_native_push_notification_1.default.configure({
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- callback shape comes from the optional, untyped react-native-push-notification peer dep
|
|
30
|
+
onNotification: (notification) => {
|
|
31
|
+
console.log('Notification received:', notification);
|
|
32
|
+
if (react_native_1.Platform.OS === 'ios') {
|
|
33
|
+
notification.finish(push_notification_ios_1.default.FetchResult.NoData);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
permissions: {
|
|
37
|
+
alert: true,
|
|
38
|
+
badge: true,
|
|
39
|
+
sound: true,
|
|
40
|
+
},
|
|
41
|
+
popInitialNotification: true,
|
|
42
|
+
requestPermissions: false,
|
|
43
|
+
});
|
|
44
|
+
if (react_native_1.Platform.OS === 'android') {
|
|
45
|
+
react_native_push_notification_1.default.createChannel({
|
|
46
|
+
channelId: 'trial-reminders',
|
|
47
|
+
channelName: 'Trial Reminders',
|
|
48
|
+
channelDescription: 'Notifications about your trial subscription',
|
|
49
|
+
importance: 4,
|
|
50
|
+
vibrate: true,
|
|
51
|
+
}, (created) => console.log(`Channel created: ${created}`));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async requestPermissions() {
|
|
55
|
+
if (react_native_1.Platform.OS === 'ios') {
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
react_native_push_notification_1.default.requestPermissions((permissions) => {
|
|
58
|
+
resolve(permissions.alert === true);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
else if (react_native_1.Platform.OS === 'android') {
|
|
63
|
+
if (react_native_1.Platform.Version >= 33) {
|
|
64
|
+
const granted = await react_native_1.PermissionsAndroid.request(react_native_1.PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
|
|
65
|
+
return granted === react_native_1.PermissionsAndroid.RESULTS.GRANTED;
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
async checkPermissions() {
|
|
72
|
+
return new Promise((resolve) => {
|
|
73
|
+
react_native_push_notification_1.default.checkPermissions((permissions) => {
|
|
74
|
+
resolve(permissions.alert === true || permissions.alert === 1);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Schedule a trial reminder notification.
|
|
80
|
+
*
|
|
81
|
+
* @param apiKey - @deprecated Resolved from BillDogConfiguration if omitted
|
|
82
|
+
*/
|
|
83
|
+
async scheduleTrialNotification(subscription, config, apiKey) {
|
|
84
|
+
if (!subscription.isTrial) {
|
|
85
|
+
console.warn('⚠️ Not a trial subscription, skipping notification');
|
|
86
|
+
throw new Error('Not a trial subscription');
|
|
87
|
+
}
|
|
88
|
+
if (!subscription.expiresAt || new Date(subscription.expiresAt) < new Date()) {
|
|
89
|
+
console.warn('⚠️ Trial already expired, skipping notification');
|
|
90
|
+
throw new Error('Trial already expired');
|
|
91
|
+
}
|
|
92
|
+
if (!subscription.purchasedAt) {
|
|
93
|
+
console.warn('⚠️ Missing trial start date, skipping notification');
|
|
94
|
+
throw new Error('Missing trial start date');
|
|
95
|
+
}
|
|
96
|
+
const purchaseDate = new Date(subscription.purchasedAt);
|
|
97
|
+
const notificationDate = new Date(purchaseDate);
|
|
98
|
+
notificationDate.setDate(notificationDate.getDate() + config.dayOfTrial);
|
|
99
|
+
if (notificationDate < new Date()) {
|
|
100
|
+
console.warn(`⚠️ Notification date is in the past (Day ${config.dayOfTrial} was ${notificationDate}), skipping`);
|
|
101
|
+
throw new Error('Notification date in the past');
|
|
102
|
+
}
|
|
103
|
+
if (notificationDate > new Date(subscription.expiresAt)) {
|
|
104
|
+
console.warn('⚠️ Notification date is after trial expiration, skipping');
|
|
105
|
+
throw new Error('Notification date after expiration');
|
|
106
|
+
}
|
|
107
|
+
if (subscription.notificationScheduledAt) {
|
|
108
|
+
console.warn(`⚠️ Notification already scheduled at ${subscription.notificationScheduledAt}`);
|
|
109
|
+
throw new Error('Notification already scheduled');
|
|
110
|
+
}
|
|
111
|
+
const hasPermission = await this.checkPermissions();
|
|
112
|
+
if (!hasPermission) {
|
|
113
|
+
if (config.requestPermissions) {
|
|
114
|
+
const granted = await this.requestPermissions();
|
|
115
|
+
if (!granted) {
|
|
116
|
+
throw new Error('Notification permission denied');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
throw new Error('Notification permission not granted');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
react_native_push_notification_1.default.localNotificationSchedule({
|
|
124
|
+
id: `trial_reminder_${subscription.id}`,
|
|
125
|
+
channelId: 'trial-reminders',
|
|
126
|
+
title: config.title,
|
|
127
|
+
message: config.body,
|
|
128
|
+
date: notificationDate,
|
|
129
|
+
allowWhileIdle: true,
|
|
130
|
+
userInfo: {
|
|
131
|
+
subscription_id: subscription.id,
|
|
132
|
+
notification_type: 'trial_reminder',
|
|
133
|
+
day_of_trial: config.dayOfTrial,
|
|
134
|
+
},
|
|
135
|
+
...(config.subtitle && react_native_1.Platform.OS === 'ios' ? { subtitle: config.subtitle } : {}),
|
|
136
|
+
...(config.sound ? { soundName: config.sound } : {}),
|
|
137
|
+
...(config.badge ? { number: config.badge } : {}),
|
|
138
|
+
});
|
|
139
|
+
// Update subscription via ApiClient
|
|
140
|
+
await this.updateSubscriptionNotificationStatus(subscription.id, { scheduledAt: new Date() }, apiKey);
|
|
141
|
+
console.log(`✅ Scheduled trial reminder notification for Day ${config.dayOfTrial} at ${notificationDate}`);
|
|
142
|
+
}
|
|
143
|
+
async cancelNotification(subscriptionId, apiKey) {
|
|
144
|
+
react_native_push_notification_1.default.cancelLocalNotification(`trial_reminder_${subscriptionId}`);
|
|
145
|
+
await this.updateSubscriptionNotificationStatus(subscriptionId, { cancelledAt: new Date() }, apiKey);
|
|
146
|
+
console.log('✅ Cancelled trial reminder notification');
|
|
147
|
+
}
|
|
148
|
+
async getScheduledNotifications() {
|
|
149
|
+
return new Promise((resolve) => {
|
|
150
|
+
react_native_push_notification_1.default.getScheduledLocalNotifications((notifications) => {
|
|
151
|
+
resolve(notifications);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Update subscription notification status via ApiClient.
|
|
157
|
+
*/
|
|
158
|
+
async updateSubscriptionNotificationStatus(subscriptionId, updates, apiKey) {
|
|
159
|
+
const body = {};
|
|
160
|
+
if (updates.scheduledAt) {
|
|
161
|
+
body.notification_scheduled_at = updates.scheduledAt.toISOString();
|
|
162
|
+
}
|
|
163
|
+
if (updates.sentAt) {
|
|
164
|
+
body.notification_sent_at = updates.sentAt.toISOString();
|
|
165
|
+
}
|
|
166
|
+
if (updates.cancelledAt) {
|
|
167
|
+
body.notification_cancelled_at = updates.cancelledAt.toISOString();
|
|
168
|
+
}
|
|
169
|
+
if (Object.keys(body).length === 0)
|
|
170
|
+
return;
|
|
171
|
+
try {
|
|
172
|
+
await ApiClient_1.ApiClient.post('update-subscription-notification', {
|
|
173
|
+
subscription_id: subscriptionId,
|
|
174
|
+
...body,
|
|
175
|
+
}, {
|
|
176
|
+
apiKey,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
console.warn('⚠️ Failed to update subscription status:', error);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
exports.NotificationScheduler = NotificationScheduler;
|
|
185
|
+
// Convenience exports
|
|
186
|
+
const requestNotificationPermissions = () => NotificationScheduler.getInstance().requestPermissions();
|
|
187
|
+
exports.requestNotificationPermissions = requestNotificationPermissions;
|
|
188
|
+
const checkNotificationPermissions = () => NotificationScheduler.getInstance().checkPermissions();
|
|
189
|
+
exports.checkNotificationPermissions = checkNotificationPermissions;
|
|
190
|
+
const scheduleTrialNotification = (subscription, config, apiKey) => NotificationScheduler.getInstance().scheduleTrialNotification(subscription, config, apiKey);
|
|
191
|
+
exports.scheduleTrialNotification = scheduleTrialNotification;
|
|
192
|
+
const cancelTrialNotification = (subscriptionId, apiKey) => NotificationScheduler.getInstance().cancelNotification(subscriptionId, apiKey);
|
|
193
|
+
exports.cancelTrialNotification = cancelTrialNotification;
|
|
194
|
+
const getScheduledNotifications = () => NotificationScheduler.getInstance().getScheduledNotifications();
|
|
195
|
+
exports.getScheduledNotifications = getScheduledNotifications;
|
|
196
|
+
// Re-export device token registration
|
|
197
|
+
var useDeviceToken_1 = require("./useDeviceToken");
|
|
198
|
+
Object.defineProperty(exports, "useDeviceToken", { enumerable: true, get: function () { return useDeviceToken_1.useDeviceToken; } });
|
|
199
|
+
Object.defineProperty(exports, "registerDeviceToken", { enumerable: true, get: function () { return useDeviceToken_1.registerDeviceToken; } });
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface PurchaseNotificationConfig {
|
|
2
|
+
/** @deprecated Use BillDogConfiguration.configure({ apiKey }) instead */
|
|
3
|
+
apiKey?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface PurchaseDetails {
|
|
6
|
+
subscriptionId: string;
|
|
7
|
+
userId: string;
|
|
8
|
+
projectId: string;
|
|
9
|
+
productId: string;
|
|
10
|
+
platform: 'ios' | 'android';
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Handles notification cancellation when purchases are completed.
|
|
14
|
+
*
|
|
15
|
+
* Resolves API endpoint from BillDogConfiguration by default.
|
|
16
|
+
*/
|
|
17
|
+
export declare class PurchaseNotificationHandler {
|
|
18
|
+
/** @deprecated */
|
|
19
|
+
private apiKey?;
|
|
20
|
+
constructor(config?: PurchaseNotificationConfig);
|
|
21
|
+
handlePurchaseCompleted(details: PurchaseDetails): Promise<boolean>;
|
|
22
|
+
private cancelLocalNotification;
|
|
23
|
+
private cancelRemoteNotification;
|
|
24
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PurchaseNotificationHandler = void 0;
|
|
7
|
+
const react_native_push_notification_1 = __importDefault(require("react-native-push-notification"));
|
|
8
|
+
const ApiClient_1 = require("../utils/ApiClient");
|
|
9
|
+
/**
|
|
10
|
+
* Handles notification cancellation when purchases are completed.
|
|
11
|
+
*
|
|
12
|
+
* Resolves API endpoint from BillDogConfiguration by default.
|
|
13
|
+
*/
|
|
14
|
+
class PurchaseNotificationHandler {
|
|
15
|
+
constructor(config = {}) {
|
|
16
|
+
this.apiKey = config.apiKey;
|
|
17
|
+
}
|
|
18
|
+
async handlePurchaseCompleted(details) {
|
|
19
|
+
try {
|
|
20
|
+
this.cancelLocalNotification(details.subscriptionId);
|
|
21
|
+
await this.cancelRemoteNotification(details);
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
console.error('[PurchaseNotificationHandler] Error handling purchase:', error);
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
cancelLocalNotification(subscriptionId) {
|
|
30
|
+
const notificationId = `trial-reminder-${subscriptionId}`;
|
|
31
|
+
react_native_push_notification_1.default.cancelLocalNotification(notificationId);
|
|
32
|
+
react_native_push_notification_1.default.cancelAllLocalNotifications();
|
|
33
|
+
console.log('[PurchaseNotificationHandler] Cancelled local notification:', notificationId);
|
|
34
|
+
}
|
|
35
|
+
async cancelRemoteNotification(details) {
|
|
36
|
+
try {
|
|
37
|
+
const result = await ApiClient_1.ApiClient.post('handle-purchase-notification', {
|
|
38
|
+
subscriptionId: details.subscriptionId,
|
|
39
|
+
userId: details.userId,
|
|
40
|
+
projectId: details.projectId,
|
|
41
|
+
productId: details.productId,
|
|
42
|
+
platform: details.platform,
|
|
43
|
+
purchaseDate: new Date().toISOString(),
|
|
44
|
+
}, {
|
|
45
|
+
apiKey: this.apiKey,
|
|
46
|
+
});
|
|
47
|
+
console.log('[PurchaseNotificationHandler] Successfully updated backend:', result);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error('[PurchaseNotificationHandler] Error updating backend:', error);
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.PurchaseNotificationHandler = PurchaseNotificationHandler;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
interface UseDeviceTokenOptions {
|
|
2
|
+
userId: string;
|
|
3
|
+
projectId: string;
|
|
4
|
+
/** @deprecated Use BillDogConfiguration.configure({ apiKey }) instead */
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
onTokenRegistered?: (token: string) => void;
|
|
7
|
+
onError?: (error: Error) => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Hook to register device token for push notifications.
|
|
11
|
+
* Automatically registers the device token when the component mounts.
|
|
12
|
+
*
|
|
13
|
+
* Credentials are resolved from `BillDogConfiguration` by default.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* import { useDeviceToken } from '@billdog.io/react-native';
|
|
18
|
+
*
|
|
19
|
+
* function App() {
|
|
20
|
+
* useDeviceToken({
|
|
21
|
+
* userId: 'user-123',
|
|
22
|
+
* projectId: 'project-456',
|
|
23
|
+
* onTokenRegistered: (token) => console.log('Token registered:', token),
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* return <YourApp />;
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function useDeviceToken({ userId, projectId, apiKey: apiKeyOverride, onTokenRegistered, onError, }: UseDeviceTokenOptions): void;
|
|
31
|
+
/**
|
|
32
|
+
* Manually register a device token.
|
|
33
|
+
* Resolves the endpoint from BillDogConfiguration (api.billdog.io/v1).
|
|
34
|
+
*/
|
|
35
|
+
export declare function registerDeviceToken(token: string, userId: string, projectId: string, apiKey?: string, platform?: 'ios' | 'android'): Promise<void>;
|
|
36
|
+
export {};
|