@bigcrunch/react-native-ads 0.9.0 → 0.11.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.
@@ -120,17 +120,21 @@ internal class GoogleAdsAdapter(
120
120
  * Resolve a BigCrunch AdSize to a Google AdSize.
121
121
  * For adaptive sizes, calculates the optimal ad size based on screen width.
122
122
  */
123
+ /**
124
+ * Resolve a BigCrunch AdSize to a Google AdSize.
125
+ * A 0x0 size is always treated as adaptive since it is never valid as a fixed size.
126
+ */
123
127
  private fun resolveGoogleAdSize(
124
128
  bcAdSize: com.bigcrunch.ads.models.AdSize
125
129
  ): AdSize {
126
- if (bcAdSize.isAdaptive) {
130
+ if (bcAdSize.isAdaptive || (bcAdSize.width == 0 && bcAdSize.height == 0)) {
127
131
  val widthDp = if (bcAdSize.width > 0) {
128
132
  bcAdSize.width
129
133
  } else {
130
134
  val displayMetrics = context.resources.displayMetrics
131
135
  (displayMetrics.widthPixels / displayMetrics.density).toInt()
132
136
  }
133
- BCLogger.d(TAG, "Resolving adaptive banner with width: ${widthDp}dp")
137
+ BCLogger.d(TAG, "Resolving adaptive banner with width: ${widthDp}dp (isAdaptive=${bcAdSize.isAdaptive}, original=${bcAdSize.width}x${bcAdSize.height})")
134
138
  return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, widthDp)
135
139
  }
136
140
  return AdSize(bcAdSize.width, bcAdSize.height)
@@ -28,7 +28,7 @@ internal class DeviceContext private constructor(context: Context) {
28
28
 
29
29
  companion object {
30
30
  private const val TAG = "DeviceContext"
31
- internal const val SDK_VERSION = "0.9.0"
31
+ internal const val SDK_VERSION = "0.11.0"
32
32
 
33
33
  @Volatile
34
34
  private var instance: DeviceContext? = null
@@ -94,12 +94,13 @@ internal class GoogleAdsAdapter: NSObject {
94
94
 
95
95
  /// Resolve a BigCrunch AdSize to a Google AdSize.
96
96
  /// For adaptive sizes, calculates the optimal ad size based on screen width.
97
+ /// A 0x0 size is always treated as adaptive since it is never valid as a fixed size.
97
98
  private func resolveGoogleAdSize(_ bcAdSize: AdSize) -> GoogleMobileAds.AdSize {
98
- if bcAdSize.isAdaptive {
99
+ if bcAdSize.isAdaptive || (bcAdSize.width == 0 && bcAdSize.height == 0) {
99
100
  let width: CGFloat = bcAdSize.width > 0
100
101
  ? CGFloat(bcAdSize.width)
101
102
  : UIScreen.main.bounds.width
102
- BCLogger.debug("\(GoogleAdsAdapter.TAG): Resolving adaptive banner with width: \(width)pt")
103
+ BCLogger.debug("\(GoogleAdsAdapter.TAG): Resolving adaptive banner with width: \(width)pt (isAdaptive=\(bcAdSize.isAdaptive), original=\(bcAdSize.width)x\(bcAdSize.height))")
103
104
  return GoogleMobileAds.currentOrientationAnchoredAdaptiveBanner(width: width)
104
105
  }
105
106
  return GoogleMobileAds.adSizeFor(cgSize: CGSize(
@@ -74,7 +74,7 @@ internal final class DeviceContext {
74
74
  // MARK: - SDK Properties
75
75
 
76
76
  /// SDK version
77
- static let SDK_VERSION = "0.9.0"
77
+ static let SDK_VERSION = "0.11.0"
78
78
  let sdkVersion: String = SDK_VERSION
79
79
 
80
80
  /// SDK platform (always "ios")
@@ -1,14 +1,19 @@
1
1
  import Foundation
2
+ import os.log
2
3
 
3
4
  /**
4
5
  * Internal logger for BigCrunch Ads SDK
5
6
  *
6
- * All logs are prefixed with "[BCrunch:LEVEL]" for easy filtering.
7
+ * Uses os_log for unified logging, visible in Console.app and terminal
8
+ * without requiring the Xcode debugger to be attached.
9
+ * All logs use the "BCrunch" subsystem for easy filtering.
7
10
  * Logging can be disabled in production by setting isEnabled = false.
8
11
  * Error logs are always shown regardless of isEnabled flag.
9
12
  */
10
13
  internal class BCLogger {
11
14
 
15
+ private static let log = OSLog(subsystem: "com.bigcrunch.ads", category: "BCrunch")
16
+
12
17
  /**
13
18
  * Enable/disable debug logging
14
19
  * Defaults to false for production builds
@@ -20,7 +25,7 @@ internal class BCLogger {
20
25
  */
21
26
  static func verbose(_ message: String) {
22
27
  if isEnabled {
23
- print("[BCrunch:VERBOSE] \(message)")
28
+ os_log("[BCrunch:VERBOSE] %{public}@", log: log, type: .debug, message)
24
29
  }
25
30
  }
26
31
 
@@ -29,7 +34,7 @@ internal class BCLogger {
29
34
  */
30
35
  static func debug(_ message: String) {
31
36
  if isEnabled {
32
- print("[BCrunch:DEBUG] \(message)")
37
+ os_log("[BCrunch:DEBUG] %{public}@", log: log, type: .debug, message)
33
38
  }
34
39
  }
35
40
 
@@ -38,7 +43,7 @@ internal class BCLogger {
38
43
  */
39
44
  static func info(_ message: String) {
40
45
  if isEnabled {
41
- print("[BCrunch:INFO] \(message)")
46
+ os_log("[BCrunch:INFO] %{public}@", log: log, type: .info, message)
42
47
  }
43
48
  }
44
49
 
@@ -47,7 +52,7 @@ internal class BCLogger {
47
52
  */
48
53
  static func warning(_ message: String) {
49
54
  if isEnabled {
50
- print("[BCrunch:WARNING] \(message)")
55
+ os_log("[BCrunch:WARNING] %{public}@", log: log, type: .default, message)
51
56
  }
52
57
  }
53
58
 
@@ -57,6 +62,6 @@ internal class BCLogger {
57
62
  */
58
63
  static func error(_ message: String) {
59
64
  // Always log errors
60
- print("[BCrunch:ERROR] \(message)")
65
+ os_log("[BCrunch:ERROR] %{public}@", log: log, type: .error, message)
61
66
  }
62
67
  }
@@ -257,6 +257,11 @@ class BigCrunchAdsModule: RCTEventEmitter {
257
257
  useTestAds: useTestAds,
258
258
  callback: callbackBridge
259
259
  )
260
+
261
+ if debug {
262
+ BigCrunchAds.setDebugMode(true)
263
+ }
264
+
260
265
  NSLog("[BigCrunchRNBridge] native initialize() returned, waiting for callback...")
261
266
  }
262
267
  }
@@ -67,7 +67,7 @@ class BigCrunchBannerViewWrapper: UIView {
67
67
  }
68
68
  }
69
69
 
70
- var sizeString: String = "BANNER"
70
+ var sizeString: String = "" // Empty = use config sizes (no override)
71
71
  @objc var customWidth: NSNumber? {
72
72
  didSet {
73
73
  _customWidth = customWidth?.intValue
@@ -151,6 +151,13 @@ class BigCrunchBannerViewWrapper: UIView {
151
151
  func updateAdSize() {
152
152
  guard let bannerView = bannerView else { return }
153
153
 
154
+ // If no explicit size was set (sizeString is empty and no custom dimensions),
155
+ // don't set adSizeOverride — let the native SDK use config sizes
156
+ if sizeString.isEmpty && _customWidth == nil && _customHeight == nil {
157
+ bannerView.adSizeOverride = nil
158
+ return
159
+ }
160
+
154
161
  var googleAdSize: GoogleMobileAds.AdSize
155
162
  var bcAdSize: BCAdSize
156
163
 
@@ -1 +1 @@
1
- {"version":3,"file":"BigCrunchBannerView.d.ts","sourceRoot":"","sources":["../src/BigCrunchBannerView.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAkD,MAAM,OAAO,CAAC;AASvE,OAAO,KAAK,EACV,wBAAwB,EAKzB,MAAM,SAAS,CAAC;AAmBjB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CA+MlE,CAAC;AAGF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"BigCrunchBannerView.d.ts","sourceRoot":"","sources":["../src/BigCrunchBannerView.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAkD,MAAM,OAAO,CAAC;AASvE,OAAO,KAAK,EACV,wBAAwB,EAKzB,MAAM,SAAS,CAAC;AAmBjB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CA6NlE,CAAC;AAGF,eAAe,mBAAmB,CAAC"}
@@ -31,12 +31,18 @@ const NativeBannerView = requireNativeComponent(NATIVE_COMPONENT_NAME);
31
31
  * />
32
32
  * ```
33
33
  */
34
- export const BigCrunchBannerView = ({ placementId, size = 'BANNER', autoLoad = true, refreshInterval = 0, customTargeting, style, onAdLoaded, onAdFailedToLoad, onAdImpression, onAdClicked, onAdOpened, onAdClosed, onAdRevenue, }) => {
34
+ export const BigCrunchBannerView = ({ placementId, size, autoLoad = true, refreshInterval = 0, customTargeting, style, onAdLoaded, onAdFailedToLoad, onAdImpression, onAdClicked, onAdOpened, onAdClosed, onAdRevenue, }) => {
35
35
  const viewRef = useRef(null);
36
36
  const subscriptionsRef = useRef([]);
37
37
  const viewIdRef = useRef(`banner_${placementId}_${Date.now()}`);
38
- // Calculate banner size
38
+ // Calculate banner size for layout
39
+ // When size is undefined, config drives the ad size natively — use adaptive layout
39
40
  const bannerSize = useMemo(() => {
41
+ if (size === undefined) {
42
+ // No explicit size — let backend config drive the ad size
43
+ // Use adaptive layout since config may specify smart/adaptive sizes
44
+ return { width: 0, height: 0, adaptive: true, configDriven: true };
45
+ }
40
46
  if (typeof size === 'object' && 'width' in size && 'height' in size) {
41
47
  // Custom size
42
48
  return size;
@@ -50,8 +56,8 @@ export const BigCrunchBannerView = ({ placementId, size = 'BANNER', autoLoad = t
50
56
  }
51
57
  return dimensions;
52
58
  }
53
- // Default to BANNER size
54
- return BANNER_SIZES.BANNER;
59
+ // Unknown size string — fallback to adaptive layout
60
+ return { width: 0, height: 0, adaptive: true };
55
61
  }, [size]);
56
62
  // Handle native events
57
63
  const handleNativeEvent = useCallback((_eventName, handler) => {
@@ -155,20 +161,28 @@ export const BigCrunchBannerView = ({ placementId, size = 'BANNER', autoLoad = t
155
161
  return StyleSheet.flatten([baseStyle, style]);
156
162
  }, [bannerSize, style]);
157
163
  // Native view props
158
- // Always pass explicit dimensions to the native view
164
+ // Only send size/customWidth/customHeight when explicitly specified by the developer.
165
+ // When omitted, the native SDK uses placement config sizes (e.g., smart/adaptive from backend).
159
166
  const nativeProps = {
160
167
  ref: viewRef,
161
168
  style: containerStyle,
162
169
  placementId,
163
- size: typeof size === 'string' ? size : 'CUSTOM',
164
- // Always pass width and height, even for standard sizes
165
- customWidth: bannerSize.width > 0 ? bannerSize.width : undefined,
166
- customHeight: bannerSize.height > 0 ? bannerSize.height : undefined,
167
170
  autoLoad,
168
171
  refreshInterval,
169
172
  customTargeting,
170
173
  viewId: viewIdRef.current,
171
174
  };
175
+ // Only send size to native when explicitly set by the developer
176
+ if (size !== undefined) {
177
+ if (typeof size === 'string') {
178
+ nativeProps.size = size;
179
+ }
180
+ else if (typeof size === 'object' && 'width' in size && 'height' in size) {
181
+ nativeProps.size = 'CUSTOM';
182
+ nativeProps.customWidth = size.width;
183
+ nativeProps.customHeight = size.height;
184
+ }
185
+ }
172
186
  // Return the native view directly with the container style
173
187
  return React.createElement(NativeBannerView, { ...nativeProps });
174
188
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigcrunch/react-native-ads",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "BigCrunch Mobile Ads SDK for React Native - Simplified in-app advertising with S2S demand and Google Ad Manager",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -51,7 +51,7 @@ const NativeBannerView = requireNativeComponent<any>(NATIVE_COMPONENT_NAME);
51
51
  */
52
52
  export const BigCrunchBannerView: React.FC<BigCrunchBannerViewProps> = ({
53
53
  placementId,
54
- size = 'BANNER',
54
+ size,
55
55
  autoLoad = true,
56
56
  refreshInterval = 0,
57
57
  customTargeting,
@@ -68,8 +68,14 @@ export const BigCrunchBannerView: React.FC<BigCrunchBannerViewProps> = ({
68
68
  const subscriptionsRef = useRef<EventSubscription[]>([]);
69
69
  const viewIdRef = useRef<string>(`banner_${placementId}_${Date.now()}`);
70
70
 
71
- // Calculate banner size
71
+ // Calculate banner size for layout
72
+ // When size is undefined, config drives the ad size natively — use adaptive layout
72
73
  const bannerSize = useMemo(() => {
74
+ if (size === undefined) {
75
+ // No explicit size — let backend config drive the ad size
76
+ // Use adaptive layout since config may specify smart/adaptive sizes
77
+ return { width: 0, height: 0, adaptive: true, configDriven: true };
78
+ }
73
79
  if (typeof size === 'object' && 'width' in size && 'height' in size) {
74
80
  // Custom size
75
81
  return size;
@@ -82,8 +88,8 @@ export const BigCrunchBannerView: React.FC<BigCrunchBannerViewProps> = ({
82
88
  }
83
89
  return dimensions;
84
90
  }
85
- // Default to BANNER size
86
- return BANNER_SIZES.BANNER;
91
+ // Unknown size string — fallback to adaptive layout
92
+ return { width: 0, height: 0, adaptive: true };
87
93
  }, [size]);
88
94
 
89
95
  // Handle native events
@@ -239,21 +245,29 @@ export const BigCrunchBannerView: React.FC<BigCrunchBannerViewProps> = ({
239
245
  }, [bannerSize, style]);
240
246
 
241
247
  // Native view props
242
- // Always pass explicit dimensions to the native view
243
- const nativeProps = {
248
+ // Only send size/customWidth/customHeight when explicitly specified by the developer.
249
+ // When omitted, the native SDK uses placement config sizes (e.g., smart/adaptive from backend).
250
+ const nativeProps: any = {
244
251
  ref: viewRef,
245
252
  style: containerStyle,
246
253
  placementId,
247
- size: typeof size === 'string' ? size : 'CUSTOM',
248
- // Always pass width and height, even for standard sizes
249
- customWidth: bannerSize.width > 0 ? bannerSize.width : undefined,
250
- customHeight: bannerSize.height > 0 ? bannerSize.height : undefined,
251
254
  autoLoad,
252
255
  refreshInterval,
253
256
  customTargeting,
254
257
  viewId: viewIdRef.current,
255
258
  };
256
259
 
260
+ // Only send size to native when explicitly set by the developer
261
+ if (size !== undefined) {
262
+ if (typeof size === 'string') {
263
+ nativeProps.size = size;
264
+ } else if (typeof size === 'object' && 'width' in size && 'height' in size) {
265
+ nativeProps.size = 'CUSTOM';
266
+ nativeProps.customWidth = size.width;
267
+ nativeProps.customHeight = size.height;
268
+ }
269
+ }
270
+
257
271
  // Return the native view directly with the container style
258
272
  return <NativeBannerView {...nativeProps} />;
259
273
  };