@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,389 @@
1
+ package io.billdog.reactnative
2
+
3
+ import android.net.Uri
4
+ import android.util.Log
5
+ import com.facebook.react.bridge.Arguments
6
+ import com.facebook.react.bridge.Promise
7
+ import com.facebook.react.bridge.ReactApplicationContext
8
+ import com.facebook.react.bridge.ReactContextBaseJavaModule
9
+ import com.facebook.react.bridge.ReactMethod
10
+ import com.facebook.react.bridge.ReadableMap
11
+ import com.facebook.react.bridge.WritableArray
12
+ import com.facebook.react.bridge.WritableMap
13
+ import com.facebook.react.modules.core.DeviceEventManagerModule
14
+ import io.billdog.core.BillDog
15
+ import kotlinx.coroutines.CoroutineScope
16
+ import kotlinx.coroutines.Dispatchers
17
+ import kotlinx.coroutines.SupervisorJob
18
+ import kotlinx.coroutines.cancel
19
+ import kotlinx.coroutines.launch
20
+
21
+ /**
22
+ * BillDogAnalytics — React Native native module for Android
23
+ * (`NativeModules.BillDogAnalytics`).
24
+ *
25
+ * Thin bridge: every `@ReactMethod` here delegates to the concrete analytics
26
+ * manager (`io.billdog.analytics.BillDogAnalytics`) resolved per-call from the
27
+ * live module registry (`BillDog.getModules()` — billdog-core BillDog.kt:427),
28
+ * mirroring the Flutter plugin's BillDogAnalyticsChannelHandler.kt. The
29
+ * authoritative JS contract is `src/modules/Analytics.ts`; each
30
+ * `BillDogAnalytics.<method>(...)` call there maps to the identically-named
31
+ * method below. When the manager is not registered (SDK not configured /
32
+ * analytics absent) it resolves to `null` and every mutating call is a
33
+ * best-effort NO-OP that resolves — matching the JS contract.
34
+ *
35
+ * ⚠️ VERIFICATION: this file cannot be compiled in this environment — there is
36
+ * no Android/Gradle toolchain present. It needs a Gradle/Android build
37
+ * (`./gradlew :billdog_react-native:compileDebugKotlin` or the example app
38
+ * build) to type-check against the resolved io.billdog:billdog-core +
39
+ * billdog-analytics + kotlinx-coroutines artifacts declared in
40
+ * android/build.gradle. Every native symbol below is cited to file:line.
41
+ */
42
+ class BillDogAnalyticsModule(private val reactContext: ReactApplicationContext) :
43
+ ReactContextBaseJavaModule(reactContext) {
44
+
45
+ private val TAG = "BillDogAnalytics"
46
+
47
+ /** Suspend/async work is launched here; cancelled in invalidate(). */
48
+ private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
49
+
50
+ override fun getName(): String = "BillDogAnalytics"
51
+
52
+ // ── Lifecycle ──────────────────────────────────────────────────────────
53
+
54
+ override fun invalidate() {
55
+ scope.cancel()
56
+ super.invalidate()
57
+ }
58
+
59
+ @Deprecated("Deprecated in RN; kept for older RN versions that call it instead of invalidate()")
60
+ override fun onCatalystInstanceDestroy() {
61
+ scope.cancel()
62
+ @Suppress("DEPRECATION")
63
+ super.onCatalystInstanceDestroy()
64
+ }
65
+
66
+ /**
67
+ * Resolve the concrete analytics manager from the live module registry.
68
+ * Looked up per-call so late module registration is picked up automatically.
69
+ * Returns null when analytics is not registered → callers NO-OP.
70
+ */
71
+ private fun analytics(): io.billdog.analytics.BillDogAnalytics? =
72
+ BillDog.getModules() // billdog-core BillDog.kt:427
73
+ .firstOrNull { it is io.billdog.analytics.BillDogAnalytics }
74
+ as? io.billdog.analytics.BillDogAnalytics
75
+
76
+ /** Run [block] on the main scope; map any throwable → promise.reject. */
77
+ private fun run(promise: Promise, block: () -> Any?) {
78
+ scope.launch {
79
+ try {
80
+ promise.resolve(block())
81
+ } catch (e: Throwable) {
82
+ promise.reject("BILLDOG_ERROR", e.message, e)
83
+ }
84
+ }
85
+ }
86
+
87
+ // ── Init ────────────────────────────────────────────────────────────────
88
+
89
+ /**
90
+ * BillDogAnalytics.initialize() — the native analytics manager is configured
91
+ * by the core `BillDog.configure(...)` (server-driven config), not per-module.
92
+ * No native per-module init exists; resolve null (documented no-op).
93
+ */
94
+ @ReactMethod
95
+ fun initialize(promise: Promise) {
96
+ // The analytics module is registered by BillDogModule.configure() via
97
+ // BillDog.use(...) — NOT by BillDog.configure(), which registers nothing.
98
+ // (An earlier version of this comment claimed otherwise, which masked the
99
+ // fact that nothing registered analytics at all and every event was
100
+ // silently dropped.) Nothing to do here; kept so the JS init handshake
101
+ // resolves. Warn when the registry is still empty so the failure is loud.
102
+ if (analytics() == null) {
103
+ Log.w(
104
+ TAG,
105
+ "initialize(): analytics module NOT registered — call BillDog configure() first; " +
106
+ "track()/identify() will no-op and events will not be delivered"
107
+ )
108
+ }
109
+ promise.resolve(null)
110
+ }
111
+
112
+ // ── Tracking ──────────────────────────────────────────────────────────────
113
+
114
+ /**
115
+ * BillDogAnalytics.track(name, properties) → BillDog.trackEvent(name, props)
116
+ * — billdog-core BillDog.kt:924 (facade, routes to the registered analytics
117
+ * module internally). Mirrors the Flutter `analytics_track` branch.
118
+ */
119
+ @ReactMethod
120
+ @Suppress("UNCHECKED_CAST")
121
+ fun track(name: String, properties: ReadableMap?, promise: Promise) {
122
+ run(promise) {
123
+ val props = (properties?.toHashMap() as? Map<String, Any>) ?: emptyMap()
124
+ BillDog.trackEvent(name, props) // BillDog.kt:924
125
+ null
126
+ }
127
+ }
128
+
129
+ /**
130
+ * BillDogAnalytics.trackRevenue(amount, currency, productId, properties) →
131
+ * mgr.trackRevenue(amount, currency, productId, properties) —
132
+ * BillDogAnalytics.kt:797 (quantity/revenueType defaulted).
133
+ */
134
+ @ReactMethod
135
+ @Suppress("UNCHECKED_CAST")
136
+ fun trackRevenue(
137
+ amount: Double,
138
+ currency: String?,
139
+ productId: String?,
140
+ properties: ReadableMap?,
141
+ promise: Promise
142
+ ) {
143
+ run(promise) {
144
+ analytics()?.trackRevenue(
145
+ amount = amount,
146
+ currency = currency ?: "USD",
147
+ productId = productId,
148
+ properties = (properties?.toHashMap() as? Map<String, Any>) ?: emptyMap()
149
+ )
150
+ null
151
+ }
152
+ }
153
+
154
+ /** BillDogAnalytics.identify(userId, properties) → mgr.identify(userId, properties) — BillDogAnalytics.kt:768. */
155
+ @ReactMethod
156
+ @Suppress("UNCHECKED_CAST")
157
+ fun identify(userId: String, properties: ReadableMap?, promise: Promise) {
158
+ run(promise) {
159
+ analytics()?.identify(userId, (properties?.toHashMap() as? Map<String, Any>) ?: emptyMap()) // :768
160
+ null
161
+ }
162
+ }
163
+
164
+ /** BillDogAnalytics.setSuperProperties(properties) → mgr.registerSuperProperties(properties) — BillDogAnalytics.kt:546. */
165
+ @ReactMethod
166
+ @Suppress("UNCHECKED_CAST")
167
+ fun setSuperProperties(properties: ReadableMap?, promise: Promise) {
168
+ run(promise) {
169
+ analytics()?.registerSuperProperties((properties?.toHashMap() as? Map<String, Any>) ?: emptyMap()) // :546
170
+ null
171
+ }
172
+ }
173
+
174
+ /** BillDogAnalytics.registerSuperPropertiesOnce(properties) → mgr.registerSuperPropertiesOnce(properties) — BillDogAnalytics.kt:553. */
175
+ @ReactMethod
176
+ @Suppress("UNCHECKED_CAST")
177
+ fun registerSuperPropertiesOnce(properties: ReadableMap?, promise: Promise) {
178
+ run(promise) {
179
+ analytics()?.registerSuperPropertiesOnce((properties?.toHashMap() as? Map<String, Any>) ?: emptyMap()) // :553
180
+ null
181
+ }
182
+ }
183
+
184
+ /** BillDogAnalytics.unregisterSuperProperty(key) → mgr.unregisterSuperProperty(key) — BillDogAnalytics.kt:564. */
185
+ @ReactMethod
186
+ fun unregisterSuperProperty(key: String, promise: Promise) {
187
+ run(promise) { analytics()?.unregisterSuperProperty(key); null } // :564
188
+ }
189
+
190
+ /** BillDogAnalytics.clearSuperProperties() → mgr.clearSuperProperties() — BillDogAnalytics.kt:569. */
191
+ @ReactMethod
192
+ fun clearSuperProperties(promise: Promise) {
193
+ run(promise) { analytics()?.clearSuperProperties(); null } // :569
194
+ }
195
+
196
+ /**
197
+ * BillDogAnalytics.updateUserProperties(operation, properties) — dispatches to
198
+ * the operation-specific manager method. Mirrors the Flutter
199
+ * `analytics_updateUserProperties` branch exactly:
200
+ * $set → setUserProperties — BillDogAnalytics.kt:831
201
+ * $set_once → setUserPropertyOnce(key,value) per key — :835
202
+ * $add → incrementUserProperty(key,amount) per key — :839
203
+ * $append → appendToUserProperty(key,value) per key — :843
204
+ * $unset → unsetUserProperties(keys) — :851
205
+ * $remove → best-effort no-op (no native remove-from-list API).
206
+ */
207
+ @ReactMethod
208
+ @Suppress("UNCHECKED_CAST")
209
+ fun updateUserProperties(operation: String, properties: ReadableMap?, promise: Promise) {
210
+ run(promise) {
211
+ val mgr = analytics()
212
+ if (mgr != null) {
213
+ val props = (properties?.toHashMap() as? Map<String, Any>) ?: emptyMap()
214
+ when (operation) {
215
+ "\$set" -> mgr.setUserProperties(props) // :831
216
+ "\$set_once" -> props.forEach { (k, v) -> mgr.setUserPropertyOnce(k, v) } // :835
217
+ "\$add" -> props.forEach { (k, v) ->
218
+ mgr.incrementUserProperty(k, (v as? Number)?.toDouble() ?: 1.0) // :839
219
+ }
220
+ "\$append" -> props.forEach { (k, v) -> mgr.appendToUserProperty(k, v) } // :843
221
+ "\$unset" -> mgr.unsetUserProperties(props.keys.toList()) // :851
222
+ "\$remove" -> { /* no native remove-from-list API — no-op */ }
223
+ else -> { /* unknown operation — no-op */ }
224
+ }
225
+ }
226
+ null
227
+ }
228
+ }
229
+
230
+ /**
231
+ * BillDogAnalytics.flush() → mgr.flush() — BillDogAnalytics.kt:859. Emits
232
+ * `onAnalyticsFlush` afterward. Native flush() returns no batch count, so
233
+ * `eventCount` is emitted as 0 (documented limitation — the JS `onFlush`
234
+ * listener is debugging-only).
235
+ */
236
+ @ReactMethod
237
+ fun flush(promise: Promise) {
238
+ run(promise) {
239
+ analytics()?.flush() // :859
240
+ emit("onAnalyticsFlush", toWritableMap(mapOf("eventCount" to 0)))
241
+ null
242
+ }
243
+ }
244
+
245
+ /** BillDogAnalytics.optOut() → mgr.optOut() — BillDogAnalytics.kt:519. */
246
+ @ReactMethod
247
+ fun optOut(promise: Promise) {
248
+ run(promise) { analytics()?.optOut(); null } // :519
249
+ }
250
+
251
+ /** BillDogAnalytics.optIn() → mgr.optIn() — BillDogAnalytics.kt:532. */
252
+ @ReactMethod
253
+ fun optIn(promise: Promise) {
254
+ run(promise) { analytics()?.optIn(); null } // :532
255
+ }
256
+
257
+ /** BillDogAnalytics.reset() → mgr.reset() — BillDogAnalytics.kt:1015. */
258
+ @ReactMethod
259
+ fun reset(promise: Promise) {
260
+ run(promise) { analytics()?.reset(); null } // :1015
261
+ }
262
+
263
+ /** BillDogAnalytics.alias(newId, originalId?) → mgr.alias(newId, previousId=originalId) — BillDogAnalytics.kt:1209. */
264
+ @ReactMethod
265
+ fun alias(newId: String, originalId: String?, promise: Promise) {
266
+ run(promise) { analytics()?.alias(newId, previousId = originalId); null } // :1209
267
+ }
268
+
269
+ /** BillDogAnalytics.timeEvent(eventName) → mgr.timeEvent(eventName) — BillDogAnalytics.kt:1200. */
270
+ @ReactMethod
271
+ fun timeEvent(eventName: String, promise: Promise) {
272
+ run(promise) { analytics()?.timeEvent(eventName); null } // :1200
273
+ }
274
+
275
+ /** BillDogAnalytics.setGroup(groupType, groupId) → mgr.setGroup(groupType, groupId) — BillDogAnalytics.kt:1170. */
276
+ @ReactMethod
277
+ fun setGroup(groupType: String, groupId: String, promise: Promise) {
278
+ run(promise) { analytics()?.setGroup(groupType, groupId); null } // :1170
279
+ }
280
+
281
+ /** BillDogAnalytics.setGroupProperties(groupType, groupId, properties) → mgr.setGroupProperties(...) — BillDogAnalytics.kt:1182. */
282
+ @ReactMethod
283
+ @Suppress("UNCHECKED_CAST")
284
+ fun setGroupProperties(groupType: String, groupId: String, properties: ReadableMap?, promise: Promise) {
285
+ run(promise) {
286
+ analytics()?.setGroupProperties(
287
+ groupType, groupId, (properties?.toHashMap() as? Map<String, Any>) ?: emptyMap()
288
+ ) // :1182
289
+ null
290
+ }
291
+ }
292
+
293
+ /** BillDogAnalytics.trackScreen(screenName, properties) → mgr.trackScreen(screenName, properties) — BillDogAnalytics.kt:1100. */
294
+ @ReactMethod
295
+ @Suppress("UNCHECKED_CAST")
296
+ fun trackScreen(screenName: String, properties: ReadableMap?, promise: Promise) {
297
+ run(promise) {
298
+ analytics()?.trackScreen(screenName, (properties?.toHashMap() as? Map<String, Any>) ?: emptyMap()) // :1100
299
+ null
300
+ }
301
+ }
302
+
303
+ /** BillDogAnalytics.trackDeepLink(url) → mgr.trackDeepLink(Uri.parse(url)) — BillDogAnalytics.kt:1092 (Uri overload). */
304
+ @ReactMethod
305
+ fun trackDeepLink(url: String, promise: Promise) {
306
+ run(promise) { analytics()?.trackDeepLink(Uri.parse(url)); null } // :1092
307
+ }
308
+
309
+ /** BillDogAnalytics.getDeviceId() → mgr.getDeviceId() — BillDogAnalytics.kt:1136 (null when unconfigured). */
310
+ @ReactMethod
311
+ fun getDeviceId(promise: Promise) {
312
+ run(promise) { analytics()?.getDeviceId() } // :1136
313
+ }
314
+
315
+ /** BillDogAnalytics.getDistinctId() → mgr.getDistinctId() — BillDogAnalytics.kt:1160. */
316
+ @ReactMethod
317
+ fun getDistinctId(promise: Promise) {
318
+ run(promise) { analytics()?.getDistinctId() } // :1160
319
+ }
320
+
321
+ /** BillDogAnalytics.getSessionId() → mgr.getSessionId() — BillDogAnalytics.kt:1108. */
322
+ @ReactMethod
323
+ fun getSessionId(promise: Promise) {
324
+ run(promise) { analytics()?.getSessionId() } // :1108
325
+ }
326
+
327
+ // ── NativeEventEmitter plumbing (onAnalyticsFlush) ───────────────────────
328
+ // Required so RN's NativeEventEmitter attaches without warnings. No native
329
+ // subscription is needed — flush() emits directly.
330
+
331
+ @ReactMethod
332
+ fun addListener(eventName: String) { /* NativeEventEmitter bookkeeping — no-op */ }
333
+
334
+ @ReactMethod
335
+ fun removeListeners(count: Int) { /* NativeEventEmitter bookkeeping — no-op */ }
336
+
337
+ private fun emit(event: String, params: WritableMap?) {
338
+ reactContext
339
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
340
+ .emit(event, params)
341
+ }
342
+
343
+ // ── Map<String, Any?> → WritableMap converter (private per-module copy) ───
344
+
345
+ private fun toWritableMap(map: Map<String, Any?>): WritableMap {
346
+ val out = Arguments.createMap()
347
+ for ((key, value) in map) {
348
+ when (value) {
349
+ null -> out.putNull(key)
350
+ is Boolean -> out.putBoolean(key, value)
351
+ is Int -> out.putInt(key, value)
352
+ is Long -> out.putDouble(key, value.toDouble())
353
+ is Float -> out.putDouble(key, value.toDouble())
354
+ is Double -> out.putDouble(key, value)
355
+ is String -> out.putString(key, value)
356
+ is WritableMap -> out.putMap(key, value)
357
+ is WritableArray -> out.putArray(key, value)
358
+ is Map<*, *> -> out.putMap(key, toWritableMap(coerceStringKeys(value)))
359
+ is List<*> -> out.putArray(key, toWritableArray(value))
360
+ else -> out.putString(key, value.toString())
361
+ }
362
+ }
363
+ return out
364
+ }
365
+
366
+ private fun toWritableArray(list: List<*>): WritableArray {
367
+ val out = Arguments.createArray()
368
+ for (value in list) {
369
+ when (value) {
370
+ null -> out.pushNull()
371
+ is Boolean -> out.pushBoolean(value)
372
+ is Int -> out.pushInt(value)
373
+ is Long -> out.pushDouble(value.toDouble())
374
+ is Float -> out.pushDouble(value.toDouble())
375
+ is Double -> out.pushDouble(value)
376
+ is String -> out.pushString(value)
377
+ is WritableMap -> out.pushMap(value)
378
+ is WritableArray -> out.pushArray(value)
379
+ is Map<*, *> -> out.pushMap(toWritableMap(coerceStringKeys(value)))
380
+ is List<*> -> out.pushArray(toWritableArray(value))
381
+ else -> out.pushString(value.toString())
382
+ }
383
+ }
384
+ return out
385
+ }
386
+
387
+ private fun coerceStringKeys(map: Map<*, *>): Map<String, Any?> =
388
+ map.entries.associate { (k, v) -> k.toString() to v }
389
+ }