@bigcrunch/react-native-ads 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +417 -0
  2. package/android/build.gradle +70 -0
  3. package/android/settings.gradle +6 -0
  4. package/android/src/main/AndroidManifest.xml +3 -0
  5. package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchAdsModule.kt +653 -0
  6. package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchAdsPackage.kt +20 -0
  7. package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchBannerViewManager.kt +296 -0
  8. package/ios/BigCrunchAdsModule.swift +588 -0
  9. package/ios/BigCrunchBannerViewManager.swift +270 -0
  10. package/ios/react-native-bigcrunch-ads-Bridging-Header.h +8 -0
  11. package/lib/BigCrunchAds.d.ts +168 -0
  12. package/lib/BigCrunchAds.d.ts.map +1 -0
  13. package/lib/BigCrunchAds.js +241 -0
  14. package/lib/BigCrunchBannerView.d.ts +21 -0
  15. package/lib/BigCrunchBannerView.d.ts.map +1 -0
  16. package/lib/BigCrunchBannerView.js +176 -0
  17. package/lib/BigCrunchInterstitial.d.ts +66 -0
  18. package/lib/BigCrunchInterstitial.d.ts.map +1 -0
  19. package/lib/BigCrunchInterstitial.js +222 -0
  20. package/lib/BigCrunchRewarded.d.ts +85 -0
  21. package/lib/BigCrunchRewarded.d.ts.map +1 -0
  22. package/lib/BigCrunchRewarded.js +257 -0
  23. package/lib/NativeBigCrunchAds.d.ts +71 -0
  24. package/lib/NativeBigCrunchAds.d.ts.map +1 -0
  25. package/lib/NativeBigCrunchAds.js +54 -0
  26. package/lib/index.d.ts +28 -0
  27. package/lib/index.d.ts.map +1 -0
  28. package/lib/index.js +32 -0
  29. package/lib/types/ads.d.ts +101 -0
  30. package/lib/types/ads.d.ts.map +1 -0
  31. package/lib/types/ads.js +4 -0
  32. package/lib/types/config.d.ts +137 -0
  33. package/lib/types/config.d.ts.map +1 -0
  34. package/lib/types/config.js +4 -0
  35. package/lib/types/events.d.ts +306 -0
  36. package/lib/types/events.d.ts.map +1 -0
  37. package/lib/types/events.js +4 -0
  38. package/lib/types/index.d.ts +175 -0
  39. package/lib/types/index.d.ts.map +1 -0
  40. package/lib/types/index.js +23 -0
  41. package/package.json +88 -0
  42. package/react-native-bigcrunch-ads.podspec +27 -0
  43. package/src/BigCrunchAds.ts +298 -0
  44. package/src/BigCrunchBannerView.tsx +262 -0
  45. package/src/BigCrunchInterstitial.ts +266 -0
  46. package/src/BigCrunchRewarded.ts +307 -0
  47. package/src/NativeBigCrunchAds.ts +120 -0
  48. package/src/index.ts +71 -0
  49. package/src/types/ads.ts +112 -0
  50. package/src/types/config.ts +145 -0
  51. package/src/types/events.ts +337 -0
  52. package/src/types/index.ts +193 -0
@@ -0,0 +1,653 @@
1
+ package com.bigcrunch.ads.react
2
+
3
+ import com.facebook.react.bridge.*
4
+ import com.facebook.react.modules.core.DeviceEventManagerModule
5
+ import com.bigcrunch.ads.*
6
+ import com.bigcrunch.ads.models.*
7
+ import kotlinx.coroutines.*
8
+
9
+ /**
10
+ * React Native bridge module for BigCrunch Ads SDK
11
+ */
12
+ class BigCrunchAdsModule(reactContext: ReactApplicationContext) :
13
+ ReactContextBaseJavaModule(reactContext) {
14
+
15
+ private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
16
+ private val interstitialCache = mutableMapOf<String, Any>() // Placeholder for interstitial instances
17
+ private val rewardedCache = mutableMapOf<String, Any>() // Placeholder for rewarded instances
18
+
19
+ override fun getName(): String = "BigCrunchAdsModule"
20
+
21
+ override fun onCatalystInstanceDestroy() {
22
+ super.onCatalystInstanceDestroy()
23
+ scope.cancel()
24
+ }
25
+
26
+ /**
27
+ * Initialize the SDK
28
+ */
29
+ @ReactMethod
30
+ fun initialize(options: ReadableMap, promise: Promise) {
31
+ try {
32
+ val propertyId = options.getString("propertyId")
33
+ ?: throw IllegalArgumentException("propertyId is required")
34
+ val apiKey = options.getString("apiKey")
35
+ ?: throw IllegalArgumentException("apiKey is required")
36
+ val environment = options.getString("environment") ?: "production"
37
+ val debug = if (options.hasKey("debug")) options.getBoolean("debug") else false
38
+
39
+ // Initialize the native SDK
40
+ val context = reactApplicationContext.applicationContext
41
+
42
+ scope.launch {
43
+ try {
44
+ BigCrunchAds.initialize(
45
+ context = context,
46
+ propertyId = propertyId,
47
+ apiKey = apiKey,
48
+ env = if (environment == "staging")
49
+ BigCrunchAds.Environment.Staging
50
+ else
51
+ BigCrunchAds.Environment.Prod,
52
+ // Use mock config for testing/development
53
+ useMockConfig = environment == "sandbox"
54
+ )
55
+
56
+ if (debug) {
57
+ BigCrunchAds.setDebugMode(true)
58
+ }
59
+
60
+ // SDK initialization is complete
61
+ // The Android SDK now handles config loading internally
62
+ promise.resolve(null)
63
+ } catch (e: Exception) {
64
+ promise.reject("INIT_ERROR", "Failed to initialize SDK: ${e.message}", e)
65
+ }
66
+ }
67
+ } catch (e: Exception) {
68
+ promise.reject("INIT_ERROR", "Failed to initialize SDK: ${e.message}", e)
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Check if SDK is initialized
74
+ */
75
+ @ReactMethod
76
+ fun isInitialized(promise: Promise) {
77
+ promise.resolve(BigCrunchAds.isInitialized())
78
+ }
79
+
80
+ /**
81
+ * Track screen view
82
+ */
83
+ @ReactMethod
84
+ fun trackScreenView(screenName: String, promise: Promise) {
85
+ scope.launch {
86
+ try {
87
+ BigCrunchAds.trackScreenView(screenName)
88
+ promise.resolve(null)
89
+ } catch (e: Exception) {
90
+ promise.reject("TRACK_ERROR", "Failed to track screen view: ${e.message}", e)
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Get app configuration
97
+ */
98
+ @ReactMethod
99
+ fun getAppConfig(promise: Promise) {
100
+ scope.launch {
101
+ try {
102
+ val config = BigCrunchAds.getAppConfig()
103
+ if (config != null) {
104
+ promise.resolve(convertAppConfigToMap(config))
105
+ } else {
106
+ promise.resolve(null)
107
+ }
108
+ } catch (e: Exception) {
109
+ promise.reject("CONFIG_ERROR", "Failed to get app config: ${e.message}", e)
110
+ }
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Refresh configuration
116
+ */
117
+ @ReactMethod
118
+ fun refreshConfig(promise: Promise) {
119
+ scope.launch {
120
+ try {
121
+ BigCrunchAds.refreshConfig()
122
+ promise.resolve(null)
123
+ } catch (e: Exception) {
124
+ promise.reject("CONFIG_ERROR", "Failed to refresh config: ${e.message}", e)
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Load interstitial ad
131
+ */
132
+ @ReactMethod
133
+ fun loadInterstitial(options: ReadableMap, promise: Promise) {
134
+ try {
135
+ val placementId = options.getString("placementId")
136
+ ?: throw IllegalArgumentException("placementId is required")
137
+
138
+ scope.launch {
139
+ try {
140
+ // Create ad request options
141
+ val customTargeting = options.getMap("customTargeting")?.let {
142
+ convertMapToStringMap(it)
143
+ }
144
+
145
+ // Set up callbacks to emit events to JavaScript
146
+ val context = reactApplicationContext.applicationContext
147
+ BigCrunchInterstitial.preload(
148
+ context = context,
149
+ placementId = placementId,
150
+ callback = object : BigCrunchInterstitial.PreloadCallback {
151
+ override fun onAdLoaded() {
152
+ val eventParams = Arguments.createMap()
153
+ eventParams.putString("placementId", placementId)
154
+ sendEvent("BigCrunchInterstitialAdLoaded", eventParams)
155
+
156
+ // Store the loaded ad in cache (for tracking)
157
+ interstitialCache[placementId] = true
158
+ }
159
+
160
+ override fun onAdFailedToLoad(error: String) {
161
+ val eventParams = Arguments.createMap()
162
+ eventParams.putString("placementId", placementId)
163
+ eventParams.putString("errorCode", "LOAD_FAILED")
164
+ eventParams.putString("errorMessage", error)
165
+ sendEvent("BigCrunchInterstitialAdFailedToLoad", eventParams)
166
+ }
167
+ }
168
+ )
169
+
170
+ // Apply custom targeting if provided (will be implemented in AdOrchestrator later)
171
+ if (customTargeting != null) {
172
+ // TODO: Pass custom targeting to AdOrchestrator
173
+ }
174
+
175
+ promise.resolve(null)
176
+ } catch (e: Exception) {
177
+ promise.reject("LOAD_ERROR", "Failed to load interstitial: ${e.message}", e)
178
+ }
179
+ }
180
+ } catch (e: Exception) {
181
+ promise.reject("LOAD_ERROR", "Failed to load interstitial: ${e.message}", e)
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Show interstitial ad
187
+ */
188
+ @ReactMethod
189
+ fun showInterstitial(placementId: String, promise: Promise) {
190
+ val activity = currentActivity
191
+ if (activity == null) {
192
+ promise.reject("NO_ACTIVITY", "No current activity available")
193
+ return
194
+ }
195
+
196
+ scope.launch {
197
+ try {
198
+ val callback = object : BigCrunchInterstitial.ShowCallback {
199
+ override fun onAdShowed() {
200
+ val eventParams = Arguments.createMap()
201
+ eventParams.putString("placementId", placementId)
202
+ sendEvent("BigCrunchInterstitialAdOpened", eventParams)
203
+
204
+ // Also emit impression event
205
+ sendEvent("BigCrunchInterstitialAdImpression", eventParams)
206
+ }
207
+
208
+ override fun onAdDismissed() {
209
+ val eventParams = Arguments.createMap()
210
+ eventParams.putString("placementId", placementId)
211
+ sendEvent("BigCrunchInterstitialAdClosed", eventParams)
212
+
213
+ // Clear from cache on dismissal
214
+ interstitialCache.remove(placementId)
215
+ }
216
+
217
+ override fun onAdClicked() {
218
+ val eventParams = Arguments.createMap()
219
+ eventParams.putString("placementId", placementId)
220
+ sendEvent("BigCrunchInterstitialAdClicked", eventParams)
221
+ }
222
+
223
+ override fun onAdFailedToShow(error: String) {
224
+ val eventParams = Arguments.createMap()
225
+ eventParams.putString("placementId", placementId)
226
+ eventParams.putString("errorCode", "SHOW_FAILED")
227
+ eventParams.putString("errorMessage", error)
228
+ sendEvent("BigCrunchInterstitialAdFailedToShow", eventParams)
229
+ }
230
+ }
231
+
232
+ BigCrunchInterstitial.show(activity, placementId, callback)
233
+ promise.resolve(null)
234
+ } catch (e: Exception) {
235
+ promise.reject("SHOW_ERROR", "Failed to show interstitial: ${e.message}", e)
236
+ }
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Check if interstitial is loaded
242
+ */
243
+ @ReactMethod
244
+ fun isInterstitialLoaded(placementId: String, promise: Promise) {
245
+ promise.resolve(BigCrunchInterstitial.isLoaded(placementId))
246
+ }
247
+
248
+ /**
249
+ * Destroy interstitial
250
+ */
251
+ @ReactMethod
252
+ fun destroyInterstitial(placementId: String, promise: Promise) {
253
+ try {
254
+ BigCrunchInterstitial.destroy(placementId)
255
+ interstitialCache.remove(placementId)
256
+ promise.resolve(null)
257
+ } catch (e: Exception) {
258
+ promise.reject("DESTROY_ERROR", "Failed to destroy interstitial: ${e.message}", e)
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Load rewarded ad
264
+ */
265
+ @ReactMethod
266
+ fun loadRewarded(options: ReadableMap, promise: Promise) {
267
+ try {
268
+ val placementId = options.getString("placementId")
269
+ ?: throw IllegalArgumentException("placementId is required")
270
+
271
+ scope.launch {
272
+ try {
273
+ val customTargeting = options.getMap("customTargeting")?.let {
274
+ convertMapToStringMap(it)
275
+ }
276
+
277
+ // Set up callbacks to emit events to JavaScript
278
+ val context = reactApplicationContext.applicationContext
279
+ BigCrunchRewarded.preload(
280
+ context = context,
281
+ placementId = placementId,
282
+ callback = object : BigCrunchRewarded.PreloadCallback {
283
+ override fun onAdLoaded() {
284
+ val eventParams = Arguments.createMap()
285
+ eventParams.putString("placementId", placementId)
286
+ sendEvent("BigCrunchRewardedAdLoaded", eventParams)
287
+
288
+ // Store the loaded ad in cache (for tracking)
289
+ rewardedCache[placementId] = true
290
+ }
291
+
292
+ override fun onAdFailedToLoad(error: String) {
293
+ val eventParams = Arguments.createMap()
294
+ eventParams.putString("placementId", placementId)
295
+ eventParams.putString("errorCode", "LOAD_FAILED")
296
+ eventParams.putString("errorMessage", error)
297
+ sendEvent("BigCrunchRewardedAdFailedToLoad", eventParams)
298
+ }
299
+ }
300
+ )
301
+
302
+ // Apply custom targeting if provided (will be implemented in AdOrchestrator later)
303
+ if (customTargeting != null) {
304
+ // TODO: Pass custom targeting to AdOrchestrator
305
+ }
306
+
307
+ promise.resolve(null)
308
+ } catch (e: Exception) {
309
+ promise.reject("LOAD_ERROR", "Failed to load rewarded: ${e.message}", e)
310
+ }
311
+ }
312
+ } catch (e: Exception) {
313
+ promise.reject("LOAD_ERROR", "Failed to load rewarded: ${e.message}", e)
314
+ }
315
+ }
316
+
317
+ /**
318
+ * Show rewarded ad
319
+ */
320
+ @ReactMethod
321
+ fun showRewarded(placementId: String, promise: Promise) {
322
+ val activity = currentActivity
323
+ if (activity == null) {
324
+ promise.reject("NO_ACTIVITY", "No current activity available")
325
+ return
326
+ }
327
+
328
+ scope.launch {
329
+ try {
330
+ val callback = object : BigCrunchRewarded.ShowCallback {
331
+ override fun onAdShowed() {
332
+ val eventParams = Arguments.createMap()
333
+ eventParams.putString("placementId", placementId)
334
+ sendEvent("BigCrunchRewardedAdOpened", eventParams)
335
+
336
+ // Also emit impression event
337
+ sendEvent("BigCrunchRewardedAdImpression", eventParams)
338
+ }
339
+
340
+ override fun onUserEarnedReward(type: String, amount: Int) {
341
+ val eventParams = Arguments.createMap()
342
+ eventParams.putString("placementId", placementId)
343
+ eventParams.putString("type", type)
344
+ eventParams.putInt("amount", amount)
345
+ sendEvent("BigCrunchRewardedAdEarned", eventParams)
346
+ }
347
+
348
+ override fun onAdDismissed() {
349
+ val eventParams = Arguments.createMap()
350
+ eventParams.putString("placementId", placementId)
351
+ sendEvent("BigCrunchRewardedAdClosed", eventParams)
352
+
353
+ // Clear from cache on dismissal
354
+ rewardedCache.remove(placementId)
355
+ }
356
+
357
+ override fun onAdClicked() {
358
+ val eventParams = Arguments.createMap()
359
+ eventParams.putString("placementId", placementId)
360
+ sendEvent("BigCrunchRewardedAdClicked", eventParams)
361
+ }
362
+
363
+ override fun onAdFailedToShow(error: String) {
364
+ val eventParams = Arguments.createMap()
365
+ eventParams.putString("placementId", placementId)
366
+ eventParams.putString("errorCode", "SHOW_FAILED")
367
+ eventParams.putString("errorMessage", error)
368
+ sendEvent("BigCrunchRewardedAdFailedToShow", eventParams)
369
+ }
370
+ }
371
+
372
+ BigCrunchRewarded.show(activity, placementId, callback)
373
+ promise.resolve(null)
374
+ } catch (e: Exception) {
375
+ promise.reject("SHOW_ERROR", "Failed to show rewarded: ${e.message}", e)
376
+ }
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Check if rewarded is loaded
382
+ */
383
+ @ReactMethod
384
+ fun isRewardedLoaded(placementId: String, promise: Promise) {
385
+ promise.resolve(BigCrunchRewarded.isLoaded(placementId))
386
+ }
387
+
388
+ /**
389
+ * Destroy rewarded
390
+ */
391
+ @ReactMethod
392
+ fun destroyRewarded(placementId: String, promise: Promise) {
393
+ try {
394
+ BigCrunchRewarded.destroy(placementId)
395
+ rewardedCache.remove(placementId)
396
+ promise.resolve(null)
397
+ } catch (e: Exception) {
398
+ promise.reject("DESTROY_ERROR", "Failed to destroy rewarded: ${e.message}", e)
399
+ }
400
+ }
401
+
402
+ /**
403
+ * Get session info
404
+ */
405
+ @ReactMethod
406
+ fun getSessionInfo(promise: Promise) {
407
+ scope.launch {
408
+ try {
409
+ val sessionInfo = BigCrunchAds.getSessionInfo()
410
+ promise.resolve(convertSessionInfoToMap(sessionInfo))
411
+ } catch (e: Exception) {
412
+ promise.reject("SESSION_ERROR", "Failed to get session info: ${e.message}", e)
413
+ }
414
+ }
415
+ }
416
+
417
+ /**
418
+ * Start new session
419
+ */
420
+ @ReactMethod
421
+ fun startNewSession(promise: Promise) {
422
+ scope.launch {
423
+ try {
424
+ BigCrunchAds.startNewSession()
425
+ promise.resolve(null)
426
+ } catch (e: Exception) {
427
+ promise.reject("SESSION_ERROR", "Failed to start new session: ${e.message}", e)
428
+ }
429
+ }
430
+ }
431
+
432
+ /**
433
+ * Get device context
434
+ */
435
+ @ReactMethod
436
+ fun getDeviceContext(promise: Promise) {
437
+ scope.launch {
438
+ try {
439
+ val deviceData = BigCrunchAds.getDeviceData()
440
+ promise.resolve(convertDeviceDataToMap(deviceData))
441
+ } catch (e: Exception) {
442
+ promise.reject("DEVICE_ERROR", "Failed to get device data: ${e.message}", e)
443
+ }
444
+ }
445
+ }
446
+
447
+ /**
448
+ * Set GDPR consent
449
+ */
450
+ @ReactMethod
451
+ fun setGdprConsent(consent: String, promise: Promise) {
452
+ try {
453
+ BigCrunchAds.setGdprConsent(consent)
454
+ promise.resolve(null)
455
+ } catch (e: Exception) {
456
+ promise.reject("PRIVACY_ERROR", "Failed to set GDPR consent: ${e.message}", e)
457
+ }
458
+ }
459
+
460
+ /**
461
+ * Set CCPA string
462
+ */
463
+ @ReactMethod
464
+ fun setCcpaString(ccpaString: String, promise: Promise) {
465
+ try {
466
+ BigCrunchAds.setCcpaString(ccpaString)
467
+ promise.resolve(null)
468
+ } catch (e: Exception) {
469
+ promise.reject("PRIVACY_ERROR", "Failed to set CCPA string: ${e.message}", e)
470
+ }
471
+ }
472
+
473
+ /**
474
+ * Set COPPA compliant
475
+ */
476
+ @ReactMethod
477
+ fun setCoppaCompliant(isCompliant: Boolean, promise: Promise) {
478
+ try {
479
+ BigCrunchAds.setCoppaCompliant(isCompliant)
480
+ promise.resolve(null)
481
+ } catch (e: Exception) {
482
+ promise.reject("PRIVACY_ERROR", "Failed to set COPPA compliance: ${e.message}", e)
483
+ }
484
+ }
485
+
486
+ /**
487
+ * Set debug mode
488
+ */
489
+ @ReactMethod
490
+ fun setDebugMode(enabled: Boolean, promise: Promise) {
491
+ try {
492
+ BigCrunchAds.setDebugMode(enabled)
493
+ promise.resolve(null)
494
+ } catch (e: Exception) {
495
+ promise.reject("DEBUG_ERROR", "Failed to set debug mode: ${e.message}", e)
496
+ }
497
+ }
498
+
499
+ /**
500
+ * Add test device
501
+ */
502
+ @ReactMethod
503
+ fun addTestDevice(deviceId: String, promise: Promise) {
504
+ try {
505
+ BigCrunchAds.addTestDevice(deviceId)
506
+ promise.resolve(null)
507
+ } catch (e: Exception) {
508
+ promise.reject("TEST_ERROR", "Failed to add test device: ${e.message}", e)
509
+ }
510
+ }
511
+
512
+ /**
513
+ * Remove test device
514
+ */
515
+ @ReactMethod
516
+ fun removeTestDevice(deviceId: String, promise: Promise) {
517
+ try {
518
+ BigCrunchAds.removeTestDevice(deviceId)
519
+ promise.resolve(null)
520
+ } catch (e: Exception) {
521
+ promise.reject("TEST_ERROR", "Failed to remove test device: ${e.message}", e)
522
+ }
523
+ }
524
+
525
+ /**
526
+ * Get test devices
527
+ */
528
+ @ReactMethod
529
+ fun getTestDevices(promise: Promise) {
530
+ try {
531
+ val devices = BigCrunchAds.getTestDevices()
532
+ promise.resolve(Arguments.fromList(devices))
533
+ } catch (e: Exception) {
534
+ promise.reject("TEST_ERROR", "Failed to get test devices: ${e.message}", e)
535
+ }
536
+ }
537
+
538
+ /**
539
+ * Add event listener (required for NativeEventEmitter)
540
+ */
541
+ @ReactMethod
542
+ fun addListener(eventName: String) {
543
+ // Keep track of listeners if needed
544
+ // This is required for NativeEventEmitter to work properly
545
+ }
546
+
547
+ /**
548
+ * Remove event listeners (required for NativeEventEmitter)
549
+ */
550
+ @ReactMethod
551
+ fun removeListeners(count: Int) {
552
+ // Remove listeners if needed
553
+ // This is required for NativeEventEmitter to work properly
554
+ }
555
+
556
+ /**
557
+ * Send event to JavaScript
558
+ */
559
+ private fun sendEvent(eventName: String, params: WritableMap?) {
560
+ reactApplicationContext
561
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
562
+ .emit(eventName, params)
563
+ }
564
+
565
+ // Helper conversion methods
566
+ private fun convertAppConfigToMap(config: AppConfig): WritableMap {
567
+ val map = Arguments.createMap()
568
+ map.putString("propertyId", config.propertyId)
569
+ map.putString("appName", config.appName)
570
+
571
+ val placements = Arguments.createArray()
572
+ config.placements.forEach { placement ->
573
+ placements.pushMap(convertPlacementConfigToMap(placement))
574
+ }
575
+ map.putArray("placements", placements)
576
+
577
+ return map
578
+ }
579
+
580
+ private fun convertPlacementConfigToMap(config: PlacementConfig): WritableMap {
581
+ val map = Arguments.createMap()
582
+ map.putString("placementId", config.placementId)
583
+ map.putString("format", config.format)
584
+ map.putString("gamAdUnit", config.gamAdUnit)
585
+
586
+ // Add sizes array if available
587
+ config.sizes?.let { sizes ->
588
+ val sizesArray = Arguments.createArray()
589
+ for (size in sizes) {
590
+ val sizeMap = Arguments.createMap()
591
+ sizeMap.putInt("width", size.width)
592
+ sizeMap.putInt("height", size.height)
593
+ sizesArray.pushMap(sizeMap)
594
+ }
595
+ map.putArray("sizes", sizesArray)
596
+ }
597
+
598
+ // Add Prebid config ID if available
599
+ config.prebidConfigId?.let {
600
+ map.putString("prebidConfigId", it)
601
+ }
602
+
603
+ // Add refresh config if available
604
+ config.refresh?.let { refresh ->
605
+ val refreshMap = Arguments.createMap()
606
+ refreshMap.putBoolean("enabled", refresh.enabled)
607
+ refreshMap.putInt("intervalMs", refresh.intervalMs)
608
+ refresh.maxRefreshes?.let { refreshMap.putInt("maxRefreshes", it) }
609
+ map.putMap("refresh", refreshMap)
610
+ }
611
+
612
+ return map
613
+ }
614
+
615
+ private fun convertSessionInfoToMap(info: SessionInfo): WritableMap {
616
+ val map = Arguments.createMap()
617
+ map.putString("sessionId", info.sessionId)
618
+ map.putString("startTime", info.startTime) // Changed from toDouble() - now ISO 8601 string
619
+ map.putInt("screenViewCount", info.screenViewCount)
620
+ map.putInt("adRequestCount", info.adRequestCount)
621
+ map.putInt("adImpressionCount", info.adImpressionCount)
622
+ map.putDouble("totalRevenueMicros", info.totalRevenueMicros.toDouble())
623
+ return map
624
+ }
625
+
626
+ private fun convertDeviceDataToMap(data: DeviceData): WritableMap {
627
+ val map = Arguments.createMap()
628
+ map.putString("deviceId", data.deviceId)
629
+ map.putString("deviceModel", data.deviceModel)
630
+ map.putString("osVersion", data.osVersion)
631
+ map.putString("appVersion", data.appVersion)
632
+ map.putInt("screenWidth", data.screenWidth)
633
+ map.putInt("screenHeight", data.screenHeight)
634
+ map.putString("language", data.language)
635
+ map.putString("country", data.country)
636
+ map.putBoolean("isTablet", data.isTablet)
637
+ data.carrier?.let { map.putString("carrier", it) }
638
+ data.networkType?.let { map.putString("networkType", it) }
639
+ return map
640
+ }
641
+
642
+ private fun convertMapToStringMap(map: ReadableMap): Map<String, String> {
643
+ val result = mutableMapOf<String, String>()
644
+ val iterator = map.keySetIterator()
645
+ while (iterator.hasNextKey()) {
646
+ val key = iterator.nextKey()
647
+ map.getString(key)?.let { value ->
648
+ result[key] = value
649
+ }
650
+ }
651
+ return result
652
+ }
653
+ }
@@ -0,0 +1,20 @@
1
+ package com.bigcrunch.ads.react
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+ /**
9
+ * React Native package for BigCrunch Ads SDK
10
+ */
11
+ class BigCrunchAdsPackage : ReactPackage {
12
+
13
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
14
+ return listOf(BigCrunchAdsModule(reactContext))
15
+ }
16
+
17
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
18
+ return listOf(BigCrunchBannerViewManager())
19
+ }
20
+ }