@vynix-org/react-native-ads-sdk 0.1.1

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 (128) hide show
  1. package/AdsSdk.podspec +52 -0
  2. package/LICENSE +20 -0
  3. package/README.md +95 -0
  4. package/android/build.gradle +108 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +5 -0
  7. package/android/src/main/java/com/adssdk/AdsSdkModule.kt +23 -0
  8. package/android/src/main/java/com/adssdk/AdsSdkPackage.kt +33 -0
  9. package/ios/AdsSdk.h +5 -0
  10. package/ios/AdsSdk.mm +18 -0
  11. package/lib/module/ads-manager/AppOpenAdsManager.js +131 -0
  12. package/lib/module/ads-manager/AppOpenAdsManager.js.map +1 -0
  13. package/lib/module/ads-manager/GoogleMobileAdsManager.js +62 -0
  14. package/lib/module/ads-manager/GoogleMobileAdsManager.js.map +1 -0
  15. package/lib/module/ads-manager/InterstitialAdsManager.js +291 -0
  16. package/lib/module/ads-manager/InterstitialAdsManager.js.map +1 -0
  17. package/lib/module/ads-manager/NativeAdsManager.js +405 -0
  18. package/lib/module/ads-manager/NativeAdsManager.js.map +1 -0
  19. package/lib/module/ads-manager/RewardedAdsManager.js +328 -0
  20. package/lib/module/ads-manager/RewardedAdsManager.js.map +1 -0
  21. package/lib/module/ads-manager/RewardedInterstitialAdsManager.js +328 -0
  22. package/lib/module/ads-manager/RewardedInterstitialAdsManager.js.map +1 -0
  23. package/lib/module/components/BannerAdComponent.js +159 -0
  24. package/lib/module/components/BannerAdComponent.js.map +1 -0
  25. package/lib/module/components/FullscreenStyles.js +162 -0
  26. package/lib/module/components/FullscreenStyles.js.map +1 -0
  27. package/lib/module/components/NativeAdComponent.js +172 -0
  28. package/lib/module/components/NativeAdComponent.js.map +1 -0
  29. package/lib/module/components/NativeAdFullscreenComponent.js +205 -0
  30. package/lib/module/components/NativeAdFullscreenComponent.js.map +1 -0
  31. package/lib/module/components/NativeStyles.js +143 -0
  32. package/lib/module/components/NativeStyles.js.map +1 -0
  33. package/lib/module/event/custom-event.js +29 -0
  34. package/lib/module/event/custom-event.js.map +1 -0
  35. package/lib/module/hook/useAppOpenAd.js +138 -0
  36. package/lib/module/hook/useAppOpenAd.js.map +1 -0
  37. package/lib/module/hook/useInterstitialAd.js +157 -0
  38. package/lib/module/hook/useInterstitialAd.js.map +1 -0
  39. package/lib/module/hook/useNativeAd.js +147 -0
  40. package/lib/module/hook/useNativeAd.js.map +1 -0
  41. package/lib/module/hook/useRewardedAd.js +166 -0
  42. package/lib/module/hook/useRewardedAd.js.map +1 -0
  43. package/lib/module/hook/useRewardedInterstitialAd.js +166 -0
  44. package/lib/module/hook/useRewardedInterstitialAd.js.map +1 -0
  45. package/lib/module/index.js +14 -0
  46. package/lib/module/index.js.map +1 -0
  47. package/lib/module/package.json +1 -0
  48. package/lib/module/stores/interstitial-ads-store.js +205 -0
  49. package/lib/module/stores/interstitial-ads-store.js.map +1 -0
  50. package/lib/module/stores/native-ads-store.js +204 -0
  51. package/lib/module/stores/native-ads-store.js.map +1 -0
  52. package/lib/module/stores/rewarded-ads-store.js +216 -0
  53. package/lib/module/stores/rewarded-ads-store.js.map +1 -0
  54. package/lib/module/stores/rewarded-interstitial-ads-store.js +216 -0
  55. package/lib/module/stores/rewarded-interstitial-ads-store.js.map +1 -0
  56. package/lib/module/types/ads-types.js +25 -0
  57. package/lib/module/types/ads-types.js.map +1 -0
  58. package/lib/typescript/package.json +1 -0
  59. package/lib/typescript/src/ads-manager/AppOpenAdsManager.d.ts +38 -0
  60. package/lib/typescript/src/ads-manager/AppOpenAdsManager.d.ts.map +1 -0
  61. package/lib/typescript/src/ads-manager/GoogleMobileAdsManager.d.ts +22 -0
  62. package/lib/typescript/src/ads-manager/GoogleMobileAdsManager.d.ts.map +1 -0
  63. package/lib/typescript/src/ads-manager/InterstitialAdsManager.d.ts +22 -0
  64. package/lib/typescript/src/ads-manager/InterstitialAdsManager.d.ts.map +1 -0
  65. package/lib/typescript/src/ads-manager/NativeAdsManager.d.ts +59 -0
  66. package/lib/typescript/src/ads-manager/NativeAdsManager.d.ts.map +1 -0
  67. package/lib/typescript/src/ads-manager/RewardedAdsManager.d.ts +25 -0
  68. package/lib/typescript/src/ads-manager/RewardedAdsManager.d.ts.map +1 -0
  69. package/lib/typescript/src/ads-manager/RewardedInterstitialAdsManager.d.ts +25 -0
  70. package/lib/typescript/src/ads-manager/RewardedInterstitialAdsManager.d.ts.map +1 -0
  71. package/lib/typescript/src/components/BannerAdComponent.d.ts +22 -0
  72. package/lib/typescript/src/components/BannerAdComponent.d.ts.map +1 -0
  73. package/lib/typescript/src/components/FullscreenStyles.d.ts +155 -0
  74. package/lib/typescript/src/components/FullscreenStyles.d.ts.map +1 -0
  75. package/lib/typescript/src/components/NativeAdComponent.d.ts +24 -0
  76. package/lib/typescript/src/components/NativeAdComponent.d.ts.map +1 -0
  77. package/lib/typescript/src/components/NativeAdFullscreenComponent.d.ts +26 -0
  78. package/lib/typescript/src/components/NativeAdFullscreenComponent.d.ts.map +1 -0
  79. package/lib/typescript/src/components/NativeStyles.d.ts +139 -0
  80. package/lib/typescript/src/components/NativeStyles.d.ts.map +1 -0
  81. package/lib/typescript/src/event/custom-event.d.ts +8 -0
  82. package/lib/typescript/src/event/custom-event.d.ts.map +1 -0
  83. package/lib/typescript/src/hook/useAppOpenAd.d.ts +19 -0
  84. package/lib/typescript/src/hook/useAppOpenAd.d.ts.map +1 -0
  85. package/lib/typescript/src/hook/useInterstitialAd.d.ts +20 -0
  86. package/lib/typescript/src/hook/useInterstitialAd.d.ts.map +1 -0
  87. package/lib/typescript/src/hook/useNativeAd.d.ts +20 -0
  88. package/lib/typescript/src/hook/useNativeAd.d.ts.map +1 -0
  89. package/lib/typescript/src/hook/useRewardedAd.d.ts +27 -0
  90. package/lib/typescript/src/hook/useRewardedAd.d.ts.map +1 -0
  91. package/lib/typescript/src/hook/useRewardedInterstitialAd.d.ts +27 -0
  92. package/lib/typescript/src/hook/useRewardedInterstitialAd.d.ts.map +1 -0
  93. package/lib/typescript/src/index.d.ts +10 -0
  94. package/lib/typescript/src/index.d.ts.map +1 -0
  95. package/lib/typescript/src/stores/interstitial-ads-store.d.ts +36 -0
  96. package/lib/typescript/src/stores/interstitial-ads-store.d.ts.map +1 -0
  97. package/lib/typescript/src/stores/native-ads-store.d.ts +36 -0
  98. package/lib/typescript/src/stores/native-ads-store.d.ts.map +1 -0
  99. package/lib/typescript/src/stores/rewarded-ads-store.d.ts +39 -0
  100. package/lib/typescript/src/stores/rewarded-ads-store.d.ts.map +1 -0
  101. package/lib/typescript/src/stores/rewarded-interstitial-ads-store.d.ts +39 -0
  102. package/lib/typescript/src/stores/rewarded-interstitial-ads-store.d.ts.map +1 -0
  103. package/lib/typescript/src/types/ads-types.d.ts +164 -0
  104. package/lib/typescript/src/types/ads-types.d.ts.map +1 -0
  105. package/package.json +177 -0
  106. package/src/ads-manager/AppOpenAdsManager.ts +155 -0
  107. package/src/ads-manager/GoogleMobileAdsManager.ts +68 -0
  108. package/src/ads-manager/InterstitialAdsManager.ts +371 -0
  109. package/src/ads-manager/NativeAdsManager.ts +445 -0
  110. package/src/ads-manager/RewardedAdsManager.ts +383 -0
  111. package/src/ads-manager/RewardedInterstitialAdsManager.ts +410 -0
  112. package/src/components/BannerAdComponent.tsx +205 -0
  113. package/src/components/FullscreenStyles.ts +158 -0
  114. package/src/components/NativeAdComponent.tsx +208 -0
  115. package/src/components/NativeAdFullscreenComponent.tsx +261 -0
  116. package/src/components/NativeStyles.ts +141 -0
  117. package/src/event/custom-event.ts +30 -0
  118. package/src/hook/useAppOpenAd.ts +161 -0
  119. package/src/hook/useInterstitialAd.ts +195 -0
  120. package/src/hook/useNativeAd.ts +173 -0
  121. package/src/hook/useRewardedAd.ts +205 -0
  122. package/src/hook/useRewardedInterstitialAd.ts +212 -0
  123. package/src/index.tsx +33 -0
  124. package/src/stores/interstitial-ads-store.ts +287 -0
  125. package/src/stores/native-ads-store.ts +272 -0
  126. package/src/stores/rewarded-ads-store.ts +290 -0
  127. package/src/stores/rewarded-interstitial-ads-store.ts +318 -0
  128. package/src/types/ads-types.ts +239 -0
@@ -0,0 +1,383 @@
1
+ import {
2
+ AdStatus,
3
+ type RewardedAdConfig,
4
+ type RewardedAdInstance,
5
+ } from '../types/ads-types';
6
+ import { googleMobileAdsManager } from './GoogleMobileAdsManager';
7
+ import { CustomEventEmitter } from '../event/custom-event';
8
+
9
+ export class RewardedAdsManager extends CustomEventEmitter {
10
+ private state: Map<string, RewardedAdInstance> = new Map();
11
+ private configs: Map<string, RewardedAdConfig> = new Map();
12
+ private loadPromises: Map<string, Promise<void>> = new Map();
13
+
14
+ constructor() {
15
+ super();
16
+ this.initializeGoogleMobileAds();
17
+ }
18
+
19
+ private async initializeGoogleMobileAds(): Promise<void> {
20
+ try {
21
+ await googleMobileAdsManager.initialize();
22
+ } catch (error) {
23
+ console.warn('Failed to initialize Google Mobile Ads SDK:', error);
24
+ }
25
+ }
26
+
27
+ // Thay đổi signature: chỉ nhận config
28
+ async preloadAd(config: RewardedAdConfig): Promise<void> {
29
+ const fullConfig: RewardedAdConfig = {
30
+ ...config,
31
+ timeout: config.timeout ?? 10000,
32
+ maxRetries: config.maxRetries ?? 3,
33
+ showOnAppStateChange: config.showOnAppStateChange ?? false,
34
+ };
35
+
36
+ const { adKey, adId } = fullConfig;
37
+ this.configs.set(adKey, fullConfig);
38
+
39
+ if (!this.state.has(adKey)) {
40
+ const adInstance: RewardedAdInstance = {
41
+ adKey,
42
+ adId,
43
+ status: AdStatus.IDLE,
44
+ data: null,
45
+ error: null,
46
+ loadTime: null,
47
+ displayTime: null,
48
+ retryCount: 0,
49
+ type: 'rewarded',
50
+ config: fullConfig,
51
+ isUsingHighPriority: false,
52
+ hasTriedHighPriority: false,
53
+ };
54
+ this.state.set(adKey, adInstance);
55
+ }
56
+
57
+ if (this.loadPromises.has(adKey)) {
58
+ return this.loadPromises.get(adKey)!;
59
+ }
60
+
61
+ const loadPromise = this.loadAdInternal(adKey);
62
+ this.loadPromises.set(adKey, loadPromise);
63
+
64
+ try {
65
+ await loadPromise;
66
+ } finally {
67
+ this.loadPromises.delete(adKey);
68
+ }
69
+ }
70
+
71
+ // Thay đổi signature: chỉ nhận config
72
+ async loadAd(config: RewardedAdConfig): Promise<void> {
73
+ return this.preloadAd(config);
74
+ }
75
+
76
+ async displayAd(
77
+ adKey: string
78
+ ): Promise<{ ad: RewardedAdInstance | null; reward: any }> {
79
+ const ad = this.state.get(adKey);
80
+
81
+ if (!ad) {
82
+ console.warn(`Rewarded ad with key "${adKey}" not found`);
83
+ return { ad: null, reward: null };
84
+ }
85
+
86
+ if (ad.status === AdStatus.LOADED) {
87
+ try {
88
+ const reward = await this.showRewardedAd(ad);
89
+
90
+ ad.status = AdStatus.DISPLAYED;
91
+ ad.displayTime = Date.now();
92
+ ad.reward = reward;
93
+ this.emit('adDisplayed', ad);
94
+
95
+ // Tự động preload lại quảng cáo mới
96
+ // const config = this.configs.get(adKey);
97
+ // if (config) {
98
+ // this.preloadAd(adKey, config.adId, config).catch((error) => {
99
+ // console.warn(
100
+ // `Failed to preload new rewarded ad for key "${adKey}":`,
101
+ // error
102
+ // );
103
+ // });
104
+ // }
105
+
106
+ return { ad, reward };
107
+ } catch (error) {
108
+ ad.status = AdStatus.ERROR;
109
+ ad.error = error instanceof Error ? error.message : String(error);
110
+ this.emit('adError', ad);
111
+ return { ad: null, reward: null };
112
+ }
113
+ }
114
+
115
+ if (ad.status === AdStatus.LOADING) {
116
+ await this.waitForAdLoad(adKey);
117
+ return this.displayAd(adKey);
118
+ }
119
+
120
+ if (ad.status === AdStatus.ERROR) {
121
+ await this.refreshAd(adKey);
122
+ return this.displayAd(adKey);
123
+ }
124
+
125
+ console.warn(
126
+ `Cannot display rewarded ad with key "${adKey}" in status: ${ad.status}`
127
+ );
128
+ return { ad: null, reward: null };
129
+ }
130
+
131
+ getAd(adKey: string): RewardedAdInstance | null {
132
+ return this.state.get(adKey) || null;
133
+ }
134
+
135
+ removeAd(adKey: string): void {
136
+ this.state.delete(adKey);
137
+ this.configs.delete(adKey);
138
+ this.loadPromises.delete(adKey);
139
+ this.emit('adRemoved', adKey);
140
+ }
141
+
142
+ async refreshAd(adKey: string): Promise<void> {
143
+ const config = this.configs.get(adKey);
144
+ if (!config) {
145
+ throw new Error(`Config for key "${adKey}" not found`);
146
+ }
147
+
148
+ console.log('Refresh ad:', adKey);
149
+
150
+ const ad = this.state.get(adKey);
151
+ if (ad) {
152
+ ad.status = AdStatus.IDLE;
153
+ ad.error = null;
154
+ ad.retryCount = 0;
155
+ }
156
+
157
+ return this.preloadAd(config); // Truyền config thay vì adKey, adId, config
158
+ }
159
+
160
+ clearAllAds(): void {
161
+ const keys = Array.from(this.state.keys());
162
+ keys.forEach((adKey) => this.removeAd(adKey));
163
+ this.emit('allAdsCleared');
164
+ }
165
+
166
+ private async loadAdInternal(adKey: string): Promise<void> {
167
+ const ad = this.state.get(adKey);
168
+ const config = this.configs.get(adKey);
169
+
170
+ if (!ad || !config) {
171
+ throw new Error(`Ad or config for key "${adKey}" not found`);
172
+ }
173
+
174
+ // Xác định adId sẽ được sử dụng
175
+ let adIdToLoad = config.adId;
176
+
177
+ // Nếu có adHighpriorityId và chưa thử load high priority
178
+ if (config.adHighpriorityId && !ad.hasTriedHighPriority) {
179
+ adIdToLoad = config.adHighpriorityId;
180
+ ad.isUsingHighPriority = true;
181
+ } else {
182
+ ad.isUsingHighPriority = false;
183
+ }
184
+
185
+ // Kiểm tra retry limit
186
+ if (ad.retryCount >= config.maxRetries!) {
187
+ // Nếu đang dùng high priority và đã hết retry, fallback về adId bình thường
188
+ if (ad.isUsingHighPriority) {
189
+ console.log(
190
+ `High priority ad failed after ${config.maxRetries} retries, falling back to normal ad`
191
+ );
192
+ ad.hasTriedHighPriority = true;
193
+ ad.retryCount = 0;
194
+ ad.isUsingHighPriority = false;
195
+ return this.loadAdInternal(adKey);
196
+ } else {
197
+ ad.status = AdStatus.ERROR;
198
+ ad.error = `Max retries (${config.maxRetries}) exceeded`;
199
+ this.emit('adError', ad);
200
+ return;
201
+ }
202
+ }
203
+
204
+ ad.status = AdStatus.LOADING;
205
+ ad.retryCount++;
206
+ this.emit('adLoading', ad);
207
+
208
+ try {
209
+ await googleMobileAdsManager.initialize();
210
+
211
+ const rewardedAd = await this.loadRewardedAd(adIdToLoad, config.timeout!);
212
+
213
+ ad.status = AdStatus.LOADED;
214
+ ad.rewardedAd = rewardedAd;
215
+ ad.error = null;
216
+ ad.loadTime = Date.now();
217
+ ad.retryCount = 0;
218
+
219
+ if (ad.isUsingHighPriority) {
220
+ ad.hasTriedHighPriority = true;
221
+ }
222
+
223
+ this.emit('adLoaded', ad);
224
+ } catch (error) {
225
+ ad.status = AdStatus.ERROR;
226
+ ad.error = error instanceof Error ? error.message : String(error);
227
+ this.emit('adError', ad);
228
+ throw error;
229
+ }
230
+ }
231
+
232
+ private async loadRewardedAd(adId: string, timeout: number): Promise<any> {
233
+ try {
234
+ const googleMobileAdsModule = await import(
235
+ 'react-native-google-mobile-ads'
236
+ );
237
+ const { RewardedAd, TestIds, RewardedAdEventType, AdEventType } =
238
+ googleMobileAdsModule;
239
+
240
+ const finalAdId = adId === 'test' ? TestIds.REWARDED : adId;
241
+
242
+ return new Promise((resolve, reject) => {
243
+ const timeoutId = setTimeout(() => {
244
+ reject(new Error(`Timeout loading rewarded ad after ${timeout}ms`));
245
+ }, timeout);
246
+
247
+ // Tạo rewarded ad instance
248
+ const rewardedAd = RewardedAd.createForAdRequest(finalAdId);
249
+
250
+ // Thêm event listeners
251
+ const unsubscribeLoaded = rewardedAd.addAdEventListener(
252
+ RewardedAdEventType.LOADED,
253
+ () => {
254
+ clearTimeout(timeoutId);
255
+ unsubscribeLoaded();
256
+ unsubscribeError();
257
+ resolve(rewardedAd);
258
+ }
259
+ );
260
+
261
+ const unsubscribeError = rewardedAd.addAdEventListener(
262
+ AdEventType.ERROR,
263
+ (error: any) => {
264
+ clearTimeout(timeoutId);
265
+ unsubscribeLoaded();
266
+ unsubscribeError();
267
+ reject(
268
+ new Error(`Failed to load rewarded ad: ${error.message || error}`)
269
+ );
270
+ }
271
+ );
272
+
273
+ // Bắt đầu load quảng cáo
274
+ rewardedAd.load();
275
+ });
276
+ } catch (error) {
277
+ console.warn('Failed to load rewarded ad:', error);
278
+ throw error;
279
+ }
280
+ }
281
+
282
+ private async showRewardedAd(ad: RewardedAdInstance): Promise<any> {
283
+ if (!ad.rewardedAd) {
284
+ throw new Error('Rewarded ad not loaded');
285
+ }
286
+
287
+ return new Promise((resolve, reject) => {
288
+ const googleMobileAdsModule = require('react-native-google-mobile-ads');
289
+ const { AdEventType, RewardedAdEventType } = googleMobileAdsModule;
290
+
291
+ let earnedReward: any = null;
292
+
293
+ // Thêm event listeners cho việc hiển thị
294
+ const unsubscribeEarnedReward = ad.rewardedAd.addAdEventListener(
295
+ RewardedAdEventType.EARNED_REWARD,
296
+ (reward: any) => {
297
+ earnedReward = reward;
298
+ // Emit sự kiện earnedReward
299
+ this.emit('adEarnedReward', { ad, reward });
300
+ }
301
+ );
302
+
303
+ const unsubscribeClosed = ad.rewardedAd.addAdEventListener(
304
+ AdEventType.CLOSED,
305
+ () => {
306
+ unsubscribeEarnedReward();
307
+ unsubscribeClosed();
308
+ unsubscribeError();
309
+ unsubscribeOpened();
310
+ unsubscribeClicked();
311
+
312
+ // Emit sự kiện adClosed
313
+ this.emit('adClosed', ad);
314
+ resolve(earnedReward);
315
+ }
316
+ );
317
+
318
+ const unsubscribeError = ad.rewardedAd.addAdEventListener(
319
+ AdEventType.ERROR,
320
+ (error: any) => {
321
+ unsubscribeEarnedReward();
322
+ unsubscribeClosed();
323
+ unsubscribeError();
324
+ unsubscribeOpened();
325
+ unsubscribeClicked();
326
+ reject(
327
+ new Error(`Failed to show rewarded ad: ${error.message || error}`)
328
+ );
329
+ }
330
+ );
331
+
332
+ const unsubscribeOpened = ad.rewardedAd.addAdEventListener(
333
+ AdEventType.OPENED,
334
+ () => {
335
+ // Emit sự kiện adOpened
336
+ this.emit('adOpened', ad);
337
+ }
338
+ );
339
+
340
+ const unsubscribeClicked = ad.rewardedAd.addAdEventListener(
341
+ AdEventType.CLICKED,
342
+ () => {
343
+ // Emit sự kiện adClicked
344
+ this.emit('adClicked', ad);
345
+ }
346
+ );
347
+
348
+ // Hiển thị quảng cáo
349
+ ad.rewardedAd.show();
350
+ });
351
+ }
352
+
353
+ private async waitForAdLoad(adKey: string): Promise<void> {
354
+ return new Promise((resolve, reject) => {
355
+ const timeout = setTimeout(() => {
356
+ reject(new Error(`Timeout waiting for rewarded ad "${adKey}" to load`));
357
+ }, 10000);
358
+
359
+ const checkAd = () => {
360
+ const ad = this.state.get(adKey);
361
+ if (!ad) {
362
+ clearTimeout(timeout);
363
+ reject(new Error(`Rewarded ad "${adKey}" not found`));
364
+ return;
365
+ }
366
+
367
+ if (ad.status === AdStatus.LOADED) {
368
+ clearTimeout(timeout);
369
+ resolve();
370
+ } else if (ad.status === AdStatus.ERROR) {
371
+ clearTimeout(timeout);
372
+ reject(new Error(ad.error || 'Unknown error'));
373
+ } else {
374
+ setTimeout(checkAd, 100);
375
+ }
376
+ };
377
+
378
+ checkAd();
379
+ });
380
+ }
381
+ }
382
+
383
+ export const rewardedAdsManager = new RewardedAdsManager();