@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.
- package/README.md +417 -0
- package/android/build.gradle +70 -0
- package/android/settings.gradle +6 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchAdsModule.kt +653 -0
- package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchAdsPackage.kt +20 -0
- package/android/src/main/java/com/bigcrunch/ads/react/BigCrunchBannerViewManager.kt +296 -0
- package/ios/BigCrunchAdsModule.swift +588 -0
- package/ios/BigCrunchBannerViewManager.swift +270 -0
- package/ios/react-native-bigcrunch-ads-Bridging-Header.h +8 -0
- package/lib/BigCrunchAds.d.ts +168 -0
- package/lib/BigCrunchAds.d.ts.map +1 -0
- package/lib/BigCrunchAds.js +241 -0
- package/lib/BigCrunchBannerView.d.ts +21 -0
- package/lib/BigCrunchBannerView.d.ts.map +1 -0
- package/lib/BigCrunchBannerView.js +176 -0
- package/lib/BigCrunchInterstitial.d.ts +66 -0
- package/lib/BigCrunchInterstitial.d.ts.map +1 -0
- package/lib/BigCrunchInterstitial.js +222 -0
- package/lib/BigCrunchRewarded.d.ts +85 -0
- package/lib/BigCrunchRewarded.d.ts.map +1 -0
- package/lib/BigCrunchRewarded.js +257 -0
- package/lib/NativeBigCrunchAds.d.ts +71 -0
- package/lib/NativeBigCrunchAds.d.ts.map +1 -0
- package/lib/NativeBigCrunchAds.js +54 -0
- package/lib/index.d.ts +28 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +32 -0
- package/lib/types/ads.d.ts +101 -0
- package/lib/types/ads.d.ts.map +1 -0
- package/lib/types/ads.js +4 -0
- package/lib/types/config.d.ts +137 -0
- package/lib/types/config.d.ts.map +1 -0
- package/lib/types/config.js +4 -0
- package/lib/types/events.d.ts +306 -0
- package/lib/types/events.d.ts.map +1 -0
- package/lib/types/events.js +4 -0
- package/lib/types/index.d.ts +175 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +23 -0
- package/package.json +88 -0
- package/react-native-bigcrunch-ads.podspec +27 -0
- package/src/BigCrunchAds.ts +298 -0
- package/src/BigCrunchBannerView.tsx +262 -0
- package/src/BigCrunchInterstitial.ts +266 -0
- package/src/BigCrunchRewarded.ts +307 -0
- package/src/NativeBigCrunchAds.ts +120 -0
- package/src/index.ts +71 -0
- package/src/types/ads.ts +112 -0
- package/src/types/config.ts +145 -0
- package/src/types/events.ts +337 -0
- package/src/types/index.ts +193 -0
package/package.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bigcrunch/react-native-ads",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "BigCrunch Mobile Ads SDK for React Native - Simplified in-app advertising with Prebid and Google Ad Manager",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"react-native": "src/index.ts",
|
|
8
|
+
"source": "src/index.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./lib/index.d.ts",
|
|
12
|
+
"import": "./lib/index.js",
|
|
13
|
+
"require": "./lib/index.js",
|
|
14
|
+
"react-native": "./src/index.ts",
|
|
15
|
+
"default": "./lib/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"src",
|
|
20
|
+
"lib",
|
|
21
|
+
"android/src",
|
|
22
|
+
"android/build.gradle",
|
|
23
|
+
"android/settings.gradle",
|
|
24
|
+
"ios/*.swift",
|
|
25
|
+
"ios/*.m",
|
|
26
|
+
"ios/*.h",
|
|
27
|
+
"react-native-bigcrunch-ads.podspec",
|
|
28
|
+
"!**/__tests__",
|
|
29
|
+
"!**/__fixtures__",
|
|
30
|
+
"!**/__mocks__"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"typescript": "tsc --noEmit",
|
|
34
|
+
"build": "tsc",
|
|
35
|
+
"prepare": "npm run build || echo 'Build skipped during install'",
|
|
36
|
+
"release": "release-it",
|
|
37
|
+
"example": "yarn --cwd example",
|
|
38
|
+
"clean": "del-cli lib"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"react-native",
|
|
42
|
+
"ios",
|
|
43
|
+
"android",
|
|
44
|
+
"ads",
|
|
45
|
+
"advertising",
|
|
46
|
+
"monetization",
|
|
47
|
+
"prebid",
|
|
48
|
+
"google-ad-manager",
|
|
49
|
+
"gam",
|
|
50
|
+
"banner",
|
|
51
|
+
"interstitial",
|
|
52
|
+
"rewarded",
|
|
53
|
+
"bigcrunch"
|
|
54
|
+
],
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "git+https://github.com/bigcrunch/mobile-ads-sdk.git"
|
|
58
|
+
},
|
|
59
|
+
"author": "BigCrunch <support@bigcrunch.com> (https://www.bigcrunch.com)",
|
|
60
|
+
"license": "MIT",
|
|
61
|
+
"bugs": {
|
|
62
|
+
"url": "https://github.com/bigcrunch/mobile-ads-sdk/issues"
|
|
63
|
+
},
|
|
64
|
+
"homepage": "https://github.com/bigcrunch/mobile-ads-sdk#readme",
|
|
65
|
+
"publishConfig": {
|
|
66
|
+
"registry": "https://registry.npmjs.org/",
|
|
67
|
+
"access": "public"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@types/react": "^18.2.0",
|
|
71
|
+
"@types/react-native": "^0.72.0",
|
|
72
|
+
"del-cli": "^5.0.0",
|
|
73
|
+
"release-it": "^15.0.0",
|
|
74
|
+
"typescript": "^5.0.0"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"react": "*",
|
|
78
|
+
"react-native": "*"
|
|
79
|
+
},
|
|
80
|
+
"peerDependenciesMeta": {
|
|
81
|
+
"react": {
|
|
82
|
+
"optional": false
|
|
83
|
+
},
|
|
84
|
+
"react-native": {
|
|
85
|
+
"optional": false
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "react-native-bigcrunch-ads"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.description = <<-DESC
|
|
10
|
+
BigCrunch Mobile Ads SDK for React Native - Simplified in-app advertising with Prebid and Google Ad Manager
|
|
11
|
+
DESC
|
|
12
|
+
s.homepage = "https://github.com/bigcrunch/mobile-ads-sdk"
|
|
13
|
+
s.license = "MIT"
|
|
14
|
+
s.authors = { "BigCrunch" => "support@bigcrunch.com" }
|
|
15
|
+
s.platforms = { :ios => "13.0" }
|
|
16
|
+
s.source = { :git => "https://github.com/bigcrunch/mobile-ads-sdk.git", :tag => "#{s.version}" }
|
|
17
|
+
|
|
18
|
+
s.source_files = "ios/**/*.{h,c,cc,cpp,m,mm,swift}"
|
|
19
|
+
s.requires_arc = true
|
|
20
|
+
|
|
21
|
+
s.dependency "React"
|
|
22
|
+
s.dependency "BigCrunchAds", "~> 0.1.0" # Reference to main iOS SDK
|
|
23
|
+
s.dependency "Google-Mobile-Ads-SDK", ">= 10.14.0"
|
|
24
|
+
s.dependency "PrebidMobile", "~> 2.1.6"
|
|
25
|
+
|
|
26
|
+
s.swift_version = "5.9"
|
|
27
|
+
end
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BigCrunch Mobile Ads SDK for React Native
|
|
3
|
+
* Main API class
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
NativeBigCrunchAds,
|
|
8
|
+
BigCrunchAdsEventEmitter,
|
|
9
|
+
NativeEventNames,
|
|
10
|
+
} from './NativeBigCrunchAds';
|
|
11
|
+
import type {
|
|
12
|
+
InitializationOptions,
|
|
13
|
+
Environment,
|
|
14
|
+
SessionInfo,
|
|
15
|
+
DeviceContext,
|
|
16
|
+
AppConfig,
|
|
17
|
+
EventSubscription,
|
|
18
|
+
} from './types';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Main entry point for BigCrunch Mobile Ads SDK
|
|
22
|
+
*/
|
|
23
|
+
export class BigCrunchAds {
|
|
24
|
+
private static isInitializedFlag = false;
|
|
25
|
+
private static initializationPromise: Promise<void> | null = null;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Initialize the BigCrunch Ads SDK
|
|
29
|
+
* Must be called before using any other SDK features
|
|
30
|
+
*
|
|
31
|
+
* @param propertyId - Your BigCrunch property ID
|
|
32
|
+
* @param apiKey - Your API key for authentication
|
|
33
|
+
* @param environment - Environment to use (default: 'production')
|
|
34
|
+
* @param options - Additional initialization options
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* await BigCrunchAds.initialize(
|
|
39
|
+
* 'your-property-id',
|
|
40
|
+
* 'your-api-key',
|
|
41
|
+
* 'production'
|
|
42
|
+
* );
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
static async initialize(
|
|
46
|
+
propertyId: string,
|
|
47
|
+
apiKey: string,
|
|
48
|
+
environment: Environment = 'production',
|
|
49
|
+
options?: Partial<InitializationOptions>
|
|
50
|
+
): Promise<void> {
|
|
51
|
+
if (this.isInitializedFlag) {
|
|
52
|
+
console.warn('BigCrunchAds: SDK is already initialized');
|
|
53
|
+
return this.initializationPromise!;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const initOptions: InitializationOptions = {
|
|
57
|
+
propertyId,
|
|
58
|
+
apiKey,
|
|
59
|
+
environment,
|
|
60
|
+
...options,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
this.initializationPromise = NativeBigCrunchAds.initialize(initOptions)
|
|
64
|
+
.then(() => {
|
|
65
|
+
this.isInitializedFlag = true;
|
|
66
|
+
console.log('BigCrunchAds: SDK initialized successfully');
|
|
67
|
+
})
|
|
68
|
+
.catch((error) => {
|
|
69
|
+
this.isInitializedFlag = false;
|
|
70
|
+
this.initializationPromise = null;
|
|
71
|
+
throw error;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return this.initializationPromise;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Check if the SDK is initialized
|
|
79
|
+
*/
|
|
80
|
+
static async isInitialized(): Promise<boolean> {
|
|
81
|
+
if (this.isInitializedFlag) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
return NativeBigCrunchAds.isInitialized();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Track a screen view for analytics
|
|
89
|
+
*
|
|
90
|
+
* @param screenName - Name of the screen being viewed
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* BigCrunchAds.trackScreenView('HomeScreen');
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
static async trackScreenView(screenName: string): Promise<void> {
|
|
98
|
+
this.ensureInitialized();
|
|
99
|
+
return NativeBigCrunchAds.trackScreenView(screenName);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get the current app configuration
|
|
104
|
+
* Returns null if config hasn't been loaded yet
|
|
105
|
+
*/
|
|
106
|
+
static async getAppConfig(): Promise<AppConfig | null> {
|
|
107
|
+
this.ensureInitialized();
|
|
108
|
+
return NativeBigCrunchAds.getAppConfig();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Force refresh the app configuration from backend
|
|
113
|
+
*/
|
|
114
|
+
static async refreshConfig(): Promise<void> {
|
|
115
|
+
this.ensureInitialized();
|
|
116
|
+
return NativeBigCrunchAds.refreshConfig();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Get current session information
|
|
121
|
+
*/
|
|
122
|
+
static async getSessionInfo(): Promise<SessionInfo> {
|
|
123
|
+
this.ensureInitialized();
|
|
124
|
+
return NativeBigCrunchAds.getSessionInfo();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Start a new session (usually handled automatically)
|
|
129
|
+
*/
|
|
130
|
+
static async startNewSession(): Promise<void> {
|
|
131
|
+
this.ensureInitialized();
|
|
132
|
+
return NativeBigCrunchAds.startNewSession();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get device context information
|
|
137
|
+
*/
|
|
138
|
+
static async getDeviceContext(): Promise<DeviceContext> {
|
|
139
|
+
return NativeBigCrunchAds.getDeviceContext();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Set GDPR consent string
|
|
144
|
+
*
|
|
145
|
+
* @param consent - GDPR consent string
|
|
146
|
+
*/
|
|
147
|
+
static async setGdprConsent(consent: string): Promise<void> {
|
|
148
|
+
return NativeBigCrunchAds.setGdprConsent(consent);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Set CCPA compliance string
|
|
153
|
+
*
|
|
154
|
+
* @param ccpaString - CCPA string (e.g., "1YNN")
|
|
155
|
+
*/
|
|
156
|
+
static async setCcpaString(ccpaString: string): Promise<void> {
|
|
157
|
+
return NativeBigCrunchAds.setCcpaString(ccpaString);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Set COPPA compliance
|
|
162
|
+
*
|
|
163
|
+
* @param isCompliant - Whether the app is COPPA compliant
|
|
164
|
+
*/
|
|
165
|
+
static async setCoppaCompliant(isCompliant: boolean): Promise<void> {
|
|
166
|
+
return NativeBigCrunchAds.setCoppaCompliant(isCompliant);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Enable or disable debug mode
|
|
171
|
+
*
|
|
172
|
+
* @param enabled - Whether to enable debug mode
|
|
173
|
+
*/
|
|
174
|
+
static async setDebugMode(enabled: boolean): Promise<void> {
|
|
175
|
+
return NativeBigCrunchAds.setDebugMode(enabled);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Add a test device ID for testing ads
|
|
180
|
+
*
|
|
181
|
+
* @param deviceId - Device ID to add as test device
|
|
182
|
+
*/
|
|
183
|
+
static async addTestDevice(deviceId: string): Promise<void> {
|
|
184
|
+
return NativeBigCrunchAds.addTestDevice(deviceId);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Remove a test device ID
|
|
189
|
+
*
|
|
190
|
+
* @param deviceId - Device ID to remove from test devices
|
|
191
|
+
*/
|
|
192
|
+
static async removeTestDevice(deviceId: string): Promise<void> {
|
|
193
|
+
return NativeBigCrunchAds.removeTestDevice(deviceId);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Get list of test device IDs
|
|
198
|
+
*/
|
|
199
|
+
static async getTestDevices(): Promise<string[]> {
|
|
200
|
+
return NativeBigCrunchAds.getTestDevices();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Set UTM parameters for attribution tracking
|
|
205
|
+
*
|
|
206
|
+
* These parameters are persisted and used for all analytics events.
|
|
207
|
+
* Typically set from deep link parameters.
|
|
208
|
+
*
|
|
209
|
+
* @param params - UTM parameters object
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript
|
|
213
|
+
* BigCrunchAds.setUTMParameters({
|
|
214
|
+
* source: 'google',
|
|
215
|
+
* medium: 'cpc',
|
|
216
|
+
* campaign: 'summer_sale',
|
|
217
|
+
* term: 'running shoes',
|
|
218
|
+
* content: 'variant_a'
|
|
219
|
+
* });
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
static async setUTMParameters(params: {
|
|
223
|
+
source?: string;
|
|
224
|
+
medium?: string;
|
|
225
|
+
campaign?: string;
|
|
226
|
+
term?: string;
|
|
227
|
+
content?: string;
|
|
228
|
+
}): Promise<void> {
|
|
229
|
+
return NativeBigCrunchAds.setUTMParameters(params);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Clear UTM parameters
|
|
234
|
+
*/
|
|
235
|
+
static async clearUTMParameters(): Promise<void> {
|
|
236
|
+
return NativeBigCrunchAds.clearUTMParameters();
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Add a global event listener
|
|
241
|
+
*
|
|
242
|
+
* @param eventName - Native event name to listen to
|
|
243
|
+
* @param listener - Callback function
|
|
244
|
+
* @returns Subscription object with remove() method
|
|
245
|
+
*/
|
|
246
|
+
static addEventListener(
|
|
247
|
+
eventName: string,
|
|
248
|
+
listener: (event: any) => void
|
|
249
|
+
): EventSubscription {
|
|
250
|
+
const subscription = BigCrunchAdsEventEmitter.addListener(eventName, listener);
|
|
251
|
+
return {
|
|
252
|
+
remove: () => subscription.remove(),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Listen for configuration updates
|
|
258
|
+
*/
|
|
259
|
+
static onConfigUpdated(listener: (config: AppConfig) => void): EventSubscription {
|
|
260
|
+
return this.addEventListener(NativeEventNames.CONFIG_UPDATED, listener);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Listen for configuration failures
|
|
265
|
+
*/
|
|
266
|
+
static onConfigFailed(listener: (error: Error) => void): EventSubscription {
|
|
267
|
+
return this.addEventListener(NativeEventNames.CONFIG_FAILED, listener);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Listen for session start events
|
|
272
|
+
*/
|
|
273
|
+
static onSessionStarted(listener: (session: SessionInfo) => void): EventSubscription {
|
|
274
|
+
return this.addEventListener(NativeEventNames.SESSION_STARTED, listener);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Listen for session end events
|
|
279
|
+
*/
|
|
280
|
+
static onSessionEnded(listener: (session: SessionInfo) => void): EventSubscription {
|
|
281
|
+
return this.addEventListener(NativeEventNames.SESSION_ENDED, listener);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Ensure SDK is initialized before calling methods
|
|
286
|
+
* @private
|
|
287
|
+
*/
|
|
288
|
+
private static ensureInitialized(): void {
|
|
289
|
+
if (!this.isInitializedFlag && !this.initializationPromise) {
|
|
290
|
+
throw new Error(
|
|
291
|
+
'BigCrunchAds: SDK is not initialized. Call BigCrunchAds.initialize() first.'
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Export as default for convenience
|
|
298
|
+
export default BigCrunchAds;
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BigCrunchBannerView - React Native component for displaying banner ads
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React, { useEffect, useRef, useCallback, useMemo } from 'react';
|
|
6
|
+
import {
|
|
7
|
+
requireNativeComponent,
|
|
8
|
+
ViewStyle,
|
|
9
|
+
StyleSheet,
|
|
10
|
+
findNodeHandle,
|
|
11
|
+
UIManager,
|
|
12
|
+
} from 'react-native';
|
|
13
|
+
import { BigCrunchAdsEventEmitter, NativeEventNames } from './NativeBigCrunchAds';
|
|
14
|
+
import type {
|
|
15
|
+
BigCrunchBannerViewProps,
|
|
16
|
+
BannerSize,
|
|
17
|
+
AdError,
|
|
18
|
+
AdRevenue,
|
|
19
|
+
EventSubscription,
|
|
20
|
+
} from './types';
|
|
21
|
+
|
|
22
|
+
// Native component name
|
|
23
|
+
const NATIVE_COMPONENT_NAME = 'BigCrunchBannerView';
|
|
24
|
+
|
|
25
|
+
// Banner size dimensions
|
|
26
|
+
const BANNER_SIZES = {
|
|
27
|
+
BANNER: { width: 320, height: 50 },
|
|
28
|
+
LARGE_BANNER: { width: 320, height: 100 },
|
|
29
|
+
MEDIUM_RECTANGLE: { width: 300, height: 250 },
|
|
30
|
+
FULL_BANNER: { width: 468, height: 60 },
|
|
31
|
+
LEADERBOARD: { width: 728, height: 90 },
|
|
32
|
+
ADAPTIVE: { width: -1, height: -1 }, // Calculated dynamically
|
|
33
|
+
SMART: { width: -1, height: -1 }, // Deprecated, use ADAPTIVE
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Native view component
|
|
37
|
+
const NativeBannerView = requireNativeComponent<any>(NATIVE_COMPONENT_NAME);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* React component for displaying BigCrunch banner ads
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```tsx
|
|
44
|
+
* <BigCrunchBannerView
|
|
45
|
+
* placementId="banner-home"
|
|
46
|
+
* size="BANNER"
|
|
47
|
+
* onAdLoaded={() => console.log('Ad loaded')}
|
|
48
|
+
* onAdFailedToLoad={(error) => console.error('Ad failed to load', error)}
|
|
49
|
+
* />
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export const BigCrunchBannerView: React.FC<BigCrunchBannerViewProps> = ({
|
|
53
|
+
placementId,
|
|
54
|
+
size = 'BANNER',
|
|
55
|
+
autoLoad = true,
|
|
56
|
+
refreshInterval = 0,
|
|
57
|
+
customTargeting,
|
|
58
|
+
style,
|
|
59
|
+
onAdLoaded,
|
|
60
|
+
onAdFailedToLoad,
|
|
61
|
+
onAdImpression,
|
|
62
|
+
onAdClicked,
|
|
63
|
+
onAdOpened,
|
|
64
|
+
onAdClosed,
|
|
65
|
+
onAdRevenue,
|
|
66
|
+
}) => {
|
|
67
|
+
const viewRef = useRef<any>(null);
|
|
68
|
+
const subscriptionsRef = useRef<EventSubscription[]>([]);
|
|
69
|
+
const viewIdRef = useRef<string>(`banner_${placementId}_${Date.now()}`);
|
|
70
|
+
|
|
71
|
+
// Calculate banner size
|
|
72
|
+
const bannerSize = useMemo(() => {
|
|
73
|
+
if (typeof size === 'object' && 'width' in size && 'height' in size) {
|
|
74
|
+
// Custom size
|
|
75
|
+
return size;
|
|
76
|
+
} else if (typeof size === 'string' && size in BANNER_SIZES) {
|
|
77
|
+
// Predefined size
|
|
78
|
+
const dimensions = BANNER_SIZES[size as BannerSize];
|
|
79
|
+
if (dimensions.width === -1 || dimensions.height === -1) {
|
|
80
|
+
// Adaptive/Smart banner - will be calculated natively
|
|
81
|
+
return { width: 0, height: 0, adaptive: true };
|
|
82
|
+
}
|
|
83
|
+
return dimensions;
|
|
84
|
+
}
|
|
85
|
+
// Default to BANNER size
|
|
86
|
+
return BANNER_SIZES.BANNER;
|
|
87
|
+
}, [size]);
|
|
88
|
+
|
|
89
|
+
// Handle native events
|
|
90
|
+
const handleNativeEvent = useCallback((_eventName: string, handler?: Function) => {
|
|
91
|
+
return (event: any) => {
|
|
92
|
+
// Check if event is for this specific banner view
|
|
93
|
+
if (event.viewId === viewIdRef.current || event.placementId === placementId) {
|
|
94
|
+
handler?.(event);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}, [placementId]);
|
|
98
|
+
|
|
99
|
+
// Setup event listeners
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
const subscriptions: EventSubscription[] = [];
|
|
102
|
+
|
|
103
|
+
if (onAdLoaded) {
|
|
104
|
+
subscriptions.push(
|
|
105
|
+
BigCrunchAdsEventEmitter.addListener(
|
|
106
|
+
NativeEventNames.BANNER_AD_LOADED,
|
|
107
|
+
handleNativeEvent(NativeEventNames.BANNER_AD_LOADED, onAdLoaded)
|
|
108
|
+
)
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (onAdFailedToLoad) {
|
|
113
|
+
subscriptions.push(
|
|
114
|
+
BigCrunchAdsEventEmitter.addListener(
|
|
115
|
+
NativeEventNames.BANNER_AD_FAILED_TO_LOAD,
|
|
116
|
+
handleNativeEvent(NativeEventNames.BANNER_AD_FAILED_TO_LOAD, (event: any) => {
|
|
117
|
+
const error: AdError = {
|
|
118
|
+
code: event.errorCode || 'UNKNOWN',
|
|
119
|
+
message: event.errorMessage || 'Ad failed to load',
|
|
120
|
+
underlyingError: event.underlyingError,
|
|
121
|
+
};
|
|
122
|
+
onAdFailedToLoad(error);
|
|
123
|
+
})
|
|
124
|
+
)
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (onAdImpression) {
|
|
129
|
+
subscriptions.push(
|
|
130
|
+
BigCrunchAdsEventEmitter.addListener(
|
|
131
|
+
NativeEventNames.BANNER_AD_IMPRESSION,
|
|
132
|
+
handleNativeEvent(NativeEventNames.BANNER_AD_IMPRESSION, onAdImpression)
|
|
133
|
+
)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (onAdClicked) {
|
|
138
|
+
subscriptions.push(
|
|
139
|
+
BigCrunchAdsEventEmitter.addListener(
|
|
140
|
+
NativeEventNames.BANNER_AD_CLICKED,
|
|
141
|
+
handleNativeEvent(NativeEventNames.BANNER_AD_CLICKED, onAdClicked)
|
|
142
|
+
)
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (onAdOpened) {
|
|
147
|
+
subscriptions.push(
|
|
148
|
+
BigCrunchAdsEventEmitter.addListener(
|
|
149
|
+
NativeEventNames.BANNER_AD_OPENED,
|
|
150
|
+
handleNativeEvent(NativeEventNames.BANNER_AD_OPENED, onAdOpened)
|
|
151
|
+
)
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (onAdClosed) {
|
|
156
|
+
subscriptions.push(
|
|
157
|
+
BigCrunchAdsEventEmitter.addListener(
|
|
158
|
+
NativeEventNames.BANNER_AD_CLOSED,
|
|
159
|
+
handleNativeEvent(NativeEventNames.BANNER_AD_CLOSED, onAdClosed)
|
|
160
|
+
)
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (onAdRevenue) {
|
|
165
|
+
subscriptions.push(
|
|
166
|
+
BigCrunchAdsEventEmitter.addListener(
|
|
167
|
+
NativeEventNames.BANNER_AD_REVENUE,
|
|
168
|
+
handleNativeEvent(NativeEventNames.BANNER_AD_REVENUE, (event: any) => {
|
|
169
|
+
const revenue: AdRevenue = {
|
|
170
|
+
valueMicros: event.valueMicros,
|
|
171
|
+
currencyCode: event.currencyCode,
|
|
172
|
+
adUnitId: event.adUnitId,
|
|
173
|
+
precision: event.precision,
|
|
174
|
+
};
|
|
175
|
+
onAdRevenue(revenue);
|
|
176
|
+
})
|
|
177
|
+
)
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
subscriptionsRef.current = subscriptions;
|
|
182
|
+
|
|
183
|
+
// Cleanup on unmount
|
|
184
|
+
return () => {
|
|
185
|
+
subscriptions.forEach(sub => sub.remove());
|
|
186
|
+
subscriptionsRef.current = [];
|
|
187
|
+
};
|
|
188
|
+
}, [
|
|
189
|
+
placementId,
|
|
190
|
+
handleNativeEvent,
|
|
191
|
+
onAdLoaded,
|
|
192
|
+
onAdFailedToLoad,
|
|
193
|
+
onAdImpression,
|
|
194
|
+
onAdClicked,
|
|
195
|
+
onAdOpened,
|
|
196
|
+
onAdClosed,
|
|
197
|
+
onAdRevenue,
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
// Load ad programmatically
|
|
201
|
+
const loadAd = useCallback(() => {
|
|
202
|
+
if (viewRef.current) {
|
|
203
|
+
const handle = findNodeHandle(viewRef.current);
|
|
204
|
+
if (handle) {
|
|
205
|
+
const viewManagerConfig = UIManager.getViewManagerConfig(NATIVE_COMPONENT_NAME);
|
|
206
|
+
const command = viewManagerConfig?.Commands?.loadAd;
|
|
207
|
+
if (command !== undefined) {
|
|
208
|
+
UIManager.dispatchViewManagerCommand(handle, command, []);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}, []);
|
|
213
|
+
|
|
214
|
+
// Auto-load ad on mount if enabled
|
|
215
|
+
useEffect(() => {
|
|
216
|
+
if (autoLoad) {
|
|
217
|
+
// Delay to ensure native view is ready
|
|
218
|
+
const timer = setTimeout(loadAd, 100);
|
|
219
|
+
return () => clearTimeout(timer);
|
|
220
|
+
}
|
|
221
|
+
return undefined;
|
|
222
|
+
}, [autoLoad, loadAd]);
|
|
223
|
+
|
|
224
|
+
// Container styles
|
|
225
|
+
const containerStyle: ViewStyle = useMemo(() => {
|
|
226
|
+
const baseStyle: ViewStyle = {
|
|
227
|
+
width: bannerSize.width > 0 ? bannerSize.width : 320,
|
|
228
|
+
height: bannerSize.height > 0 ? bannerSize.height : 50,
|
|
229
|
+
// Remove overflow: 'hidden' to avoid clipping the ad content
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
if ((bannerSize as any).adaptive) {
|
|
233
|
+
// Adaptive banner - let it size itself
|
|
234
|
+
baseStyle.alignSelf = 'stretch';
|
|
235
|
+
baseStyle.width = '100%';
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return StyleSheet.flatten([baseStyle, style]);
|
|
239
|
+
}, [bannerSize, style]);
|
|
240
|
+
|
|
241
|
+
// Native view props
|
|
242
|
+
// Always pass explicit dimensions to the native view
|
|
243
|
+
const nativeProps = {
|
|
244
|
+
ref: viewRef,
|
|
245
|
+
style: containerStyle,
|
|
246
|
+
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
|
+
autoLoad,
|
|
252
|
+
refreshInterval,
|
|
253
|
+
customTargeting,
|
|
254
|
+
viewId: viewIdRef.current,
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// Return the native view directly with the container style
|
|
258
|
+
return <NativeBannerView {...nativeProps} />;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
// Export as default
|
|
262
|
+
export default BigCrunchBannerView;
|