@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.
Files changed (309) hide show
  1. package/BillDogReactNative.podspec +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +330 -0
  4. package/android/build.gradle +99 -0
  5. package/android/src/main/AndroidManifest.xml +1 -0
  6. package/android/src/main/kotlin/io/billdog/reactnative/BillDogABTestModule.kt +317 -0
  7. package/android/src/main/kotlin/io/billdog/reactnative/BillDogAnalyticsModule.kt +389 -0
  8. package/android/src/main/kotlin/io/billdog/reactnative/BillDogModule.kt +817 -0
  9. package/android/src/main/kotlin/io/billdog/reactnative/BillDogPaywallViewManager.kt +383 -0
  10. package/android/src/main/kotlin/io/billdog/reactnative/BillDogSurveyModule.kt +427 -0
  11. package/android/src/main/kotlin/io/billdog/reactnative/BillDogVirtualCurrencyModule.kt +407 -0
  12. package/android/src/main/kotlin/io/billdog/virtualcurrency/BillDogVirtualCurrencyPackage.kt +44 -0
  13. package/dist/AdvancedPaywallCache.d.ts +70 -0
  14. package/dist/AdvancedPaywallCache.js +344 -0
  15. package/dist/BillDog.d.ts +255 -0
  16. package/dist/BillDog.js +918 -0
  17. package/dist/BillDogConfiguration.d.ts +145 -0
  18. package/dist/BillDogConfiguration.js +229 -0
  19. package/dist/ComponentRenderer.d.ts +17 -0
  20. package/dist/ComponentRenderer.js +886 -0
  21. package/dist/LayoutEngine.d.ts +101 -0
  22. package/dist/LayoutEngine.js +394 -0
  23. package/dist/LocalizationResolver.d.ts +99 -0
  24. package/dist/LocalizationResolver.js +266 -0
  25. package/dist/NativePaywallView.d.ts +36 -0
  26. package/dist/NativePaywallView.js +59 -0
  27. package/dist/PaywallCache.d.ts +74 -0
  28. package/dist/PaywallCache.js +293 -0
  29. package/dist/PaywallStateManager.d.ts +62 -0
  30. package/dist/PaywallStateManager.js +147 -0
  31. package/dist/PaywallView.d.ts +42 -0
  32. package/dist/PaywallView.js +275 -0
  33. package/dist/ProductVariableProvider.d.ts +60 -0
  34. package/dist/ProductVariableProvider.js +239 -0
  35. package/dist/VariableResolver.d.ts +120 -0
  36. package/dist/VariableResolver.js +379 -0
  37. package/dist/WebViewPaywall.d.ts +75 -0
  38. package/dist/WebViewPaywall.js +360 -0
  39. package/dist/animations/presets.d.ts +49 -0
  40. package/dist/animations/presets.js +367 -0
  41. package/dist/components/AccoladeCpsComponent.d.ts +13 -0
  42. package/dist/components/AccoladeCpsComponent.js +248 -0
  43. package/dist/components/AccordionComponent.d.ts +10 -0
  44. package/dist/components/AccordionComponent.js +187 -0
  45. package/dist/components/AnimatedWrapper.d.ts +35 -0
  46. package/dist/components/AnimatedWrapper.js +277 -0
  47. package/dist/components/CarouselComponent.d.ts +23 -0
  48. package/dist/components/CarouselComponent.js +484 -0
  49. package/dist/components/ChartCurveComponent.d.ts +13 -0
  50. package/dist/components/ChartCurveComponent.js +333 -0
  51. package/dist/components/CheckboxComponent.d.ts +9 -0
  52. package/dist/components/CheckboxComponent.js +172 -0
  53. package/dist/components/ConfettiComponent.d.ts +9 -0
  54. package/dist/components/ConfettiComponent.js +172 -0
  55. package/dist/components/CountdownComponent.d.ts +16 -0
  56. package/dist/components/CountdownComponent.js +414 -0
  57. package/dist/components/DelayedXComponent.d.ts +12 -0
  58. package/dist/components/DelayedXComponent.js +240 -0
  59. package/dist/components/DrawerModalComponent.d.ts +20 -0
  60. package/dist/components/DrawerModalComponent.js +286 -0
  61. package/dist/components/GradientView.d.ts +38 -0
  62. package/dist/components/GradientView.js +126 -0
  63. package/dist/components/HapticFeedbackComponent.d.ts +16 -0
  64. package/dist/components/HapticFeedbackComponent.js +64 -0
  65. package/dist/components/HorizontalProductsComponent.d.ts +17 -0
  66. package/dist/components/HorizontalProductsComponent.js +284 -0
  67. package/dist/components/MultiChoiceGridComponent.d.ts +13 -0
  68. package/dist/components/MultiChoiceGridComponent.js +234 -0
  69. package/dist/components/NPSScaleComponent.d.ts +16 -0
  70. package/dist/components/NPSScaleComponent.js +260 -0
  71. package/dist/components/NavigationComponent.d.ts +26 -0
  72. package/dist/components/NavigationComponent.js +302 -0
  73. package/dist/components/OAuthButtonComponent.d.ts +20 -0
  74. package/dist/components/OAuthButtonComponent.js +237 -0
  75. package/dist/components/ProgressLoaderComponent.d.ts +13 -0
  76. package/dist/components/ProgressLoaderComponent.js +308 -0
  77. package/dist/components/ProgressStepperComponent.d.ts +18 -0
  78. package/dist/components/ProgressStepperComponent.js +228 -0
  79. package/dist/components/SegmentedPickerComponent.d.ts +10 -0
  80. package/dist/components/SegmentedPickerComponent.js +221 -0
  81. package/dist/components/ShareButtonsComponent.d.ts +21 -0
  82. package/dist/components/ShareButtonsComponent.js +265 -0
  83. package/dist/components/ShareCodeComponent.d.ts +16 -0
  84. package/dist/components/ShareCodeComponent.js +274 -0
  85. package/dist/components/SingleChoiceGridComponent.d.ts +13 -0
  86. package/dist/components/SingleChoiceGridComponent.js +210 -0
  87. package/dist/components/SliderComponent.d.ts +9 -0
  88. package/dist/components/SliderComponent.js +263 -0
  89. package/dist/components/StarRatingInputComponent.d.ts +20 -0
  90. package/dist/components/StarRatingInputComponent.js +198 -0
  91. package/dist/components/StickerCompositeComponent.d.ts +13 -0
  92. package/dist/components/StickerCompositeComponent.js +136 -0
  93. package/dist/components/TabsComponent.d.ts +19 -0
  94. package/dist/components/TabsComponent.js +431 -0
  95. package/dist/components/TextInputComponent.d.ts +18 -0
  96. package/dist/components/TextInputComponent.js +227 -0
  97. package/dist/components/TimelineComponent.d.ts +19 -0
  98. package/dist/components/TimelineComponent.js +104 -0
  99. package/dist/components/ToggleComponent.d.ts +14 -0
  100. package/dist/components/ToggleComponent.js +132 -0
  101. package/dist/components/VerticalProductsComponent.d.ts +17 -0
  102. package/dist/components/VerticalProductsComponent.js +311 -0
  103. package/dist/dynamicValues.d.ts +36 -0
  104. package/dist/dynamicValues.js +142 -0
  105. package/dist/filters/dateFilters.d.ts +50 -0
  106. package/dist/filters/dateFilters.js +390 -0
  107. package/dist/filters/index.d.ts +18 -0
  108. package/dist/filters/index.js +253 -0
  109. package/dist/hooks/useOfferings.d.ts +76 -0
  110. package/dist/hooks/useOfferings.js +99 -0
  111. package/dist/hooks/usePaywall.d.ts +27 -0
  112. package/dist/hooks/usePaywall.js +114 -0
  113. package/dist/hooks/usePlacement.d.ts +34 -0
  114. package/dist/hooks/usePlacement.js +89 -0
  115. package/dist/hooks/useSubscription.d.ts +40 -0
  116. package/dist/hooks/useSubscription.js +97 -0
  117. package/dist/index.d.ts +98 -0
  118. package/dist/index.js +198 -0
  119. package/dist/models/BillDogError.d.ts +40 -0
  120. package/dist/models/BillDogError.js +11 -0
  121. package/dist/models/CacheFetchPolicy.d.ts +8 -0
  122. package/dist/models/CacheFetchPolicy.js +4 -0
  123. package/dist/models/CustomProduct.d.ts +32 -0
  124. package/dist/models/CustomProduct.js +15 -0
  125. package/dist/models/CustomerInfo.d.ts +17 -0
  126. package/dist/models/CustomerInfo.js +11 -0
  127. package/dist/models/Delegate.d.ts +20 -0
  128. package/dist/models/Delegate.js +11 -0
  129. package/dist/models/EntitlementInfo.d.ts +19 -0
  130. package/dist/models/EntitlementInfo.js +2 -0
  131. package/dist/models/Placement.d.ts +54 -0
  132. package/dist/models/Placement.js +15 -0
  133. package/dist/models/PurchaseParams.d.ts +39 -0
  134. package/dist/models/PurchaseParams.js +60 -0
  135. package/dist/models/PurchaseResult.d.ts +30 -0
  136. package/dist/models/PurchaseResult.js +15 -0
  137. package/dist/models/RestoreResult.d.ts +30 -0
  138. package/dist/models/RestoreResult.js +22 -0
  139. package/dist/models/RestoredItem.d.ts +26 -0
  140. package/dist/models/RestoredItem.js +13 -0
  141. package/dist/modules/ABTest.d.ts +65 -0
  142. package/dist/modules/ABTest.js +113 -0
  143. package/dist/modules/Analytics.d.ts +91 -0
  144. package/dist/modules/Analytics.js +182 -0
  145. package/dist/modules/Survey.d.ts +65 -0
  146. package/dist/modules/Survey.js +82 -0
  147. package/dist/modules/VirtualCurrency.d.ts +63 -0
  148. package/dist/modules/VirtualCurrency.js +147 -0
  149. package/dist/murmur.d.ts +23 -0
  150. package/dist/murmur.js +104 -0
  151. package/dist/notifications/LiveActivitiesManager.d.ts +47 -0
  152. package/dist/notifications/LiveActivitiesManager.js +106 -0
  153. package/dist/notifications/NotificationScheduler.d.ts +55 -0
  154. package/dist/notifications/NotificationScheduler.js +199 -0
  155. package/dist/notifications/PurchaseNotificationHandler.d.ts +24 -0
  156. package/dist/notifications/PurchaseNotificationHandler.js +55 -0
  157. package/dist/notifications/useDeviceToken.d.ts +36 -0
  158. package/dist/notifications/useDeviceToken.js +97 -0
  159. package/dist/notifications/useLiveActivity.d.ts +39 -0
  160. package/dist/notifications/useLiveActivity.js +104 -0
  161. package/dist/review/ReviewAnalytics.d.ts +34 -0
  162. package/dist/review/ReviewAnalytics.js +73 -0
  163. package/dist/review/ReviewManager.d.ts +83 -0
  164. package/dist/review/ReviewManager.js +339 -0
  165. package/dist/review/ReviewTimingManager.d.ts +82 -0
  166. package/dist/review/ReviewTimingManager.js +224 -0
  167. package/dist/survey-core/types.d.ts +215 -0
  168. package/dist/survey-core/types.js +8 -0
  169. package/dist/types.d.ts +438 -0
  170. package/dist/types.js +158 -0
  171. package/dist/utils/ApiClient.d.ts +65 -0
  172. package/dist/utils/ApiClient.js +132 -0
  173. package/dist/utils/CSSConverter.d.ts +49 -0
  174. package/dist/utils/CSSConverter.js +470 -0
  175. package/dist/utils/animations.d.ts +41 -0
  176. package/dist/utils/animations.js +194 -0
  177. package/dist/utils/calendarIntegration.d.ts +36 -0
  178. package/dist/utils/calendarIntegration.js +89 -0
  179. package/dist/utils/configurationResolver.d.ts +23 -0
  180. package/dist/utils/configurationResolver.js +78 -0
  181. package/dist/utils/deviceDetection.d.ts +38 -0
  182. package/dist/utils/deviceDetection.js +59 -0
  183. package/dist/utils/hapticFeedback.d.ts +17 -0
  184. package/dist/utils/hapticFeedback.js +53 -0
  185. package/dist/utils/iconMapper.d.ts +26 -0
  186. package/dist/utils/iconMapper.js +113 -0
  187. package/dist/utils/notificationPermissions.d.ts +13 -0
  188. package/dist/utils/notificationPermissions.js +51 -0
  189. package/dist/utils/priceFormatting.d.ts +19 -0
  190. package/dist/utils/priceFormatting.js +99 -0
  191. package/dist/utils/shareSheet.d.ts +17 -0
  192. package/dist/utils/shareSheet.js +42 -0
  193. package/dist/utils/subscriptionUpgrade.d.ts +84 -0
  194. package/dist/utils/subscriptionUpgrade.js +100 -0
  195. package/dist/valueUtils.d.ts +48 -0
  196. package/dist/valueUtils.js +129 -0
  197. package/dist/xFlowTags.d.ts +18 -0
  198. package/dist/xFlowTags.js +385 -0
  199. package/ios/BillDogABTest.m +50 -0
  200. package/ios/BillDogABTest.swift +188 -0
  201. package/ios/BillDogAnalytics.m +105 -0
  202. package/ios/BillDogAnalytics.swift +324 -0
  203. package/ios/BillDogBridge.m +222 -0
  204. package/ios/BillDogBridge.swift +715 -0
  205. package/ios/BillDogLiveActivities.m +41 -0
  206. package/ios/BillDogLiveActivities.swift +104 -0
  207. package/ios/BillDogPaywallViewManager.m +39 -0
  208. package/ios/BillDogPaywallViewManager.swift +361 -0
  209. package/ios/BillDogSurvey.m +34 -0
  210. package/ios/BillDogSurvey.swift +257 -0
  211. package/ios/BillDogVirtualCurrencyBridge.m +63 -0
  212. package/ios/BillDogVirtualCurrencyBridge.swift +511 -0
  213. package/junit.xml +25 -0
  214. package/package.json +61 -0
  215. package/react-native.config.js +13 -0
  216. package/src/AdvancedPaywallCache.ts +433 -0
  217. package/src/BillDog.ts +983 -0
  218. package/src/BillDogConfiguration.ts +318 -0
  219. package/src/ComponentRenderer.tsx +1325 -0
  220. package/src/LayoutEngine.ts +459 -0
  221. package/src/LocalizationResolver.ts +311 -0
  222. package/src/NativePaywallView.tsx +132 -0
  223. package/src/PaywallCache.ts +358 -0
  224. package/src/PaywallStateManager.ts +154 -0
  225. package/src/PaywallView.tsx +328 -0
  226. package/src/ProductVariableProvider.ts +282 -0
  227. package/src/VariableResolver.ts +516 -0
  228. package/src/WebViewPaywall.tsx +454 -0
  229. package/src/animations/presets.ts +421 -0
  230. package/src/components/AccoladeCpsComponent.tsx +259 -0
  231. package/src/components/AccordionComponent.tsx +213 -0
  232. package/src/components/AnimatedWrapper.tsx +316 -0
  233. package/src/components/CarouselComponent.tsx +615 -0
  234. package/src/components/ChartCurveComponent.tsx +452 -0
  235. package/src/components/CheckboxComponent.tsx +185 -0
  236. package/src/components/ConfettiComponent.tsx +178 -0
  237. package/src/components/CountdownComponent.tsx +454 -0
  238. package/src/components/DelayedXComponent.tsx +266 -0
  239. package/src/components/DrawerModalComponent.tsx +324 -0
  240. package/src/components/GradientView.tsx +129 -0
  241. package/src/components/HapticFeedbackComponent.tsx +39 -0
  242. package/src/components/HorizontalProductsComponent.tsx +329 -0
  243. package/src/components/MultiChoiceGridComponent.tsx +265 -0
  244. package/src/components/NPSScaleComponent.tsx +294 -0
  245. package/src/components/NavigationComponent.tsx +329 -0
  246. package/src/components/OAuthButtonComponent.tsx +266 -0
  247. package/src/components/ProgressLoaderComponent.tsx +366 -0
  248. package/src/components/ProgressStepperComponent.tsx +250 -0
  249. package/src/components/SegmentedPickerComponent.tsx +245 -0
  250. package/src/components/ShareButtonsComponent.tsx +299 -0
  251. package/src/components/ShareCodeComponent.tsx +303 -0
  252. package/src/components/SingleChoiceGridComponent.tsx +229 -0
  253. package/src/components/SliderComponent.tsx +280 -0
  254. package/src/components/StarRatingInputComponent.tsx +223 -0
  255. package/src/components/StickerCompositeComponent.tsx +168 -0
  256. package/src/components/TabsComponent.tsx +496 -0
  257. package/src/components/TextInputComponent.tsx +258 -0
  258. package/src/components/TimelineComponent.tsx +129 -0
  259. package/src/components/ToggleComponent.tsx +142 -0
  260. package/src/components/VerticalProductsComponent.tsx +357 -0
  261. package/src/dynamicValues.ts +180 -0
  262. package/src/filters/dateFilters.ts +411 -0
  263. package/src/filters/index.ts +281 -0
  264. package/src/hooks/useOfferings.ts +192 -0
  265. package/src/hooks/usePaywall.ts +154 -0
  266. package/src/hooks/usePlacement.ts +143 -0
  267. package/src/hooks/useSubscription.ts +154 -0
  268. package/src/index.ts +245 -0
  269. package/src/models/BillDogError.ts +24 -0
  270. package/src/models/CacheFetchPolicy.ts +13 -0
  271. package/src/models/CustomProduct.ts +33 -0
  272. package/src/models/CustomerInfo.ts +26 -0
  273. package/src/models/Delegate.ts +22 -0
  274. package/src/models/EntitlementInfo.ts +27 -0
  275. package/src/models/Placement.ts +50 -0
  276. package/src/models/PurchaseParams.ts +81 -0
  277. package/src/models/PurchaseResult.ts +32 -0
  278. package/src/models/RestoreResult.ts +27 -0
  279. package/src/models/RestoredItem.ts +25 -0
  280. package/src/modules/ABTest.ts +131 -0
  281. package/src/modules/Analytics.ts +227 -0
  282. package/src/modules/Survey.ts +126 -0
  283. package/src/modules/VirtualCurrency.ts +223 -0
  284. package/src/murmur.ts +102 -0
  285. package/src/notifications/LiveActivitiesManager.ts +140 -0
  286. package/src/notifications/NotificationScheduler.ts +292 -0
  287. package/src/notifications/PurchaseNotificationHandler.ts +67 -0
  288. package/src/notifications/useDeviceToken.ts +116 -0
  289. package/src/notifications/useLiveActivity.ts +125 -0
  290. package/src/review/ReviewAnalytics.ts +89 -0
  291. package/src/review/ReviewManager.ts +355 -0
  292. package/src/review/ReviewTimingManager.ts +265 -0
  293. package/src/survey-core/types.ts +244 -0
  294. package/src/types/ambient.d.ts +9 -0
  295. package/src/types.ts +680 -0
  296. package/src/utils/ApiClient.ts +163 -0
  297. package/src/utils/CSSConverter.ts +552 -0
  298. package/src/utils/animations.ts +232 -0
  299. package/src/utils/calendarIntegration.ts +113 -0
  300. package/src/utils/configurationResolver.ts +106 -0
  301. package/src/utils/deviceDetection.ts +83 -0
  302. package/src/utils/hapticFeedback.ts +55 -0
  303. package/src/utils/iconMapper.ts +102 -0
  304. package/src/utils/notificationPermissions.ts +48 -0
  305. package/src/utils/priceFormatting.ts +119 -0
  306. package/src/utils/shareSheet.ts +55 -0
  307. package/src/utils/subscriptionUpgrade.ts +183 -0
  308. package/src/valueUtils.ts +108 -0
  309. package/src/xFlowTags.ts +463 -0
@@ -0,0 +1,41 @@
1
+ //
2
+ // BillDogLiveActivities.m
3
+ // @billdog.io/react-native
4
+ //
5
+ // RCT_EXTERN bridge declarations for the BillDogLiveActivities Swift module.
6
+ // iOS-only, no events. ⚠️ Requires `pod install` + Xcode (iOS 16.2+) to
7
+ // compile/verify — no iOS toolchain in the authoring environment.
8
+ //
9
+
10
+ #import <React/RCTBridgeModule.h>
11
+ #import <React/RCTEventEmitter.h>
12
+
13
+ @interface RCT_EXTERN_MODULE(BillDogLiveActivities, RCTEventEmitter)
14
+
15
+ RCT_EXTERN_METHOD(areActivitiesEnabled:(RCTPromiseResolveBlock)resolve
16
+ rejecter:(RCTPromiseRejectBlock)reject)
17
+
18
+ RCT_EXTERN_METHOD(startActivity:(NSString *)activityType
19
+ attributes:(NSDictionary *)attributes
20
+ contentState:(NSDictionary *)contentState
21
+ staleDate:(NSString *)staleDate
22
+ dismissalDate:(NSString *)dismissalDate
23
+ resolver:(RCTPromiseResolveBlock)resolve
24
+ rejecter:(RCTPromiseRejectBlock)reject)
25
+
26
+ RCT_EXTERN_METHOD(updateActivity:(NSString *)activityId
27
+ contentState:(NSDictionary *)contentState
28
+ staleDate:(NSString *)staleDate
29
+ resolver:(RCTPromiseResolveBlock)resolve
30
+ rejecter:(RCTPromiseRejectBlock)reject)
31
+
32
+ RCT_EXTERN_METHOD(endActivity:(NSString *)activityId
33
+ finalState:(NSDictionary *)finalState
34
+ dismissalPolicy:(NSString *)dismissalPolicy
35
+ resolver:(RCTPromiseResolveBlock)resolve
36
+ rejecter:(RCTPromiseRejectBlock)reject)
37
+
38
+ RCT_EXTERN_METHOD(getActiveActivities:(RCTPromiseResolveBlock)resolve
39
+ rejecter:(RCTPromiseRejectBlock)reject)
40
+
41
+ @end
@@ -0,0 +1,104 @@
1
+ //
2
+ // BillDogLiveActivities.swift
3
+ // @billdog.io/react-native
4
+ //
5
+ // React Native bridge → iOS Live Activities (ActivityKit). iOS-only, no events.
6
+ //
7
+ // ⚠️ VERIFICATION: there is no iOS/CocoaPods toolchain in the authoring
8
+ // environment. This file REQUIRES a `pod install` + Xcode build (with an
9
+ // ActivityKit-capable deployment target, iOS 16.2+) to compile/verify.
10
+ //
11
+ // DESIGN LIMITATION (documented, intentional no-ops):
12
+ // The native `LiveActivityManager` (LiveActivityManager.swift:25) exposes
13
+ // start/update/end/getActiveActivities as GENERICS over a concrete
14
+ // `ActivityAttributes` type — e.g. startActivity<Attributes: ActivityAttributes>
15
+ // (LiveActivityManager.swift:53). A React Native bridge only ever receives
16
+ // untyped JS dictionaries, so there is NO concrete ActivityAttributes /
17
+ // ContentState struct to instantiate at this layer. Those four methods are
18
+ // therefore best-effort NO-OPS (NSLog + resolve null/[]), and MUST be driven
19
+ // from a host-app native module that owns the concrete Attributes types.
20
+ // `areActivitiesEnabled` IS wired for real via ActivityKit's
21
+ // ActivityAuthorizationInfo (the same check at LiveActivityManager.swift:60).
22
+ //
23
+
24
+ import Foundation
25
+ import React
26
+
27
+ #if canImport(ActivityKit)
28
+ import ActivityKit
29
+ #endif
30
+
31
+ @objc(BillDogLiveActivities)
32
+ class BillDogLiveActivities: RCTEventEmitter {
33
+
34
+ override static func requiresMainQueueSetup() -> Bool {
35
+ return false
36
+ }
37
+
38
+ // No events for this module.
39
+ override func supportedEvents() -> [String]! {
40
+ return []
41
+ }
42
+
43
+ // MARK: - Authorization
44
+
45
+ @objc
46
+ func areActivitiesEnabled(_ resolve: @escaping RCTPromiseResolveBlock,
47
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
48
+ #if canImport(ActivityKit)
49
+ if #available(iOS 16.2, *) {
50
+ // Mirrors LiveActivityManager.swift:60 — real authorization state.
51
+ resolve(ActivityAuthorizationInfo().areActivitiesEnabled)
52
+ return
53
+ }
54
+ #endif
55
+ resolve(false)
56
+ }
57
+
58
+ // MARK: - Lifecycle (documented no-ops — see file header)
59
+
60
+ @objc
61
+ func startActivity(_ activityType: String,
62
+ attributes: NSDictionary,
63
+ contentState: NSDictionary,
64
+ staleDate: String?,
65
+ dismissalDate: String?,
66
+ resolver resolve: @escaping RCTPromiseResolveBlock,
67
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
68
+ NSLog("[BillDogLiveActivities] startActivity is a no-op in the RN bridge: "
69
+ + "the native LiveActivityManager requires a concrete ActivityAttributes "
70
+ + "type that cannot be built from an untyped JS payload. Drive Live "
71
+ + "Activities from a host-app native module. (activityType=\(activityType))")
72
+ resolve(nil)
73
+ }
74
+
75
+ @objc
76
+ func updateActivity(_ activityId: String,
77
+ contentState: NSDictionary,
78
+ staleDate: String?,
79
+ resolver resolve: @escaping RCTPromiseResolveBlock,
80
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
81
+ NSLog("[BillDogLiveActivities] updateActivity is a no-op in the RN bridge "
82
+ + "(generic ActivityAttributes unavailable). activityId=\(activityId)")
83
+ resolve(nil)
84
+ }
85
+
86
+ @objc
87
+ func endActivity(_ activityId: String,
88
+ finalState: NSDictionary?,
89
+ dismissalPolicy: String,
90
+ resolver resolve: @escaping RCTPromiseResolveBlock,
91
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
92
+ NSLog("[BillDogLiveActivities] endActivity is a no-op in the RN bridge "
93
+ + "(generic ActivityAttributes unavailable). activityId=\(activityId)")
94
+ resolve(nil)
95
+ }
96
+
97
+ @objc
98
+ func getActiveActivities(_ resolve: @escaping RCTPromiseResolveBlock,
99
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
100
+ NSLog("[BillDogLiveActivities] getActiveActivities is a no-op in the RN "
101
+ + "bridge (generic ActivityAttributes unavailable). Returning [].")
102
+ resolve([])
103
+ }
104
+ }
@@ -0,0 +1,39 @@
1
+ //
2
+ // BillDogPaywallViewManager.m
3
+ // @billdog.io/react-native
4
+ //
5
+ // RCT_EXTERN bridge declarations for the BillDogPaywallViewManager Swift view
6
+ // manager. Exposes the inline (embedded) native paywall to React Native's
7
+ // legacy (Paper) architecture as `BDPaywallView` — JS resolves it via
8
+ // `requireNativeComponent('BDPaywallView')`.
9
+ //
10
+ // ⚠️ Requires `pod install` + Xcode to compile/verify — no iOS toolchain in
11
+ // the authoring environment. Written to be compile-ready and internally
12
+ // consistent, but MUST be built against the example app before shipping.
13
+ //
14
+
15
+ #import <React/RCTViewManager.h>
16
+ #import <React/RCTComponent.h>
17
+
18
+ // Remap the JS module name so RN's view-name derivation (strip trailing
19
+ // "Manager") yields exactly `BDPaywallView` — the name JS resolves via
20
+ // `requireNativeComponent('BDPaywallView')` — while the Swift class stays
21
+ // `BillDogPaywallViewManager` (see @objc(BillDogPaywallViewManager)).
22
+ // A plain RCT_EXTERN_MODULE(BillDogPaywallViewManager, …) would instead export
23
+ // the component as `BillDogPaywallView`, which JS does NOT look up.
24
+ @interface RCT_EXTERN_REMAP_MODULE(BDPaywallViewManager, BillDogPaywallViewManager, RCTViewManager)
25
+
26
+ // The placement / paywall identifier to load. Setting a non-empty value loads
27
+ // and embeds the paywall (see BillDogPaywallView.paywallIdentifier didSet).
28
+ RCT_EXPORT_VIEW_PROPERTY(paywallIdentifier, NSString)
29
+
30
+ // native → JS event callbacks (RCTBubblingEventBlock).
31
+ RCT_EXPORT_VIEW_PROPERTY(onLoaded, RCTBubblingEventBlock)
32
+ RCT_EXPORT_VIEW_PROPERTY(onError, RCTBubblingEventBlock)
33
+ RCT_EXPORT_VIEW_PROPERTY(onPurchase, RCTBubblingEventBlock)
34
+ RCT_EXPORT_VIEW_PROPERTY(onDismiss, RCTBubblingEventBlock)
35
+ RCT_EXPORT_VIEW_PROPERTY(onRestore, RCTBubblingEventBlock)
36
+ RCT_EXPORT_VIEW_PROPERTY(onOpenUrl, RCTBubblingEventBlock)
37
+ RCT_EXPORT_VIEW_PROPERTY(onTrackEvent, RCTBubblingEventBlock)
38
+
39
+ @end
@@ -0,0 +1,361 @@
1
+ //
2
+ // BillDogPaywallViewManager.swift
3
+ // @billdog.io/react-native
4
+ //
5
+ // Inline (embedded) native paywall UIView for React Native's legacy (Paper /
6
+ // NON-Fabric) architecture. Exposed to JS as `BDPaywallView` via the paired
7
+ // RCT_EXTERN_MODULE in BillDogPaywallViewManager.m; JS resolves it with
8
+ // `requireNativeComponent('BDPaywallView')`.
9
+ //
10
+ // NOTE: This file has NOT been compiled in this environment (no iOS toolchain /
11
+ // CocoaPods here). It is written to be compile-ready and internally consistent,
12
+ // but MUST be verified with `pod install` + an Xcode build of the example app
13
+ // before shipping.
14
+ //
15
+ // `import BillDog` exposes every public SDK symbol (CocoaPods compiles all
16
+ // BillDog subspecs into a single Clang module named `BillDog`).
17
+ //
18
+ // CRITICAL — purchase routing (ported from the Flutter PlatformView,
19
+ // packages/flutter/ios/Classes/BillDogPaywallViewFactory.swift):
20
+ // A raw `getPaywall(...)` VC does NOT auto-route taps into the SDK (unlike the
21
+ // auto-present path, which installs `InternalPaywallDelegate`). So this view
22
+ // sets itself as the VC delegate and MIRRORS `InternalPaywallDelegate` —
23
+ // executing `BillDog.shared.purchase(...)` / `restore()` on `.purchase` /
24
+ // `.restore`, and forwarding results back to JS as bubbling events.
25
+ // Reference: BillDogPaywall/UI/InternalPaywallDelegate.swift:15 (class),
26
+ // :24 (didReceiveAction routing).
27
+ //
28
+
29
+ import UIKit
30
+ import React
31
+ import BillDogFull
32
+
33
+ // MARK: - View Manager
34
+
35
+ @objc(BillDogPaywallViewManager)
36
+ class BillDogPaywallViewManager: RCTViewManager {
37
+
38
+ override func view() -> UIView! {
39
+ return BillDogPaywallView()
40
+ }
41
+
42
+ override static func requiresMainQueueSetup() -> Bool {
43
+ return true
44
+ }
45
+ }
46
+
47
+ // MARK: - View
48
+
49
+ // Conforms to `PaywallViewControllerDelegate`
50
+ // (protocol: BillDogPaywall/UI/PaywallViewController.swift:1182).
51
+ class BillDogPaywallView: UIView, PaywallViewControllerDelegate {
52
+
53
+ // MARK: Exported props (native → JS callbacks; RCTBubblingEventBlock)
54
+
55
+ @objc var onLoaded: RCTBubblingEventBlock?
56
+ @objc var onError: RCTBubblingEventBlock?
57
+ @objc var onPurchase: RCTBubblingEventBlock?
58
+ @objc var onDismiss: RCTBubblingEventBlock?
59
+ @objc var onRestore: RCTBubblingEventBlock?
60
+ @objc var onOpenUrl: RCTBubblingEventBlock?
61
+ @objc var onTrackEvent: RCTBubblingEventBlock?
62
+
63
+ /// The placement / paywall identifier. Loading is triggered the first time a
64
+ /// non-empty value is assigned (RN sets props after construction).
65
+ @objc var paywallIdentifier: String? {
66
+ didSet {
67
+ guard let id = paywallIdentifier, !id.isEmpty else { return }
68
+ guard !didStartLoad else { return }
69
+ didStartLoad = true
70
+ loadPaywall(identifier: id)
71
+ }
72
+ }
73
+
74
+ // MARK: State
75
+
76
+ /// The embedded paywall VC (retained so it — and its delegate wiring —
77
+ /// survives). PaywallViewController: BillDogPaywall/UI/PaywallViewController.swift:16.
78
+ private var paywallViewController: PaywallViewController?
79
+
80
+ /// Guards a double-load (RN can re-assign the same prop).
81
+ private var didStartLoad = false
82
+
83
+ /// Guards against emitting `onDismiss` twice (a `.close` action AND a
84
+ /// `didFinishWith(.dismissed)` lifecycle callback can both arrive).
85
+ private var didEmitDismiss = false
86
+
87
+ // MARK: - Loading / embedding
88
+
89
+ private func loadPaywall(identifier: String) {
90
+ Task { [weak self] in
91
+ guard let self = self else { return }
92
+ do {
93
+ // getPaywall(forPlacement:) → PaywallViewController.
94
+ // BillDog.swift:3243.
95
+ let vc = try await BillDog.shared.getPaywall(forPlacement: identifier)
96
+ await MainActor.run { [weak self] in
97
+ self?.embed(vc)
98
+ }
99
+ } catch {
100
+ self.send(self.onError, ["message": error.localizedDescription])
101
+ }
102
+ }
103
+ }
104
+
105
+ @MainActor
106
+ private func embed(_ vc: PaywallViewController) {
107
+ self.paywallViewController = vc
108
+
109
+ // Route paywall taps/lifecycle back through this object so we can execute
110
+ // purchases and forward events to JS (mirrors InternalPaywallDelegate).
111
+ vc.delegate = self
112
+
113
+ // Add the VC's view with edge-pinned constraints.
114
+ let child = vc.view!
115
+ child.translatesAutoresizingMaskIntoConstraints = false
116
+ addSubview(child)
117
+ NSLayoutConstraint.activate([
118
+ child.leadingAnchor.constraint(equalTo: leadingAnchor),
119
+ child.trailingAnchor.constraint(equalTo: trailingAnchor),
120
+ child.topAnchor.constraint(equalTo: topAnchor),
121
+ child.bottomAnchor.constraint(equalTo: bottomAnchor)
122
+ ])
123
+
124
+ // Establish a proper view-controller containment relationship when a host
125
+ // VC is reachable (so appearance/lifecycle + `present(...)` from the
126
+ // paywall work). Prefer the RN-provided ancestor VC; fall back to the
127
+ // front-most presented VC of the key window.
128
+ if let parent = reactViewController() ?? Self.nearestHostViewController() {
129
+ parent.addChild(vc)
130
+ vc.didMove(toParent: parent)
131
+ }
132
+
133
+ send(onLoaded, nil)
134
+ }
135
+
136
+ /// Best-effort walk to the front-most presented VC of the key window, used as
137
+ /// a fallback containment parent for the embedded paywall.
138
+ private static func nearestHostViewController() -> UIViewController? {
139
+ let window: UIWindow?
140
+ if #available(iOS 13.0, *) {
141
+ window = UIApplication.shared.connectedScenes
142
+ .compactMap { $0 as? UIWindowScene }
143
+ .flatMap { $0.windows }
144
+ .first(where: { $0.isKeyWindow }) ?? UIApplication.shared.windows.first(where: { $0.isKeyWindow })
145
+ } else {
146
+ window = UIApplication.shared.keyWindow
147
+ }
148
+ var top = window?.rootViewController
149
+ while let presented = top?.presentedViewController {
150
+ top = presented
151
+ }
152
+ return top
153
+ }
154
+
155
+ // MARK: - PaywallViewControllerDelegate
156
+
157
+ // MIRROR of BillDogPaywall/UI/InternalPaywallDelegate.swift:24 — the SDK's
158
+ // default routing of PaywallAction → BillDog.shared. `value` carries the
159
+ // action payload (productId for `.purchase`, url for `.openUrl`, etc.).
160
+ // PaywallAction enum + cases: PaywallViewController.swift:1197
161
+ // .purchase :1198, .restore :1201, .close :1202, .openUrl :1203.
162
+ func paywallViewController(
163
+ _ controller: PaywallViewController,
164
+ didReceiveAction action: PaywallAction,
165
+ value: String
166
+ ) {
167
+ switch action {
168
+ case .purchase:
169
+ // InternalPaywallDelegate.swift:26-39 → BillDog.shared.purchase(productId:)
170
+ // purchase(productId:) : BillDog.swift:1375 (→ PurchaseResult, PurchaseResult.swift:24)
171
+ let productId = value
172
+ Task { [weak self] in
173
+ guard let self = self else { return }
174
+ do {
175
+ let result = try await BillDog.shared.purchase(productId: productId)
176
+ self.send(self.onPurchase, [
177
+ "productId": Self.resolvedProductId(from: result, fallback: productId),
178
+ "data": Self.purchaseData(from: result) as Any
179
+ ])
180
+ } catch {
181
+ self.send(self.onError, ["message": error.localizedDescription])
182
+ }
183
+ }
184
+
185
+ case .restore:
186
+ // InternalPaywallDelegate.swift:41-49 → BillDog.shared.restore()
187
+ // restore() : BillDog.swift:1544 (→ PurchaseResult)
188
+ Task { [weak self] in
189
+ guard let self = self else { return }
190
+ do {
191
+ _ = try await BillDog.shared.restore()
192
+ self.send(self.onRestore, nil)
193
+ } catch {
194
+ self.send(self.onError, ["message": error.localizedDescription])
195
+ }
196
+ }
197
+
198
+ case .close:
199
+ // InternalPaywallDelegate.swift:51-52 dismisses the VC. Here the VC is
200
+ // embedded (not modally presented), so we just notify JS to tear down
201
+ // the view; JS owns the container lifecycle.
202
+ emitDismiss()
203
+
204
+ case .openUrl:
205
+ // InternalPaywallDelegate.swift:54-55 opens SFSafari in-app. For the
206
+ // embedded case we hand the URL to JS so the host app decides.
207
+ send(onOpenUrl, ["url": value])
208
+
209
+ case .webCheckout:
210
+ send(onTrackEvent, ["event": "web_checkout", "data": ["value": value]])
211
+
212
+ case .customCheckout:
213
+ send(onTrackEvent, ["event": "custom_checkout", "data": ["value": value]])
214
+
215
+ case .oauth(let provider):
216
+ // OAuth is fully handled inside PaywallViewController.handleOAuthAction
217
+ // before reaching the delegate (InternalPaywallDelegate.swift:76-79) —
218
+ // observation only.
219
+ send(onTrackEvent, ["event": "oauth", "data": ["provider": provider, "value": value]])
220
+
221
+ case .custom(let name):
222
+ send(onTrackEvent, ["event": "custom", "data": ["name": name, "value": value]])
223
+
224
+ case .openTerms:
225
+ send(onTrackEvent, ["event": "open_terms", "data": ["value": value]])
226
+
227
+ case .openPrivacy:
228
+ send(onTrackEvent, ["event": "open_privacy", "data": ["value": value]])
229
+
230
+ case .manageSubscription:
231
+ send(onTrackEvent, ["event": "manage_subscription", "data": ["value": value]])
232
+
233
+ case .requestRefund(let productIdentifier):
234
+ send(onTrackEvent, ["event": "request_refund", "data": ["productIdentifier": productIdentifier as Any, "value": value]])
235
+
236
+ case .upgradeSubscription(let currentProductIdentifier, let newProductIdentifier):
237
+ send(onTrackEvent, ["event": "upgrade_subscription", "data": [
238
+ "currentProductIdentifier": currentProductIdentifier as Any,
239
+ "newProductIdentifier": newProductIdentifier,
240
+ "value": value
241
+ ]])
242
+
243
+ case .downgradeSubscription(let currentProductIdentifier, let newProductIdentifier):
244
+ send(onTrackEvent, ["event": "downgrade_subscription", "data": [
245
+ "currentProductIdentifier": currentProductIdentifier as Any,
246
+ "newProductIdentifier": newProductIdentifier,
247
+ "value": value
248
+ ]])
249
+
250
+ case .executeAction(let actionType, let componentId, let idempotencyKey):
251
+ send(onTrackEvent, ["event": "execute_action", "data": [
252
+ "actionType": actionType,
253
+ "componentId": componentId,
254
+ "idempotencyKey": idempotencyKey as Any,
255
+ "value": value
256
+ ]])
257
+ }
258
+ }
259
+
260
+ // Lifecycle result (PaywallViewController.PaywallDismissResult:
261
+ // PaywallViewController.swift:118). Maps the terminal outcome to the matching
262
+ // JS event. `.purchased`/`.restored` are primarily driven by the action
263
+ // handler above (which carries richer SDK data); this path is the
264
+ // authoritative dismiss signal and a safety net.
265
+ func paywallViewController(
266
+ _ controller: PaywallViewController,
267
+ didFinishWith result: PaywallViewController.PaywallDismissResult,
268
+ shouldDismiss: Bool
269
+ ) {
270
+ switch result {
271
+ case .purchased(let productId):
272
+ // PaywallDismissResult.purchased(productId:) : PaywallViewController.swift:119
273
+ send(onPurchase, ["productId": productId, "data": NSNull()])
274
+ case .restored:
275
+ // PaywallDismissResult.restored : PaywallViewController.swift:120
276
+ send(onRestore, nil)
277
+ case .dismissed:
278
+ // PaywallDismissResult.dismissed : PaywallViewController.swift:121
279
+ emitDismiss()
280
+ case .oauthSuccess(let provider, let userId, let email, let name, let idToken):
281
+ // PaywallDismissResult.oauthSuccess : PaywallViewController.swift:122
282
+ send(onTrackEvent, ["event": "oauth_success", "data": [
283
+ "provider": provider,
284
+ "userId": userId as Any,
285
+ "email": email as Any,
286
+ "name": name as Any,
287
+ "idToken": idToken as Any
288
+ ]])
289
+ }
290
+
291
+ if shouldDismiss {
292
+ emitDismiss()
293
+ }
294
+ }
295
+
296
+ // Loading-state callback (PaywallViewController.PaywallLoadingState:
297
+ // PaywallViewController.swift:83). Observation only — `onLoaded` is emitted
298
+ // from `embed(_:)`.
299
+ func paywallViewController(
300
+ _ controller: PaywallViewController,
301
+ loadingStateDidChange state: PaywallViewController.PaywallLoadingState
302
+ ) { }
303
+
304
+ // MARK: - Helpers
305
+
306
+ private func emitDismiss() {
307
+ guard !didEmitDismiss else { return }
308
+ didEmitDismiss = true
309
+ send(onDismiss, nil)
310
+ }
311
+
312
+ /// Fire an RCTBubblingEventBlock on the main thread with a `[String: Any]`
313
+ /// payload. RN block calls must occur on the main thread.
314
+ private func send(_ block: RCTBubblingEventBlock?, _ payload: [String: Any]?) {
315
+ guard let block = block else { return }
316
+ let body = payload ?? [:]
317
+ if Thread.isMainThread {
318
+ block(body)
319
+ } else {
320
+ DispatchQueue.main.async {
321
+ block(body)
322
+ }
323
+ }
324
+ }
325
+
326
+ /// Resolve the productId from a PurchaseResult (PurchaseResult.swift:24),
327
+ /// falling back to the tapped product on non-success outcomes.
328
+ private static func resolvedProductId(from result: PurchaseResult, fallback: String) -> String {
329
+ switch result {
330
+ case .purchased(_, let productId, _): return productId
331
+ case .restored(_, let productId, _): return productId
332
+ default: return fallback
333
+ }
334
+ }
335
+
336
+ /// Flatten a PurchaseResult into a `[String: Any]?` payload for JS.
337
+ private static func purchaseData(from result: PurchaseResult) -> [String: Any]? {
338
+ switch result {
339
+ case .purchased(let transactionId, let productId, let originalTransactionId):
340
+ return [
341
+ "status": "purchased",
342
+ "transactionId": transactionId,
343
+ "productId": productId,
344
+ "originalTransactionId": originalTransactionId as Any
345
+ ]
346
+ case .restored(let transactionId, let productId, let originalTransactionId):
347
+ return [
348
+ "status": "restored",
349
+ "transactionId": transactionId,
350
+ "productId": productId,
351
+ "originalTransactionId": originalTransactionId as Any
352
+ ]
353
+ case .cancelled:
354
+ return ["status": "cancelled"]
355
+ case .pending:
356
+ return ["status": "pending"]
357
+ case .failed(let error):
358
+ return ["status": "failed", "error": error.localizedDescription]
359
+ }
360
+ }
361
+ }
@@ -0,0 +1,34 @@
1
+ //
2
+ // BillDogSurvey.m
3
+ // @billdog.io/react-native
4
+ //
5
+ // RCT_EXTERN bridge declarations for the BillDogSurvey Swift module.
6
+ // ⚠️ Requires `pod install` + Xcode to compile/verify — no iOS toolchain in
7
+ // the authoring environment.
8
+ //
9
+
10
+ #import <React/RCTBridgeModule.h>
11
+ #import <React/RCTEventEmitter.h>
12
+
13
+ @interface RCT_EXTERN_MODULE(BillDogSurvey, RCTEventEmitter)
14
+
15
+ RCT_EXTERN_METHOD(initialize:(RCTPromiseResolveBlock)resolve
16
+ rejecter:(RCTPromiseRejectBlock)reject)
17
+
18
+ RCT_EXTERN_METHOD(presentSurvey:(NSDictionary *)options
19
+ resolver:(RCTPromiseResolveBlock)resolve
20
+ rejecter:(RCTPromiseRejectBlock)reject)
21
+
22
+ RCT_EXTERN_METHOD(fetchSurvey:(NSString *)surveyIdentifier
23
+ resolver:(RCTPromiseResolveBlock)resolve
24
+ rejecter:(RCTPromiseRejectBlock)reject)
25
+
26
+ RCT_EXTERN_METHOD(submitResponse:(NSDictionary *)response
27
+ resolver:(RCTPromiseResolveBlock)resolve
28
+ rejecter:(RCTPromiseRejectBlock)reject)
29
+
30
+ RCT_EXTERN_METHOD(canShowSurvey:(NSString *)surveyIdentifier
31
+ resolver:(RCTPromiseResolveBlock)resolve
32
+ rejecter:(RCTPromiseRejectBlock)reject)
33
+
34
+ @end