@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,158 @@
1
+ import { StyleSheet, Dimensions } from 'react-native';
2
+
3
+ const { width, height } = Dimensions.get('window');
4
+
5
+ export const fullscreenStyles = StyleSheet.create({
6
+ container: {
7
+ flex: 1,
8
+ width: width,
9
+ height: height,
10
+ backgroundColor: '#000000',
11
+ justifyContent: 'center',
12
+ alignItems: 'center',
13
+ },
14
+ adContainer: {
15
+ flex: 1,
16
+ width: '100%',
17
+ height: '100%',
18
+ backgroundColor: '#000000',
19
+ },
20
+ centerContent: {
21
+ flex: 1,
22
+ justifyContent: 'center',
23
+ alignItems: 'center',
24
+ padding: 20,
25
+ },
26
+ closeButton: {
27
+ position: 'absolute',
28
+ top: 50,
29
+ right: 20,
30
+ width: 40,
31
+ height: 40,
32
+ borderRadius: 20,
33
+ backgroundColor: 'rgba(0, 0, 0, 0.6)',
34
+ justifyContent: 'center',
35
+ alignItems: 'center',
36
+ zIndex: 999,
37
+ },
38
+ closeButtonText: {
39
+ color: '#FFFFFF',
40
+ fontSize: 24,
41
+ fontWeight: '600',
42
+ },
43
+ loadingText: {
44
+ marginTop: 16,
45
+ fontSize: 16,
46
+ color: '#FFFFFF',
47
+ },
48
+ errorText: {
49
+ fontSize: 16,
50
+ color: '#FF3B30',
51
+ textAlign: 'center',
52
+ marginBottom: 16,
53
+ },
54
+ retryButton: {
55
+ backgroundColor: '#007AFF',
56
+ paddingHorizontal: 24,
57
+ paddingVertical: 12,
58
+ borderRadius: 8,
59
+ },
60
+ retryText: {
61
+ color: '#FFFFFF',
62
+ fontSize: 16,
63
+ fontWeight: '600',
64
+ },
65
+ emptyText: {
66
+ fontSize: 16,
67
+ color: '#999',
68
+ },
69
+ adHeader: {
70
+ position: 'absolute',
71
+ top: 50,
72
+ left: 20,
73
+ flexDirection: 'row',
74
+ alignItems: 'center',
75
+ backgroundColor: 'rgba(0, 0, 0, 0.7)',
76
+ paddingHorizontal: 12,
77
+ paddingVertical: 8,
78
+ borderRadius: 6,
79
+ zIndex: 998,
80
+ maxWidth: width - 100,
81
+ },
82
+ adBadge: {
83
+ backgroundColor: '#FFCC00',
84
+ paddingHorizontal: 8,
85
+ paddingVertical: 3,
86
+ borderRadius: 4,
87
+ fontSize: 11,
88
+ fontWeight: '700',
89
+ color: '#000',
90
+ },
91
+ advertiserText: {
92
+ fontSize: 12,
93
+ color: '#FFFFFF',
94
+ fontWeight: '500',
95
+ marginLeft: 10,
96
+ },
97
+ mediaView: {
98
+ width: '100%',
99
+ backgroundColor: '#1A1A1A',
100
+ },
101
+ contentContainer: {
102
+ position: 'absolute',
103
+ bottom: 0,
104
+ width: '100%',
105
+ backgroundColor: 'rgba(0, 0, 0, 0.85)',
106
+ paddingHorizontal: 20,
107
+ paddingVertical: 24,
108
+ paddingBottom: 40,
109
+ },
110
+ headline: {
111
+ fontSize: 22,
112
+ fontWeight: '700',
113
+ color: '#FFFFFF',
114
+ marginBottom: 8,
115
+ lineHeight: 28,
116
+ },
117
+ bodyText: {
118
+ fontSize: 15,
119
+ color: '#E0E0E0',
120
+ lineHeight: 20,
121
+ marginBottom: 12,
122
+ },
123
+ infoRow: {
124
+ flexDirection: 'row',
125
+ alignItems: 'center',
126
+ marginBottom: 16,
127
+ flexWrap: 'wrap',
128
+ gap: 12,
129
+ },
130
+ ratingText: {
131
+ fontSize: 14,
132
+ fontWeight: '600',
133
+ color: '#FF9500',
134
+ },
135
+ priceText: {
136
+ fontSize: 16,
137
+ fontWeight: '700',
138
+ color: '#34C759',
139
+ },
140
+ storeText: {
141
+ fontSize: 13,
142
+ color: '#AAAAAA',
143
+ flex: 1,
144
+ },
145
+ ctaButton: {
146
+ backgroundColor: '#007AFF',
147
+ paddingVertical: 14,
148
+ paddingHorizontal: 32,
149
+ borderRadius: 8,
150
+ alignItems: 'center',
151
+ justifyContent: 'center',
152
+ },
153
+ ctaText: {
154
+ fontSize: 16,
155
+ fontWeight: '700',
156
+ color: '#FFFFFF',
157
+ },
158
+ });
@@ -0,0 +1,208 @@
1
+ import React from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ ActivityIndicator,
6
+ TouchableOpacity,
7
+ type ViewStyle,
8
+ type TextStyle,
9
+ } from 'react-native';
10
+ import {
11
+ NativeAdView,
12
+ NativeAsset,
13
+ NativeMediaView,
14
+ NativeAssetType,
15
+ NativeAd,
16
+ } from 'react-native-google-mobile-ads';
17
+ import { useNativeAd } from '../hook/useNativeAd';
18
+ import type { AdInstance } from '../types/ads-types';
19
+ import { styles } from './NativeStyles';
20
+
21
+ interface NativeAdComponentProps {
22
+ adKey: string;
23
+ adId: string;
24
+ autoLoad?: boolean;
25
+ style?: ViewStyle;
26
+ onLoad?: (ad: AdInstance) => void;
27
+ onDisplay?: (ad: AdInstance) => void;
28
+ onError?: (error: string, ad: AdInstance) => void;
29
+ onClicked?: (ad: AdInstance) => void;
30
+ onImpression?: (ad: AdInstance) => void;
31
+ buttonActionStyles?: ViewStyle;
32
+ adBadgeStyles?: ViewStyle;
33
+ headlineStyles?: TextStyle;
34
+ bodyStyles?: TextStyle;
35
+ ratingStyles?: TextStyle;
36
+ priceStyles?: TextStyle;
37
+ storeStyles?: TextStyle;
38
+ }
39
+
40
+ export const NativeAdComponent: React.FC<NativeAdComponentProps> = ({
41
+ adKey,
42
+ adId,
43
+ autoLoad = true,
44
+ style,
45
+ onLoad,
46
+ onDisplay,
47
+ onError,
48
+ onClicked,
49
+ onImpression,
50
+ buttonActionStyles,
51
+ adBadgeStyles,
52
+ headlineStyles,
53
+ bodyStyles,
54
+ ratingStyles,
55
+ priceStyles,
56
+ storeStyles,
57
+ }) => {
58
+ const { ad, isLoading, error, isLoaded, loadAd } = useNativeAd({
59
+ adKey,
60
+ adId,
61
+ autoLoad,
62
+ onLoad,
63
+ onDisplay,
64
+ onError,
65
+ onClicked,
66
+ onImpression,
67
+ });
68
+
69
+ // Render loading state
70
+ if (isLoading) {
71
+ return (
72
+ <View style={[styles.wrapper, style]}>
73
+ <View style={[styles.container, styles.centerContent]}>
74
+ <ActivityIndicator size="small" color="#007AFF" />
75
+ <Text style={styles.loadingText}>Đang tải quảng cáo...</Text>
76
+ </View>
77
+ </View>
78
+ );
79
+ }
80
+
81
+ // Render error state
82
+ if (error) {
83
+ return (
84
+ <View style={[styles.wrapper, style]}>
85
+ <View style={[styles.container, styles.centerContent]}>
86
+ <Text style={styles.errorText}>Lỗi: {error}</Text>
87
+ <TouchableOpacity onPress={() => loadAd()} style={styles.retryButton}>
88
+ <Text style={styles.retryText}>Thử lại</Text>
89
+ </TouchableOpacity>
90
+ </View>
91
+ </View>
92
+ );
93
+ }
94
+
95
+ // Render empty state
96
+ if (!isLoaded || !ad?.data?.nativeAd) {
97
+ return (
98
+ <View style={[styles.wrapper, style]}>
99
+ <View style={[styles.container, styles.centerContent]}>
100
+ <Text style={styles.emptyText}>Không có quảng cáo</Text>
101
+ </View>
102
+ </View>
103
+ );
104
+ }
105
+
106
+ const nativeAd = ad.data.nativeAd as NativeAd;
107
+
108
+ return (
109
+ <View style={[styles.wrapper, style]}>
110
+ <NativeAdView nativeAd={nativeAd} style={[styles.container]}>
111
+ {/* Ad Badge và Advertiser */}
112
+ <View style={styles.adHeader}>
113
+ {/* <NativeAsset assetType={NativeAssetType.ADVERTISER}> */}
114
+ <Text style={[styles.adBadge, adBadgeStyles]}>Ad</Text>
115
+ {/* </NativeAsset> */}
116
+ {nativeAd.advertiser && (
117
+ <NativeAsset assetType={NativeAssetType.ADVERTISER}>
118
+ <Text style={styles.advertiserText} numberOfLines={1}>
119
+ {nativeAd.advertiser}
120
+ </Text>
121
+ </NativeAsset>
122
+ )}
123
+ </View>
124
+
125
+ {/* Media View - Hiển thị ảnh hoặc video */}
126
+ {((nativeAd.images?.length && nativeAd.images.length > 0) ||
127
+ nativeAd.mediaContent) && (
128
+ <NativeMediaView
129
+ style={[
130
+ styles.mediaView,
131
+ nativeAd.mediaContent?.aspectRatio
132
+ ? { aspectRatio: nativeAd.mediaContent.aspectRatio }
133
+ : { aspectRatio: 16 / 9 },
134
+ ]}
135
+ />
136
+ )}
137
+
138
+ {/* Ad Content */}
139
+ <View style={styles.contentContainer}>
140
+ {/* Headline */}
141
+ {nativeAd.headline && (
142
+ <NativeAsset assetType={NativeAssetType.HEADLINE}>
143
+ <Text style={[styles.headline, headlineStyles]} numberOfLines={2}>
144
+ {nativeAd.headline}
145
+ </Text>
146
+ </NativeAsset>
147
+ )}
148
+
149
+ {/* Body */}
150
+ {nativeAd.body && (
151
+ <NativeAsset assetType={NativeAssetType.BODY}>
152
+ <Text style={[styles.bodyText, bodyStyles]} numberOfLines={3}>
153
+ {nativeAd.body}
154
+ </Text>
155
+ </NativeAsset>
156
+ )}
157
+
158
+ {/* Rating, Price, Store Row */}
159
+ <View style={styles.infoRow}>
160
+ {/* Star Rating */}
161
+ {nativeAd.starRating !== null &&
162
+ nativeAd.starRating !== undefined && (
163
+ <NativeAsset assetType={NativeAssetType.STAR_RATING}>
164
+ <Text style={[styles.ratingText, ratingStyles]}>
165
+ ⭐ {nativeAd.starRating.toFixed(1)}
166
+ </Text>
167
+ </NativeAsset>
168
+ )}
169
+
170
+ {/* Price */}
171
+ {nativeAd.price && (
172
+ <NativeAsset assetType={NativeAssetType.PRICE}>
173
+ <Text style={[styles.priceText, priceStyles]}>
174
+ {nativeAd.price}
175
+ </Text>
176
+ </NativeAsset>
177
+ )}
178
+
179
+ {/* Store */}
180
+ {nativeAd.store && (
181
+ <NativeAsset assetType={NativeAssetType.STORE}>
182
+ <Text style={[styles.storeText, storeStyles]} numberOfLines={1}>
183
+ {nativeAd.store}
184
+ </Text>
185
+ </NativeAsset>
186
+ )}
187
+ </View>
188
+
189
+ {/* Call To Action Button */}
190
+ {nativeAd.callToAction && (
191
+ <NativeAsset assetType={NativeAssetType.CALL_TO_ACTION}>
192
+ <View style={[styles.ctaButton, buttonActionStyles]}>
193
+ <Text style={styles.ctaText}>{nativeAd.callToAction}</Text>
194
+ </View>
195
+ </NativeAsset>
196
+ )}
197
+ </View>
198
+
199
+ {/* Icon */}
200
+ {/* {nativeAd.icon && (
201
+ <NativeAsset assetType={NativeAssetType.ICON}>
202
+ <View style={styles.iconContainer} />
203
+ </NativeAsset>
204
+ )} */}
205
+ </NativeAdView>
206
+ </View>
207
+ );
208
+ };
@@ -0,0 +1,261 @@
1
+ import React from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ ActivityIndicator,
6
+ TouchableOpacity,
7
+ type ViewStyle,
8
+ type TextStyle,
9
+ Dimensions,
10
+ } from 'react-native';
11
+ import {
12
+ NativeAdView,
13
+ NativeAsset,
14
+ NativeMediaView,
15
+ NativeAssetType,
16
+ NativeAd,
17
+ } from 'react-native-google-mobile-ads';
18
+ import { useNativeAd } from '../hook/useNativeAd';
19
+ import type { AdInstance } from '../types/ads-types';
20
+ import { fullscreenStyles } from './FullscreenStyles';
21
+
22
+ const { height } = Dimensions.get('window');
23
+
24
+ interface NativeAdFullscreenComponentProps {
25
+ adKey: string;
26
+ adId: string;
27
+ autoLoad?: boolean;
28
+ onClose?: () => void;
29
+ onLoad?: (ad: AdInstance) => void;
30
+ onDisplay?: (ad: AdInstance) => void;
31
+ onError?: (error: string, ad: AdInstance) => void;
32
+ onClicked?: (ad: AdInstance) => void;
33
+ onImpression?: (ad: AdInstance) => void;
34
+ buttonActionStyles?: ViewStyle;
35
+ adBadgeStyles?: ViewStyle;
36
+ headlineStyles?: TextStyle;
37
+ bodyStyles?: TextStyle;
38
+ ratingStyles?: TextStyle;
39
+ priceStyles?: TextStyle;
40
+ storeStyles?: TextStyle;
41
+ closeButtonStyles?: ViewStyle;
42
+ showCloseButton?: boolean;
43
+ }
44
+
45
+ export const NativeAdFullscreenComponent: React.FC<
46
+ NativeAdFullscreenComponentProps
47
+ > = ({
48
+ adKey,
49
+ adId,
50
+ autoLoad = true,
51
+ onClose,
52
+ onLoad,
53
+ onDisplay,
54
+ onError,
55
+ onClicked,
56
+ onImpression,
57
+ buttonActionStyles,
58
+ adBadgeStyles,
59
+ headlineStyles,
60
+ bodyStyles,
61
+ ratingStyles,
62
+ priceStyles,
63
+ storeStyles,
64
+ closeButtonStyles,
65
+ showCloseButton = true,
66
+ }) => {
67
+ const { ad, isLoading, error, isLoaded, loadAd } = useNativeAd({
68
+ adKey,
69
+ adId,
70
+ autoLoad,
71
+ onLoad,
72
+ onDisplay,
73
+ onError,
74
+ onClicked,
75
+ onImpression,
76
+ });
77
+
78
+ // Render loading state
79
+ if (isLoading) {
80
+ return (
81
+ <View style={fullscreenStyles.container}>
82
+ {showCloseButton && onClose && (
83
+ <TouchableOpacity
84
+ style={[fullscreenStyles.closeButton, closeButtonStyles]}
85
+ onPress={onClose}
86
+ >
87
+ <Text style={fullscreenStyles.closeButtonText}>✕</Text>
88
+ </TouchableOpacity>
89
+ )}
90
+
91
+ <View style={fullscreenStyles.centerContent}>
92
+ <ActivityIndicator size="large" color="#FFFFFF" />
93
+ <Text style={fullscreenStyles.loadingText}>
94
+ Đang tải quảng cáo...
95
+ </Text>
96
+ </View>
97
+ </View>
98
+ );
99
+ }
100
+
101
+ // Render error state
102
+ if (error) {
103
+ return (
104
+ <View style={fullscreenStyles.container}>
105
+ {showCloseButton && onClose && (
106
+ <TouchableOpacity
107
+ style={[fullscreenStyles.closeButton, closeButtonStyles]}
108
+ onPress={onClose}
109
+ >
110
+ <Text style={fullscreenStyles.closeButtonText}>✕</Text>
111
+ </TouchableOpacity>
112
+ )}
113
+
114
+ <View style={fullscreenStyles.centerContent}>
115
+ <Text style={fullscreenStyles.errorText}>Lỗi: {error}</Text>
116
+ <TouchableOpacity
117
+ onPress={() => loadAd()}
118
+ style={fullscreenStyles.retryButton}
119
+ >
120
+ <Text style={fullscreenStyles.retryText}>Thử lại</Text>
121
+ </TouchableOpacity>
122
+ </View>
123
+ </View>
124
+ );
125
+ }
126
+
127
+ // Render empty state
128
+ if (!isLoaded || !ad?.data?.nativeAd) {
129
+ return (
130
+ <View style={fullscreenStyles.container}>
131
+ {showCloseButton && onClose && (
132
+ <TouchableOpacity
133
+ style={[fullscreenStyles.closeButton, closeButtonStyles]}
134
+ onPress={onClose}
135
+ >
136
+ <Text style={fullscreenStyles.closeButtonText}>✕</Text>
137
+ </TouchableOpacity>
138
+ )}
139
+
140
+ <View style={fullscreenStyles.centerContent}>
141
+ <Text style={fullscreenStyles.emptyText}>Không có quảng cáo</Text>
142
+ </View>
143
+ </View>
144
+ );
145
+ }
146
+
147
+ const nativeAd = ad.data.nativeAd as NativeAd;
148
+
149
+ return (
150
+ <View style={fullscreenStyles.container}>
151
+ <NativeAdView nativeAd={nativeAd} style={fullscreenStyles.adContainer}>
152
+ {/* Close Button */}
153
+ {showCloseButton && onClose && (
154
+ <TouchableOpacity
155
+ style={[fullscreenStyles.closeButton, closeButtonStyles]}
156
+ onPress={onClose}
157
+ >
158
+ <Text style={fullscreenStyles.closeButtonText}>✕</Text>
159
+ </TouchableOpacity>
160
+ )}
161
+
162
+ {/* Ad Badge và Advertiser - Top Overlay */}
163
+ <View style={fullscreenStyles.adHeader}>
164
+ <Text style={[fullscreenStyles.adBadge, adBadgeStyles]}>Ad</Text>
165
+ {nativeAd.advertiser && (
166
+ <NativeAsset assetType={NativeAssetType.ADVERTISER}>
167
+ <Text style={fullscreenStyles.advertiserText} numberOfLines={1}>
168
+ {nativeAd.advertiser}
169
+ </Text>
170
+ </NativeAsset>
171
+ )}
172
+ </View>
173
+
174
+ {/* Media View - Large, taking most of screen */}
175
+ {((nativeAd.images?.length && nativeAd.images.length > 0) ||
176
+ nativeAd.mediaContent) && (
177
+ <NativeMediaView
178
+ style={[
179
+ fullscreenStyles.mediaView,
180
+ nativeAd.mediaContent?.aspectRatio
181
+ ? { aspectRatio: nativeAd.mediaContent.aspectRatio }
182
+ : { height: height * 0.6 },
183
+ ]}
184
+ />
185
+ )}
186
+
187
+ {/* Content Area - Bottom Overlay */}
188
+ <View style={fullscreenStyles.contentContainer}>
189
+ {/* Headline */}
190
+ {nativeAd.headline && (
191
+ <NativeAsset assetType={NativeAssetType.HEADLINE}>
192
+ <Text
193
+ style={[fullscreenStyles.headline, headlineStyles]}
194
+ numberOfLines={2}
195
+ >
196
+ {nativeAd.headline}
197
+ </Text>
198
+ </NativeAsset>
199
+ )}
200
+
201
+ {/* Body */}
202
+ {nativeAd.body && (
203
+ <NativeAsset assetType={NativeAssetType.BODY}>
204
+ <Text
205
+ style={[fullscreenStyles.bodyText, bodyStyles]}
206
+ numberOfLines={3}
207
+ >
208
+ {nativeAd.body}
209
+ </Text>
210
+ </NativeAsset>
211
+ )}
212
+
213
+ {/* Rating, Price, Store Row */}
214
+ <View style={fullscreenStyles.infoRow}>
215
+ {/* Star Rating */}
216
+ {nativeAd.starRating !== null &&
217
+ nativeAd.starRating !== undefined && (
218
+ <NativeAsset assetType={NativeAssetType.STAR_RATING}>
219
+ <Text style={[fullscreenStyles.ratingText, ratingStyles]}>
220
+ ⭐ {nativeAd.starRating.toFixed(1)}
221
+ </Text>
222
+ </NativeAsset>
223
+ )}
224
+
225
+ {/* Price */}
226
+ {nativeAd.price && (
227
+ <NativeAsset assetType={NativeAssetType.PRICE}>
228
+ <Text style={[fullscreenStyles.priceText, priceStyles]}>
229
+ {nativeAd.price}
230
+ </Text>
231
+ </NativeAsset>
232
+ )}
233
+
234
+ {/* Store */}
235
+ {nativeAd.store && (
236
+ <NativeAsset assetType={NativeAssetType.STORE}>
237
+ <Text
238
+ style={[fullscreenStyles.storeText, storeStyles]}
239
+ numberOfLines={1}
240
+ >
241
+ {nativeAd.store}
242
+ </Text>
243
+ </NativeAsset>
244
+ )}
245
+ </View>
246
+
247
+ {/* Call To Action Button */}
248
+ {nativeAd.callToAction && (
249
+ <NativeAsset assetType={NativeAssetType.CALL_TO_ACTION}>
250
+ <View style={[fullscreenStyles.ctaButton, buttonActionStyles]}>
251
+ <Text style={fullscreenStyles.ctaText}>
252
+ {nativeAd.callToAction}
253
+ </Text>
254
+ </View>
255
+ </NativeAsset>
256
+ )}
257
+ </View>
258
+ </NativeAdView>
259
+ </View>
260
+ );
261
+ };