@bigcrunch/react-native-ads 0.3.1 → 0.5.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 (64) hide show
  1. package/README.md +5 -5
  2. package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchAds.kt +434 -0
  3. package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchBannerView.kt +484 -0
  4. package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchInterstitial.kt +403 -0
  5. package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchRewarded.kt +409 -0
  6. package/android/bigcrunch-ads/com/bigcrunch/ads/adapters/GoogleAdsAdapter.kt +592 -0
  7. package/android/bigcrunch-ads/com/bigcrunch/ads/core/AdOrchestrator.kt +623 -0
  8. package/android/bigcrunch-ads/com/bigcrunch/ads/core/AnalyticsClient.kt +719 -0
  9. package/android/bigcrunch-ads/com/bigcrunch/ads/core/BidRequestClient.kt +364 -0
  10. package/android/bigcrunch-ads/com/bigcrunch/ads/core/ConfigManager.kt +301 -0
  11. package/android/bigcrunch-ads/com/bigcrunch/ads/core/DeviceContext.kt +385 -0
  12. package/android/bigcrunch-ads/com/bigcrunch/ads/core/RewardedCallback.kt +42 -0
  13. package/android/bigcrunch-ads/com/bigcrunch/ads/core/SessionManager.kt +330 -0
  14. package/android/bigcrunch-ads/com/bigcrunch/ads/internal/DeviceHelper.kt +60 -0
  15. package/android/bigcrunch-ads/com/bigcrunch/ads/internal/HttpClient.kt +114 -0
  16. package/android/bigcrunch-ads/com/bigcrunch/ads/internal/Logger.kt +71 -0
  17. package/android/bigcrunch-ads/com/bigcrunch/ads/internal/PrivacyStore.kt +125 -0
  18. package/android/bigcrunch-ads/com/bigcrunch/ads/internal/Storage.kt +88 -0
  19. package/android/bigcrunch-ads/com/bigcrunch/ads/listeners/BannerAdListener.kt +55 -0
  20. package/android/bigcrunch-ads/com/bigcrunch/ads/listeners/InterstitialAdListener.kt +55 -0
  21. package/android/bigcrunch-ads/com/bigcrunch/ads/listeners/RewardedAdListener.kt +58 -0
  22. package/android/bigcrunch-ads/com/bigcrunch/ads/models/AdEvent.kt +880 -0
  23. package/android/bigcrunch-ads/com/bigcrunch/ads/models/AppConfig.kt +90 -0
  24. package/android/bigcrunch-ads/com/bigcrunch/ads/models/DeviceData.kt +18 -0
  25. package/android/bigcrunch-ads/com/bigcrunch/ads/models/PlacementConfig.kt +70 -0
  26. package/android/bigcrunch-ads/com/bigcrunch/ads/models/SessionInfo.kt +21 -0
  27. package/android/build.gradle +22 -10
  28. package/android/settings.gradle +2 -6
  29. package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchAdsModule.kt +0 -23
  30. package/ios/BigCrunchAds/Sources/Adapters/GoogleAdsAdapter.swift +512 -0
  31. package/ios/BigCrunchAds/Sources/BigCrunchAds.swift +387 -0
  32. package/ios/BigCrunchAds/Sources/BigCrunchBannerView.swift +448 -0
  33. package/ios/BigCrunchAds/Sources/BigCrunchInterstitial.swift +412 -0
  34. package/ios/BigCrunchAds/Sources/BigCrunchRewarded.swift +523 -0
  35. package/ios/BigCrunchAds/Sources/Core/AdOrchestrator.swift +514 -0
  36. package/ios/BigCrunchAds/Sources/Core/AnalyticsClient.swift +874 -0
  37. package/ios/BigCrunchAds/Sources/Core/BidRequestClient.swift +344 -0
  38. package/ios/BigCrunchAds/Sources/Core/ConfigManager.swift +306 -0
  39. package/ios/BigCrunchAds/Sources/Core/DeviceContext.swift +284 -0
  40. package/ios/BigCrunchAds/Sources/Core/SessionManager.swift +392 -0
  41. package/ios/BigCrunchAds/Sources/Internal/HTTPClient.swift +146 -0
  42. package/ios/BigCrunchAds/Sources/Internal/Logger.swift +62 -0
  43. package/ios/BigCrunchAds/Sources/Internal/PrivacyStore.swift +129 -0
  44. package/ios/BigCrunchAds/Sources/Internal/Storage.swift +73 -0
  45. package/ios/BigCrunchAds/Sources/Models/AdEvent.swift +784 -0
  46. package/ios/BigCrunchAds/Sources/Models/AppConfig.swift +100 -0
  47. package/ios/BigCrunchAds/Sources/Models/DeviceData.swift +68 -0
  48. package/ios/BigCrunchAds/Sources/Models/PlacementConfig.swift +137 -0
  49. package/ios/BigCrunchAds/Sources/Models/SessionInfo.swift +48 -0
  50. package/ios/BigCrunchAdsModule.swift +5 -14
  51. package/ios/BigCrunchBannerViewManager.swift +0 -1
  52. package/lib/index.d.ts +1 -1
  53. package/lib/index.d.ts.map +1 -1
  54. package/lib/index.js +3 -2
  55. package/lib/types/config.d.ts +22 -9
  56. package/lib/types/config.d.ts.map +1 -1
  57. package/lib/types/events.d.ts +4 -4
  58. package/lib/types/events.d.ts.map +1 -1
  59. package/package.json +11 -4
  60. package/react-native-bigcrunch-ads.podspec +1 -3
  61. package/scripts/inject-version.js +55 -0
  62. package/src/index.ts +3 -2
  63. package/src/types/config.ts +23 -9
  64. package/src/types/events.ts +4 -4
@@ -0,0 +1,523 @@
1
+ import UIKit
2
+ import GoogleMobileAds
3
+
4
+ /**
5
+ * BigCrunch Rewarded Ads - Static API for rewarded video ads
6
+ *
7
+ * Rewarded ads are full-screen ads that reward users for watching video content.
8
+ * Users opt-in to watch the ad in exchange for in-app rewards.
9
+ *
10
+ * Usage:
11
+ * ```swift
12
+ * // 1. Preload the ad (do this early, e.g., when entering a screen)
13
+ * BigCrunchRewarded.preload(placementId: "rewarded_video") { result in
14
+ * switch result {
15
+ * case .success:
16
+ * print("Ad ready to show")
17
+ * case .failure(let error):
18
+ * print("Failed to load: \(error)")
19
+ * }
20
+ * }
21
+ *
22
+ * // 2. Check if ready (optional)
23
+ * if BigCrunchRewarded.isReady(placementId: "rewarded_video") {
24
+ * // Ad is ready to show
25
+ * }
26
+ *
27
+ * // 3. Show when user opts in
28
+ * BigCrunchRewarded.show(
29
+ * from: self,
30
+ * placementId: "rewarded_video",
31
+ * delegate: self
32
+ * )
33
+ * ```
34
+ *
35
+ * Implement BigCrunchRewardedDelegate for events:
36
+ * ```swift
37
+ * extension ViewController: BigCrunchRewardedDelegate {
38
+ * func rewardedDidShow(placementId: String) { }
39
+ * func rewardedDidDismiss(placementId: String) { }
40
+ * func rewardedDidClick(placementId: String) { }
41
+ * func rewardedDidFail(placementId: String, error: String) { }
42
+ * func rewardedDidEarnReward(placementId: String, type: String, amount: Int) {
43
+ * // Grant the reward to the user
44
+ * }
45
+ * }
46
+ * ```
47
+ */
48
+ public final class BigCrunchRewarded {
49
+
50
+ private static let TAG = "BigCrunchRewarded"
51
+
52
+ // Cache for preloaded rewarded ads
53
+ private static var rewardedCache: [String: RewardedAd] = [:]
54
+ private static let cacheLock = NSLock()
55
+
56
+ // Store delegates to prevent deallocation during show
57
+ private static var activeDelegates: [String: RewardedDelegateWrapper] = [:]
58
+ private static let delegateLock = NSLock()
59
+
60
+ // Private initializer to prevent instantiation
61
+ private init() {}
62
+
63
+ // MARK: - Legacy Callback Protocol
64
+
65
+ /**
66
+ * Legacy callback protocol for rewarded ad events
67
+ */
68
+ public protocol Callback {
69
+ func onUserEarnedReward(type: String, amount: Int)
70
+ func onAdDismissed()
71
+ func onAdFailed(error: String)
72
+ }
73
+
74
+ // MARK: - Preload Methods
75
+
76
+ /**
77
+ * Preload a rewarded ad for the given placement
78
+ *
79
+ * Call this early (e.g., when entering a screen) to give the ad time to load.
80
+ *
81
+ * - Parameters:
82
+ * - placementId: The placement ID from BigCrunch dashboard
83
+ * - completion: Optional completion handler called when preload finishes
84
+ */
85
+ public static func preload(
86
+ placementId: String,
87
+ completion: ((Result<Void, Error>) -> Void)? = nil
88
+ ) {
89
+ BCLogger.debug("\(TAG): Preloading rewarded: \(placementId)")
90
+
91
+ BigCrunchAds.requireInitialized()
92
+
93
+ guard !placementId.isEmpty else {
94
+ BCLogger.error("\(TAG): Invalid placementId: cannot be empty")
95
+ completion?(.failure(BigCrunchError.invalidPlacement("placementId cannot be empty")))
96
+ return
97
+ }
98
+
99
+ // Check if already cached
100
+ cacheLock.lock()
101
+ if rewardedCache[placementId] != nil {
102
+ cacheLock.unlock()
103
+ BCLogger.debug("\(TAG): Rewarded already cached: \(placementId)")
104
+ completion?(.success(()))
105
+ return
106
+ }
107
+ cacheLock.unlock()
108
+
109
+ // Get placement config
110
+ let configManager = BigCrunchAds.getConfigManager()
111
+ guard let placement = configManager.getPlacement(placementId) else {
112
+ BCLogger.error("\(TAG): Placement not found: \(placementId)")
113
+ completion?(.failure(BigCrunchError.invalidPlacement("Placement not found: \(placementId)")))
114
+ return
115
+ }
116
+
117
+ guard placement.format == "rewarded" else {
118
+ BCLogger.error("\(TAG): Invalid format for rewarded: \(placement.format)")
119
+ completion?(.failure(BigCrunchError.invalidPlacement("Invalid placement format: \(placement.format)")))
120
+ return
121
+ }
122
+
123
+ // Track ad request
124
+ let analyticsClient = BigCrunchAds.getAnalyticsClient()
125
+ analyticsClient.trackAdRequest(placementId: placementId, format: placement.format)
126
+
127
+ // Load the rewarded ad
128
+ Task {
129
+ await loadRewardedAsync(
130
+ placement: placement,
131
+ configManager: configManager,
132
+ analyticsClient: analyticsClient,
133
+ completion: completion
134
+ )
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Preload a rewarded ad (simplified version without completion)
140
+ *
141
+ * - Parameter placementId: The placement ID from BigCrunch dashboard
142
+ */
143
+ public static func preload(placementId: String) {
144
+ preload(placementId: placementId, completion: nil)
145
+ }
146
+
147
+ private static func loadRewardedAsync(
148
+ placement: PlacementConfig,
149
+ configManager: ConfigManager,
150
+ analyticsClient: AnalyticsClient,
151
+ completion: ((Result<Void, Error>) -> Void)?
152
+ ) async {
153
+ // Get GAM network code from config
154
+ guard let gamNetworkCode = configManager.getGamNetworkCode() else {
155
+ BCLogger.error("\(TAG): GAM network code not available")
156
+ await MainActor.run {
157
+ completion?(.failure(BigCrunchError.loadFailed("Config not loaded")))
158
+ }
159
+ return
160
+ }
161
+
162
+ // Build ad unit ID
163
+ let adUnitID: String
164
+ if gamNetworkCode.isEmpty {
165
+ adUnitID = placement.gamAdUnit
166
+ } else {
167
+ adUnitID = "/\(gamNetworkCode)/\(placement.gamAdUnit)"
168
+ }
169
+
170
+ // Create ad request
171
+ let request = Request()
172
+
173
+ // Fetch S2S demand
174
+ if let bidRequestClient = BigCrunchAds.getBidRequestClient() {
175
+ let targeting = await bidRequestClient.fetchDemand(placement: placement)
176
+ if let targeting = targeting, !targeting.isEmpty {
177
+ var customTargeting = request.customTargeting ?? [:]
178
+ for (key, value) in targeting {
179
+ customTargeting[key] = value
180
+ }
181
+ request.customTargeting = customTargeting
182
+ BCLogger.debug("\(TAG): S2S demand fetched for: \(placement.placementId) (\(targeting.count) keys)")
183
+ } else {
184
+ BCLogger.warning("\(TAG): S2S demand fetch returned no targeting, continuing with Google only")
185
+ }
186
+ }
187
+
188
+ // Load Google rewarded ad
189
+ await withCheckedContinuation { (continuation: CheckedContinuation<Void, Never>) in
190
+ RewardedAd.load(
191
+ with: adUnitID,
192
+ request: request
193
+ ) { rewardedAd, error in
194
+ if let error = error {
195
+ BCLogger.warning("\(TAG): Rewarded ad failed to load: \(error.localizedDescription)")
196
+ Task { @MainActor in
197
+ completion?(.failure(BigCrunchError.loadFailed(error.localizedDescription)))
198
+ }
199
+ continuation.resume()
200
+ return
201
+ }
202
+
203
+ guard let rewardedAd = rewardedAd else {
204
+ BCLogger.warning("\(TAG): Rewarded ad loaded but was nil")
205
+ Task { @MainActor in
206
+ completion?(.failure(BigCrunchError.loadFailed("Rewarded ad was nil")))
207
+ }
208
+ continuation.resume()
209
+ return
210
+ }
211
+
212
+ BCLogger.debug("\(TAG): Rewarded ad loaded: \(placement.placementId)")
213
+
214
+ // Set up paid event handler for ILRD
215
+ rewardedAd.paidEventHandler = { adValue in
216
+ BCLogger.debug("\(TAG): Rewarded paid event: \(adValue.value) \(adValue.currencyCode)")
217
+ let valueMicros = adValue.value.multiplying(by: NSDecimalNumber(value: 1_000_000))
218
+ analyticsClient.trackAdRevenue(
219
+ placementId: placement.placementId,
220
+ format: placement.format,
221
+ valueMicros: valueMicros.int64Value,
222
+ currency: adValue.currencyCode
223
+ )
224
+ }
225
+
226
+ // Cache the ad
227
+ cacheLock.lock()
228
+ rewardedCache[placement.placementId] = rewardedAd
229
+ cacheLock.unlock()
230
+
231
+ Task { @MainActor in
232
+ completion?(.success(()))
233
+ }
234
+ continuation.resume()
235
+ }
236
+ }
237
+ }
238
+
239
+ // MARK: - Show Methods
240
+
241
+ /**
242
+ * Show a preloaded rewarded ad
243
+ *
244
+ * The ad must be preloaded first using `preload(placementId:)`. Check `isReady(placementId:)`
245
+ * before calling this to ensure an ad is available.
246
+ *
247
+ * - Parameters:
248
+ * - viewController: The view controller to present the ad from
249
+ * - placementId: The placement ID
250
+ * - delegate: Optional delegate for ad events
251
+ * - Returns: true if an ad was available and will be shown, false otherwise
252
+ */
253
+ @discardableResult
254
+ public static func show(
255
+ from viewController: UIViewController,
256
+ placementId: String,
257
+ delegate: BigCrunchRewardedDelegate? = nil
258
+ ) -> Bool {
259
+ BCLogger.debug("\(TAG): Showing rewarded: \(placementId)")
260
+
261
+ BigCrunchAds.requireInitialized()
262
+
263
+ guard !placementId.isEmpty else {
264
+ BCLogger.error("\(TAG): Invalid placementId: cannot be empty")
265
+ delegate?.rewardedDidFail(placementId: placementId, error: "Invalid placementId")
266
+ return false
267
+ }
268
+
269
+ // Get cached rewarded ad
270
+ cacheLock.lock()
271
+ guard let rewardedAd = rewardedCache.removeValue(forKey: placementId) else {
272
+ cacheLock.unlock()
273
+ BCLogger.warning("\(TAG): No preloaded rewarded for: \(placementId)")
274
+ delegate?.rewardedDidFail(placementId: placementId, error: "No preloaded ad available")
275
+ return false
276
+ }
277
+ cacheLock.unlock()
278
+
279
+ // Get placement config for analytics
280
+ let configManager = BigCrunchAds.getConfigManager()
281
+ guard let placement = configManager.getPlacement(placementId) else {
282
+ BCLogger.error("\(TAG): Placement not found: \(placementId)")
283
+ delegate?.rewardedDidFail(placementId: placementId, error: "Placement not found")
284
+ return false
285
+ }
286
+
287
+ // Create and store delegate wrapper
288
+ let analyticsClient = BigCrunchAds.getAnalyticsClient()
289
+ let wrapper = RewardedDelegateWrapper(
290
+ placementId: placementId,
291
+ placementConfig: placement,
292
+ analyticsClient: analyticsClient,
293
+ delegate: delegate
294
+ ) { pid in
295
+ // Cleanup delegate wrapper after ad is dismissed or fails
296
+ delegateLock.lock()
297
+ activeDelegates.removeValue(forKey: pid)
298
+ delegateLock.unlock()
299
+ }
300
+
301
+ delegateLock.lock()
302
+ activeDelegates[placementId] = wrapper
303
+ delegateLock.unlock()
304
+
305
+ rewardedAd.fullScreenContentDelegate = wrapper
306
+
307
+ // Present the ad
308
+ rewardedAd.present(from: viewController) {
309
+ // User earned reward
310
+ let reward = rewardedAd.adReward
311
+ BCLogger.debug("\(TAG): User earned reward: \(reward.amount) \(reward.type)")
312
+ delegate?.rewardedDidEarnReward(
313
+ placementId: placementId,
314
+ type: reward.type,
315
+ amount: reward.amount.intValue
316
+ )
317
+ }
318
+
319
+ return true
320
+ }
321
+
322
+ /**
323
+ * Show a preloaded rewarded ad (legacy API)
324
+ *
325
+ * - Parameters:
326
+ * - viewController: The view controller to present the ad from
327
+ * - placementId: The placement ID
328
+ * - callback: Legacy callback for ad events
329
+ */
330
+ public static func show(
331
+ viewController: UIViewController,
332
+ placementId: String,
333
+ callback: Callback? = nil
334
+ ) {
335
+ let delegate: BigCrunchRewardedDelegate? = callback.map { cb in
336
+ LegacyRewardedCallbackAdapter(callback: cb)
337
+ }
338
+ show(from: viewController, placementId: placementId, delegate: delegate)
339
+ }
340
+
341
+ // MARK: - Query Methods
342
+
343
+ /**
344
+ * Check if a rewarded ad is ready to show
345
+ *
346
+ * - Parameter placementId: The placement ID
347
+ * - Returns: true if an ad is preloaded and ready to show
348
+ */
349
+ public static func isReady(placementId: String) -> Bool {
350
+ cacheLock.lock()
351
+ defer { cacheLock.unlock() }
352
+ return rewardedCache[placementId] != nil
353
+ }
354
+
355
+ /**
356
+ * Clear all cached rewarded ads
357
+ *
358
+ * Call this to free up memory when ads are no longer needed.
359
+ */
360
+ public static func clearCache() {
361
+ BCLogger.debug("\(TAG): Clearing rewarded cache")
362
+ cacheLock.lock()
363
+ rewardedCache.removeAll()
364
+ cacheLock.unlock()
365
+ }
366
+
367
+ // MARK: - Testing Support
368
+
369
+ internal static func resetForTesting() {
370
+ cacheLock.lock()
371
+ rewardedCache.removeAll()
372
+ cacheLock.unlock()
373
+
374
+ delegateLock.lock()
375
+ activeDelegates.removeAll()
376
+ delegateLock.unlock()
377
+ }
378
+ }
379
+
380
+ // MARK: - Delegate Protocol
381
+
382
+ /**
383
+ * Delegate protocol for BigCrunchRewarded events
384
+ */
385
+ public protocol BigCrunchRewardedDelegate: AnyObject {
386
+ /**
387
+ * Called when the rewarded ad is displayed on screen
388
+ */
389
+ func rewardedDidShow(placementId: String)
390
+
391
+ /**
392
+ * Called when the rewarded ad is dismissed by the user
393
+ */
394
+ func rewardedDidDismiss(placementId: String)
395
+
396
+ /**
397
+ * Called when the user clicks on the rewarded ad
398
+ */
399
+ func rewardedDidClick(placementId: String)
400
+
401
+ /**
402
+ * Called when the rewarded ad fails to show
403
+ */
404
+ func rewardedDidFail(placementId: String, error: String)
405
+
406
+ /**
407
+ * Called when the user earns a reward
408
+ *
409
+ * - Parameters:
410
+ * - placementId: The placement ID
411
+ * - type: The reward type (e.g., "coins", "points")
412
+ * - amount: The reward amount
413
+ */
414
+ func rewardedDidEarnReward(placementId: String, type: String, amount: Int)
415
+ }
416
+
417
+ // MARK: - Default Implementations
418
+
419
+ public extension BigCrunchRewardedDelegate {
420
+ func rewardedDidShow(placementId: String) {}
421
+ func rewardedDidDismiss(placementId: String) {}
422
+ func rewardedDidClick(placementId: String) {}
423
+ func rewardedDidFail(placementId: String, error: String) {}
424
+ func rewardedDidEarnReward(placementId: String, type: String, amount: Int) {}
425
+ }
426
+
427
+ // MARK: - Private Helper Classes
428
+
429
+ private class RewardedDelegateWrapper: NSObject, FullScreenContentDelegate {
430
+ let placementId: String
431
+ let placementConfig: PlacementConfig
432
+ let analyticsClient: AnalyticsClient
433
+ weak var delegate: BigCrunchRewardedDelegate?
434
+ let cleanup: (String) -> Void
435
+
436
+ init(
437
+ placementId: String,
438
+ placementConfig: PlacementConfig,
439
+ analyticsClient: AnalyticsClient,
440
+ delegate: BigCrunchRewardedDelegate?,
441
+ cleanup: @escaping (String) -> Void
442
+ ) {
443
+ self.placementId = placementId
444
+ self.placementConfig = placementConfig
445
+ self.analyticsClient = analyticsClient
446
+ self.delegate = delegate
447
+ self.cleanup = cleanup
448
+ }
449
+
450
+ func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
451
+ BCLogger.debug("BigCrunchRewarded: Rewarded ad shown: \(placementId)")
452
+
453
+ // Extract GAM metadata from ResponseInfo
454
+ if let rewardedAd = ad as? RewardedAd {
455
+ let responseInfo = rewardedAd.responseInfo
456
+ let adMetadata = GoogleAdsAdapter.extractAdMetadata(from: responseInfo)
457
+
458
+ analyticsClient.trackAdImpression(
459
+ placementId: placementConfig.placementId,
460
+ format: placementConfig.format,
461
+ advertiserId: adMetadata["advertiser_id"] as? String,
462
+ campaignId: adMetadata["campaign_id"] as? String,
463
+ lineItemId: adMetadata["line_item_id"] as? String,
464
+ creativeId: adMetadata["creative_id"] as? String
465
+ )
466
+ }
467
+
468
+ delegate?.rewardedDidShow(placementId: placementId)
469
+ }
470
+
471
+ func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
472
+ BCLogger.debug("BigCrunchRewarded: Rewarded ad dismissed: \(placementId)")
473
+ delegate?.rewardedDidDismiss(placementId: placementId)
474
+ cleanup(placementId)
475
+ }
476
+
477
+ func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
478
+ BCLogger.warning("BigCrunchRewarded: Rewarded ad failed to show: \(error.localizedDescription)")
479
+ delegate?.rewardedDidFail(placementId: placementId, error: error.localizedDescription)
480
+ cleanup(placementId)
481
+ }
482
+
483
+ func adDidRecordClick(_ ad: FullScreenPresentingAd) {
484
+ BCLogger.debug("BigCrunchRewarded: Rewarded ad clicked: \(placementId)")
485
+ analyticsClient.trackAdClick(
486
+ placementId: placementConfig.placementId,
487
+ format: placementConfig.format
488
+ )
489
+ delegate?.rewardedDidClick(placementId: placementId)
490
+ }
491
+
492
+ func adDidRecordImpression(_ ad: FullScreenPresentingAd) {
493
+ BCLogger.debug("BigCrunchRewarded: Rewarded ad impression: \(placementId)")
494
+ }
495
+ }
496
+
497
+ private class LegacyRewardedCallbackAdapter: BigCrunchRewardedDelegate {
498
+ let callback: BigCrunchRewarded.Callback
499
+
500
+ init(callback: BigCrunchRewarded.Callback) {
501
+ self.callback = callback
502
+ }
503
+
504
+ func rewardedDidShow(placementId: String) {
505
+ // Not in legacy callback
506
+ }
507
+
508
+ func rewardedDidDismiss(placementId: String) {
509
+ callback.onAdDismissed()
510
+ }
511
+
512
+ func rewardedDidClick(placementId: String) {
513
+ // Not in legacy callback
514
+ }
515
+
516
+ func rewardedDidFail(placementId: String, error: String) {
517
+ callback.onAdFailed(error: error)
518
+ }
519
+
520
+ func rewardedDidEarnReward(placementId: String, type: String, amount: Int) {
521
+ callback.onUserEarnedReward(type: type, amount: amount)
522
+ }
523
+ }