react-native-daro 1.0.13 → 1.0.16

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 (262) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +30 -30
  3. package/android/build.gradle +52 -59
  4. package/android/src/admob/java/com/daro/reactnative/DaroSdkBridge.kt +23 -0
  5. package/android/src/main/AndroidManifest.xml +1 -2
  6. package/android/src/main/java/com/{darom → daro/reactnative}/DaroMAdBannerViewManager.kt +38 -15
  7. package/android/src/main/java/com/daro/reactnative/DaroMAdNativeViewManager.kt +167 -0
  8. package/android/src/main/java/com/daro/reactnative/DaroMModule.kt +257 -0
  9. package/android/src/main/java/com/daro/reactnative/DaroMPackage.kt +45 -0
  10. package/android/src/main/java/com/daro/reactnative/DaroMediaViewManager.kt +25 -0
  11. package/android/src/main/java/com/{darom → daro/reactnative}/constants/InternalDaroMBannerSize.kt +1 -1
  12. package/android/src/main/java/com/{darom → daro/reactnative}/event/DaroMEvent.kt +19 -8
  13. package/android/src/main/java/com/{darom → daro/reactnative}/impl/DaroMBannerViewModuleImpl.kt +2 -2
  14. package/android/src/main/java/com/{darom → daro/reactnative}/impl/DaroMInterstitialModuleImpl.kt +26 -26
  15. package/android/src/main/java/com/{darom → daro/reactnative}/impl/DaroMLightPopupModuleImpl.kt +30 -29
  16. package/android/src/main/java/com/{darom → daro/reactnative}/impl/DaroMRewardedAdModuleImpl.kt +27 -27
  17. package/android/src/main/java/com/{darom → daro/reactnative}/util/AdInfoUtil.kt +25 -1
  18. package/android/src/main/java/com/daro/reactnative/util/EventEmitterUtil.kt +37 -0
  19. package/android/src/main/java/com/daro/reactnative/view/DaroMAdBannerViewContainer.kt +417 -0
  20. package/android/src/main/java/com/daro/reactnative/view/DaroMAdNativeViewContainer.kt +624 -0
  21. package/android/src/main/java/com/daro/reactnative/view/DaroMediaView.kt +123 -0
  22. package/android/src/newarch/java/com/daro/reactnative/DaroMModuleSpec.kt +6 -0
  23. package/android/src/oldarch/java/com/daro/reactnative/DaroMModuleSpec.kt +90 -0
  24. package/app.plugin.js +1 -0
  25. package/ios/DaroMModule+AppOpen.swift +38 -32
  26. package/ios/DaroMModule+Interstitial.swift +32 -26
  27. package/ios/DaroMModule+LightPopup.swift +43 -33
  28. package/ios/DaroMModule+Rewarded.swift +38 -27
  29. package/ios/DaroMModule.mm +45 -17
  30. package/ios/DaroMModule.swift +24 -17
  31. package/ios/Fabric/DaroMAdBannerComponentView.mm +207 -0
  32. package/ios/Fabric/DaroMFabricEventSink.mm +31 -0
  33. package/ios/Fabric/DaroMFabricPropApplier.mm +123 -0
  34. package/ios/Fabric/DaroMNativeAdComponentView.mm +294 -0
  35. package/ios/{DaroMAdBannerViewManager.m → Paper/DaroMAdBannerViewManager.m} +3 -1
  36. package/ios/Paper/DaroMAdBannerViewManager.swift +21 -0
  37. package/ios/{DaroMNativeAdViewManager.m → Paper/DaroMNativeAdViewManager.m} +2 -1
  38. package/ios/Paper/DaroMNativeAdViewManager.swift +22 -0
  39. package/ios/Shared/DaroMAdEventSink.swift +24 -0
  40. package/ios/Shared/DaroMBannerAdView.swift +188 -0
  41. package/ios/Shared/DaroMNativeAdLoadCoordinator.swift +49 -0
  42. package/ios/Shared/DaroMNativeAdView.swift +575 -0
  43. package/ios/Shared/DaroMNativeAssetResolver.swift +53 -0
  44. package/ios/mediation/admob/DaroMediationDebugger.swift +11 -0
  45. package/ios/mediation/admob/DaroMediationTypes.swift +23 -0
  46. package/lib/commonjs/AdBannerView.js +21 -35
  47. package/lib/commonjs/AdBannerView.js.map +1 -1
  48. package/lib/commonjs/AppOpenAd.js +80 -21
  49. package/lib/commonjs/AppOpenAd.js.map +1 -1
  50. package/lib/commonjs/DaroMAdBannerViewNativeComponent.ts +47 -0
  51. package/lib/commonjs/DaroMNativeAdViewNativeComponent.ts +62 -0
  52. package/lib/commonjs/DaroMediaViewNativeComponent.ts +9 -0
  53. package/lib/commonjs/ErrorCode.js.map +1 -1
  54. package/lib/commonjs/EventEmitter.js +4 -5
  55. package/lib/commonjs/EventEmitter.js.map +1 -1
  56. package/lib/commonjs/InterstitialAd.js +48 -22
  57. package/lib/commonjs/InterstitialAd.js.map +1 -1
  58. package/lib/commonjs/LightPopupAd.js +64 -46
  59. package/lib/commonjs/LightPopupAd.js.map +1 -1
  60. package/lib/commonjs/NativeDaroModule.js +9 -0
  61. package/lib/commonjs/NativeDaroModule.js.map +1 -0
  62. package/lib/commonjs/RewardedAd.js +47 -23
  63. package/lib/commonjs/RewardedAd.js.map +1 -1
  64. package/lib/commonjs/codegen-env.d.js +2 -0
  65. package/lib/commonjs/codegen-env.d.js.map +1 -0
  66. package/lib/commonjs/hooks/useInterstitialAd.js +110 -0
  67. package/lib/commonjs/hooks/useInterstitialAd.js.map +1 -0
  68. package/lib/commonjs/hooks/useLightPopupAd.js +114 -0
  69. package/lib/commonjs/hooks/useLightPopupAd.js.map +1 -0
  70. package/lib/commonjs/hooks/useRewardedAd.js +113 -0
  71. package/lib/commonjs/hooks/useRewardedAd.js.map +1 -0
  72. package/lib/commonjs/index.js +29 -13
  73. package/lib/commonjs/index.js.map +1 -1
  74. package/lib/commonjs/nativeAd/NativeAdView.js +23 -18
  75. package/lib/commonjs/nativeAd/NativeAdView.js.map +1 -1
  76. package/lib/commonjs/nativeAd/NativeAdViewComponents.js +43 -31
  77. package/lib/commonjs/nativeAd/NativeAdViewComponents.js.map +1 -1
  78. package/lib/commonjs/nativeAd/NativeAdViewProvider.js +34 -7
  79. package/lib/commonjs/nativeAd/NativeAdViewProvider.js.map +1 -1
  80. package/lib/commonjs/package.json +1 -0
  81. package/lib/module/AdBannerView.js +20 -36
  82. package/lib/module/AdBannerView.js.map +1 -1
  83. package/lib/module/AppOpenAd.js +80 -22
  84. package/lib/module/AppOpenAd.js.map +1 -1
  85. package/lib/module/DaroMAdBannerViewNativeComponent.ts +47 -0
  86. package/lib/module/DaroMNativeAdViewNativeComponent.ts +62 -0
  87. package/lib/module/DaroMediaViewNativeComponent.ts +9 -0
  88. package/lib/module/ErrorCode.js.map +1 -1
  89. package/lib/module/EventEmitter.js +4 -6
  90. package/lib/module/EventEmitter.js.map +1 -1
  91. package/lib/module/InterstitialAd.js +47 -22
  92. package/lib/module/InterstitialAd.js.map +1 -1
  93. package/lib/module/LightPopupAd.js +65 -47
  94. package/lib/module/LightPopupAd.js.map +1 -1
  95. package/lib/module/NativeDaroModule.js +5 -0
  96. package/lib/module/NativeDaroModule.js.map +1 -0
  97. package/lib/module/RewardedAd.js +46 -23
  98. package/lib/module/RewardedAd.js.map +1 -1
  99. package/lib/module/codegen-env.d.js +2 -0
  100. package/lib/module/codegen-env.d.js.map +1 -0
  101. package/lib/module/hooks/useInterstitialAd.js +106 -0
  102. package/lib/module/hooks/useInterstitialAd.js.map +1 -0
  103. package/lib/module/hooks/useLightPopupAd.js +110 -0
  104. package/lib/module/hooks/useLightPopupAd.js.map +1 -0
  105. package/lib/module/hooks/useRewardedAd.js +109 -0
  106. package/lib/module/hooks/useRewardedAd.js.map +1 -0
  107. package/lib/module/index.js +7 -13
  108. package/lib/module/index.js.map +1 -1
  109. package/lib/module/nativeAd/NativeAdView.js +22 -19
  110. package/lib/module/nativeAd/NativeAdView.js.map +1 -1
  111. package/lib/module/nativeAd/NativeAdViewComponents.js +45 -34
  112. package/lib/module/nativeAd/NativeAdViewComponents.js.map +1 -1
  113. package/lib/module/nativeAd/NativeAdViewProvider.js +35 -8
  114. package/lib/module/nativeAd/NativeAdViewProvider.js.map +1 -1
  115. package/lib/module/package.json +1 -0
  116. package/lib/typescript/commonjs/plugin/src/index.d.ts +19 -0
  117. package/lib/typescript/commonjs/plugin/src/index.d.ts.map +1 -0
  118. package/lib/typescript/commonjs/plugin/src/skAdNetworkIds.d.ts +6 -0
  119. package/lib/typescript/commonjs/plugin/src/skAdNetworkIds.d.ts.map +1 -0
  120. package/lib/typescript/commonjs/plugin/src/withAndroid.d.ts +8 -0
  121. package/lib/typescript/commonjs/plugin/src/withAndroid.d.ts.map +1 -0
  122. package/lib/typescript/commonjs/plugin/src/withIos.d.ts +8 -0
  123. package/lib/typescript/commonjs/plugin/src/withIos.d.ts.map +1 -0
  124. package/lib/typescript/commonjs/src/AdBannerView.d.ts +126 -4
  125. package/lib/typescript/commonjs/src/AdBannerView.d.ts.map +1 -1
  126. package/lib/typescript/commonjs/src/AppOpenAd.d.ts +6 -0
  127. package/lib/typescript/commonjs/src/AppOpenAd.d.ts.map +1 -1
  128. package/lib/typescript/commonjs/src/DaroMAdBannerViewNativeComponent.d.ts +32 -0
  129. package/lib/typescript/commonjs/src/DaroMAdBannerViewNativeComponent.d.ts.map +1 -0
  130. package/lib/typescript/commonjs/src/DaroMNativeAdViewNativeComponent.d.ts +42 -0
  131. package/lib/typescript/commonjs/src/DaroMNativeAdViewNativeComponent.d.ts.map +1 -0
  132. package/lib/typescript/commonjs/src/DaroMediaViewNativeComponent.d.ts +6 -0
  133. package/lib/typescript/commonjs/src/DaroMediaViewNativeComponent.d.ts.map +1 -0
  134. package/lib/typescript/commonjs/src/ErrorCode.d.ts.map +1 -1
  135. package/lib/typescript/commonjs/src/EventEmitter.d.ts.map +1 -1
  136. package/lib/typescript/commonjs/src/InterstitialAd.d.ts +6 -0
  137. package/lib/typescript/commonjs/src/InterstitialAd.d.ts.map +1 -1
  138. package/lib/typescript/commonjs/src/LightPopupAd.d.ts +6 -0
  139. package/lib/typescript/commonjs/src/LightPopupAd.d.ts.map +1 -1
  140. package/lib/typescript/commonjs/src/NativeDaroModule.d.ts +61 -0
  141. package/lib/typescript/commonjs/src/NativeDaroModule.d.ts.map +1 -0
  142. package/lib/typescript/commonjs/src/RewardedAd.d.ts +6 -0
  143. package/lib/typescript/commonjs/src/RewardedAd.d.ts.map +1 -1
  144. package/lib/typescript/commonjs/src/hooks/useInterstitialAd.d.ts +19 -0
  145. package/lib/typescript/commonjs/src/hooks/useInterstitialAd.d.ts.map +1 -0
  146. package/lib/typescript/commonjs/src/hooks/useLightPopupAd.d.ts +23 -0
  147. package/lib/typescript/commonjs/src/hooks/useLightPopupAd.d.ts.map +1 -0
  148. package/lib/typescript/commonjs/src/hooks/useRewardedAd.d.ts +20 -0
  149. package/lib/typescript/commonjs/src/hooks/useRewardedAd.d.ts.map +1 -0
  150. package/lib/typescript/commonjs/src/index.d.ts +7 -1
  151. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  152. package/lib/typescript/commonjs/src/nativeAd/NativeAdView.d.ts +125 -2
  153. package/lib/typescript/commonjs/src/nativeAd/NativeAdView.d.ts.map +1 -1
  154. package/lib/typescript/commonjs/src/nativeAd/NativeAdViewComponents.d.ts.map +1 -1
  155. package/lib/typescript/commonjs/src/nativeAd/NativeAdViewProvider.d.ts +11 -5
  156. package/lib/typescript/commonjs/src/nativeAd/NativeAdViewProvider.d.ts.map +1 -1
  157. package/lib/typescript/commonjs/src/types/AdBannerViewProps.d.ts +2 -2
  158. package/lib/typescript/commonjs/src/types/AdBannerViewProps.d.ts.map +1 -1
  159. package/lib/typescript/commonjs/src/types/AdInfo.d.ts.map +1 -1
  160. package/lib/typescript/commonjs/src/types/AdProps.d.ts +2 -2
  161. package/lib/typescript/commonjs/src/types/AdProps.d.ts.map +1 -1
  162. package/lib/typescript/commonjs/src/types/DaroMMobileAds.d.ts.map +1 -1
  163. package/lib/typescript/commonjs/src/types/NativeAdViewProps.d.ts +2 -0
  164. package/lib/typescript/commonjs/src/types/NativeAdViewProps.d.ts.map +1 -1
  165. package/lib/typescript/module/plugin/src/index.d.ts +19 -0
  166. package/lib/typescript/module/plugin/src/index.d.ts.map +1 -0
  167. package/lib/typescript/module/plugin/src/skAdNetworkIds.d.ts +6 -0
  168. package/lib/typescript/module/plugin/src/skAdNetworkIds.d.ts.map +1 -0
  169. package/lib/typescript/module/plugin/src/withAndroid.d.ts +8 -0
  170. package/lib/typescript/module/plugin/src/withAndroid.d.ts.map +1 -0
  171. package/lib/typescript/module/plugin/src/withIos.d.ts +8 -0
  172. package/lib/typescript/module/plugin/src/withIos.d.ts.map +1 -0
  173. package/lib/typescript/module/src/AdBannerView.d.ts +126 -4
  174. package/lib/typescript/module/src/AdBannerView.d.ts.map +1 -1
  175. package/lib/typescript/module/src/AppOpenAd.d.ts +6 -0
  176. package/lib/typescript/module/src/AppOpenAd.d.ts.map +1 -1
  177. package/lib/typescript/module/src/DaroMAdBannerViewNativeComponent.d.ts +32 -0
  178. package/lib/typescript/module/src/DaroMAdBannerViewNativeComponent.d.ts.map +1 -0
  179. package/lib/typescript/module/src/DaroMNativeAdViewNativeComponent.d.ts +42 -0
  180. package/lib/typescript/module/src/DaroMNativeAdViewNativeComponent.d.ts.map +1 -0
  181. package/lib/typescript/module/src/DaroMediaViewNativeComponent.d.ts +6 -0
  182. package/lib/typescript/module/src/DaroMediaViewNativeComponent.d.ts.map +1 -0
  183. package/lib/typescript/module/src/ErrorCode.d.ts.map +1 -1
  184. package/lib/typescript/module/src/EventEmitter.d.ts.map +1 -1
  185. package/lib/typescript/module/src/InterstitialAd.d.ts +6 -0
  186. package/lib/typescript/module/src/InterstitialAd.d.ts.map +1 -1
  187. package/lib/typescript/module/src/LightPopupAd.d.ts +6 -0
  188. package/lib/typescript/module/src/LightPopupAd.d.ts.map +1 -1
  189. package/lib/typescript/module/src/NativeDaroModule.d.ts +61 -0
  190. package/lib/typescript/module/src/NativeDaroModule.d.ts.map +1 -0
  191. package/lib/typescript/module/src/RewardedAd.d.ts +6 -0
  192. package/lib/typescript/module/src/RewardedAd.d.ts.map +1 -1
  193. package/lib/typescript/module/src/hooks/useInterstitialAd.d.ts +19 -0
  194. package/lib/typescript/module/src/hooks/useInterstitialAd.d.ts.map +1 -0
  195. package/lib/typescript/module/src/hooks/useLightPopupAd.d.ts +23 -0
  196. package/lib/typescript/module/src/hooks/useLightPopupAd.d.ts.map +1 -0
  197. package/lib/typescript/module/src/hooks/useRewardedAd.d.ts +20 -0
  198. package/lib/typescript/module/src/hooks/useRewardedAd.d.ts.map +1 -0
  199. package/lib/typescript/module/src/index.d.ts +7 -1
  200. package/lib/typescript/module/src/index.d.ts.map +1 -1
  201. package/lib/typescript/module/src/nativeAd/NativeAdView.d.ts +125 -2
  202. package/lib/typescript/module/src/nativeAd/NativeAdView.d.ts.map +1 -1
  203. package/lib/typescript/module/src/nativeAd/NativeAdViewComponents.d.ts.map +1 -1
  204. package/lib/typescript/module/src/nativeAd/NativeAdViewProvider.d.ts +11 -5
  205. package/lib/typescript/module/src/nativeAd/NativeAdViewProvider.d.ts.map +1 -1
  206. package/lib/typescript/module/src/types/AdBannerViewProps.d.ts +2 -2
  207. package/lib/typescript/module/src/types/AdBannerViewProps.d.ts.map +1 -1
  208. package/lib/typescript/module/src/types/AdInfo.d.ts.map +1 -1
  209. package/lib/typescript/module/src/types/AdProps.d.ts +2 -2
  210. package/lib/typescript/module/src/types/AdProps.d.ts.map +1 -1
  211. package/lib/typescript/module/src/types/DaroMMobileAds.d.ts.map +1 -1
  212. package/lib/typescript/module/src/types/NativeAdViewProps.d.ts +2 -0
  213. package/lib/typescript/module/src/types/NativeAdViewProps.d.ts.map +1 -1
  214. package/package.json +95 -105
  215. package/plugin/build/index.d.ts +18 -0
  216. package/plugin/build/index.js +71 -0
  217. package/plugin/build/skAdNetworkIds.d.ts +5 -0
  218. package/plugin/build/skAdNetworkIds.js +205 -0
  219. package/plugin/build/withAndroid.d.ts +7 -0
  220. package/plugin/build/withAndroid.js +222 -0
  221. package/plugin/build/withIos.d.ts +7 -0
  222. package/plugin/build/withIos.js +82 -0
  223. package/react-native-daro.podspec +28 -0
  224. package/src/AdBannerView.tsx +48 -48
  225. package/src/AppOpenAd.ts +101 -20
  226. package/src/DaroMAdBannerViewNativeComponent.ts +47 -0
  227. package/src/DaroMNativeAdViewNativeComponent.ts +62 -0
  228. package/src/DaroMediaViewNativeComponent.ts +9 -0
  229. package/src/ErrorCode.ts +1 -2
  230. package/src/EventEmitter.ts +9 -7
  231. package/src/InterstitialAd.ts +75 -21
  232. package/src/LightPopupAd.ts +90 -51
  233. package/src/NativeDaroModule.ts +91 -0
  234. package/src/RewardedAd.ts +72 -22
  235. package/src/codegen-env.d.ts +45 -0
  236. package/src/hooks/useInterstitialAd.ts +117 -0
  237. package/src/hooks/useLightPopupAd.ts +132 -0
  238. package/src/hooks/useRewardedAd.ts +122 -0
  239. package/src/index.tsx +21 -22
  240. package/src/nativeAd/NativeAdView.tsx +83 -45
  241. package/src/nativeAd/NativeAdViewComponents.tsx +129 -64
  242. package/src/nativeAd/NativeAdViewProvider.tsx +84 -16
  243. package/src/types/AdBannerViewProps.ts +11 -11
  244. package/src/types/AdInfo.ts +17 -17
  245. package/src/types/AdProps.ts +8 -9
  246. package/src/types/DaroMMobileAds.ts +3 -6
  247. package/src/types/NativeAdViewProps.ts +12 -5
  248. package/src/types/index.ts +1 -1
  249. package/android/gradle.properties +0 -5
  250. package/android/src/main/AndroidManifestNew.xml +0 -7
  251. package/android/src/main/java/com/darom/DaroMAdNativeViewManager.kt +0 -136
  252. package/android/src/main/java/com/darom/DaroMModule.kt +0 -203
  253. package/android/src/main/java/com/darom/DaroMPackage.kt +0 -21
  254. package/android/src/main/java/com/darom/util/EventEmitterUtil.kt +0 -24
  255. package/android/src/main/java/com/darom/view/DaroMAdBannerViewContainer.kt +0 -163
  256. package/android/src/main/java/com/darom/view/DaroMAdNativeViewContainer.kt +0 -375
  257. package/android/src/main/res/layout/layout_activity_transparent.xml +0 -7
  258. package/android/src/main/res/values/styles.xml +0 -11
  259. package/ios/DaroM-Bridging-Header.h +0 -6
  260. package/ios/DaroMAdBannerViewManager.swift +0 -91
  261. package/ios/DaroMNativeAdViewManager.swift +0 -291
  262. package/react-native-daro-m.podspec +0 -44
@@ -0,0 +1,624 @@
1
+ package com.daro.reactnative.view
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.os.Handler
5
+ import android.os.Looper
6
+ import android.text.SpannableString
7
+ import android.text.Spanned
8
+ import android.view.View
9
+ import android.view.ViewGroup
10
+ import android.widget.FrameLayout
11
+ import android.widget.ImageView
12
+ import android.widget.TextView
13
+ import androidx.annotation.IdRes
14
+ import androidx.core.view.children
15
+ import com.daro.reactnative.event.AdViewEvent
16
+ import com.daro.reactnative.util.AdInfoUtil
17
+ import com.daro.reactnative.util.EventEmitterUtil.sendNativeViewEvent
18
+ import com.facebook.react.bridge.ReactContext
19
+ import com.facebook.react.views.text.ReactTextView
20
+ import com.facebook.react.views.view.ReactViewGroup
21
+ import droom.daro.core.adunit.DaroNativeAdUnit
22
+ import droom.daro.core.model.DaroAdInfo
23
+ import droom.daro.core.model.DaroAdLoadError
24
+ import droom.daro.core.model.DaroNativeAdBinder
25
+ import droom.daro.core.model.DaroNativeAdChoicePlacement
26
+ import droom.daro.core.model.DaroViewAd
27
+ import droom.daro.view.DaroAdViewListener
28
+ import droom.daro.view.DaroNativeAdView
29
+ import kotlin.math.min
30
+ import kotlin.math.roundToInt
31
+
32
+
33
+ @SuppressLint("ViewConstructor")
34
+ class DaroMAdNativeViewContainer(val context: ReactContext) : ReactViewGroup(context),
35
+ DaroAdViewListener {
36
+
37
+ private companion object {
38
+ private const val MAX_LOAD_ASSET_VIEW_RETRY_COUNT = 40
39
+ private const val LOAD_ASSET_VIEW_RETRY_DELAY_MS = 50L
40
+ }
41
+
42
+ private val adViewContainer: ReactViewGroup = ReactViewGroup(context)
43
+
44
+ init {
45
+ post {
46
+ setOnClickListener {
47
+ adView?.performClick()
48
+ }
49
+ }
50
+ }
51
+
52
+ private var adView: DaroNativeAdView? = null
53
+
54
+ internal var adUnitId: String = ""
55
+
56
+ internal var loadOnMount: Boolean = true
57
+ private var adChoicesPosition: DaroNativeAdChoicePlacement =
58
+ DaroNativeAdChoicePlacement.BOTTOM_RIGHT
59
+
60
+ private var isFirstLoad: Boolean = true
61
+ private var isDestroyed: Boolean = false
62
+ private var pendingLoadAssetViewRetryCount: Int = 0
63
+
64
+ fun addReactSubview(child: View, index: Int) {
65
+ if (isDestroyed) return
66
+
67
+ if (index < 0 || index >= adViewContainer.childCount) {
68
+ adViewContainer.addView(child)
69
+ } else {
70
+ adViewContainer.addView(child, index)
71
+ }
72
+
73
+ scheduleInitialLoadIfNeeded()
74
+ }
75
+
76
+ fun getReactSubviewCount(): Int {
77
+ if (isDestroyed) return 0
78
+
79
+ return adViewContainer.childCount
80
+ }
81
+
82
+ fun getReactSubviewAt(index: Int): View {
83
+ return adViewContainer.getChildAt(index)
84
+ }
85
+
86
+ fun removeReactSubviewAt(index: Int) {
87
+ if (isDestroyed || index < 0 || index >= adViewContainer.childCount) return
88
+
89
+ adViewContainer.removeViewAt(index)
90
+ }
91
+
92
+ fun removeAllReactSubviews() {
93
+ if (isDestroyed) return
94
+
95
+ adViewContainer.removeAllViews()
96
+ }
97
+
98
+ fun loadAd(): Boolean {
99
+ if (isDestroyed) return false
100
+
101
+ if (!hasRegisteredAssetView()) {
102
+ scheduleLoadWhenAssetViewsMounted()
103
+ return false
104
+ }
105
+
106
+ if (!areRegisteredAssetViewsMounted()) {
107
+ scheduleLoadWhenAssetViewsMounted()
108
+ return false
109
+ }
110
+
111
+ pendingLoadAssetViewRetryCount = 0
112
+ captureRegisteredTextSpans()
113
+
114
+ return (adView ?: buildAdView())?.let { view ->
115
+
116
+ adView = view
117
+
118
+ if (view.parent == null) {
119
+ this@DaroMAdNativeViewContainer.addView(view)
120
+ }
121
+
122
+ view.loadAd()
123
+ isFirstLoad = false
124
+ true
125
+ } ?: false
126
+ }
127
+
128
+ private fun buildAdView(): DaroNativeAdView? {
129
+ if (adUnitId.isEmpty()) {
130
+ return null
131
+ }
132
+
133
+ return DaroNativeAdView(
134
+ context,
135
+ DaroNativeAdUnit(
136
+ key = adUnitId,
137
+ placement = adUnitId,
138
+ )
139
+ ).also { view ->
140
+ view.setAdBinder(
141
+ DaroNativeAdBinder
142
+ .Builder(adViewContainer)
143
+ .let { if (titleViewId != null) it.setTitleViewId(titleViewId!!) else it }
144
+ .let { if (bodyViewId != null) it.setBodyTextViewId(bodyViewId!!) else it }
145
+ .let { if (iconViewId != null) it.setIconViewId(iconViewId!!) else it }
146
+ .let { builder ->
147
+ // 등록 누락 시 더미 뷰에 바인딩되지 않도록 DaroMediaView를 직접 찾아 폴백한다.
148
+ val mediaId = mediaViewId ?: findDaroMediaViewId()
149
+ if (mediaId != null) builder.setMediaViewGroupId(mediaId) else builder
150
+ }
151
+ .let { if (callToActionViewId != null) it.setCallToActionViewId(callToActionViewId!!) else it }
152
+ .setAdChoicePlacement(adChoicesPosition)
153
+ .build()
154
+ )
155
+
156
+ view.setListener(this)
157
+ view.setOnHierarchyChangeListener(
158
+ object : OnHierarchyChangeListener {
159
+ override fun onChildViewAdded(parent: View?, child: View?) {
160
+ if (child != null && parent != null) {
161
+ view.layoutParams = LayoutParams(
162
+ LayoutParams.WRAP_CONTENT,
163
+ LayoutParams.WRAP_CONTENT,
164
+ )
165
+ view.layout(0, 0, parent.width, parent.height)
166
+ }
167
+ }
168
+
169
+ override fun onChildViewRemoved(parent: View?, child: View?) {}
170
+ }
171
+ )
172
+ }
173
+ }
174
+
175
+ fun destroy() {
176
+ isDestroyed = true
177
+ loadAdHandler.removeCallbacksAndMessages(null)
178
+ setOnClickListener(null)
179
+
180
+ adView?.let { view ->
181
+ (view.parent as? ViewGroup)?.removeView(view)
182
+ view.destroy()
183
+ installFallbackAssetViews()
184
+ }
185
+ adView = null
186
+ pendingLoadAssetViewRetryCount = 0
187
+ removeAllViews()
188
+ testSpanMap.clear()
189
+ }
190
+
191
+ override fun onAttachedToWindow() {
192
+ super.onAttachedToWindow()
193
+ if (!isDestroyed) {
194
+ adView?.resume()
195
+ }
196
+ }
197
+
198
+ override fun onAdLoadSuccess(
199
+ ad: DaroViewAd,
200
+ adInfo: DaroAdInfo,
201
+ ) {
202
+ if (isDestroyed) return
203
+
204
+ sendNativeViewEvent(
205
+ reactContext = context,
206
+ event = AdViewEvent.ON_AD_LOADED,
207
+ params = AdInfoUtil.getAdInfo(adUnitId, adInfo)
208
+ )
209
+
210
+ post({
211
+ layoutMediaViewChildrenFallback()
212
+ context.currentActivity?.window.let { window ->
213
+ window?.decorView?.requestLayout()
214
+ }
215
+ })
216
+ }
217
+
218
+ override fun onAdLoadFail(err: DaroAdLoadError) {
219
+ if (isDestroyed) return
220
+
221
+ sendNativeViewEvent(
222
+ reactContext = context,
223
+ event = AdViewEvent.ON_AD_FAILED_TO_LOAD,
224
+ params = AdInfoUtil.getAdLoadFailedInfo(adUnitId, err)
225
+ )
226
+ }
227
+
228
+ override fun onAdClicked(adInfo: DaroAdInfo) {
229
+ if (isDestroyed) return
230
+
231
+ sendNativeViewEvent(
232
+ reactContext = context,
233
+ event = AdViewEvent.ON_AD_CLICKED,
234
+ params = AdInfoUtil.getAdInfo(adUnitId, adInfo)
235
+ )
236
+ }
237
+
238
+ override fun onAdImpression(adInfo: DaroAdInfo) {
239
+ if (isDestroyed) return
240
+
241
+ sendNativeViewEvent(
242
+ reactContext = context,
243
+ event = AdViewEvent.ON_AD_IMPRESSION,
244
+ params = AdInfoUtil.getAdInfo(adUnitId, adInfo)
245
+ )
246
+ }
247
+
248
+ private val loadAdHandler = Handler(Looper.getMainLooper())
249
+ private val loadAdTask = LoadAdTask(this)
250
+ private val retryLoadAdTask = Runnable {
251
+ if (!isDestroyed) {
252
+ loadAd()
253
+ }
254
+ }
255
+
256
+ private inner class LoadAdTask(private val nativeAdView: DaroMAdNativeViewContainer) :
257
+ Runnable {
258
+
259
+ override fun run() {
260
+ nativeAdView.loadAd()
261
+ }
262
+ }
263
+
264
+ internal fun onSetProps() {
265
+ if (isDestroyed) return
266
+
267
+ scheduleInitialLoadIfNeeded()
268
+ }
269
+
270
+ private fun scheduleInitialLoadIfNeeded() {
271
+ loadAdHandler.removeCallbacks(loadAdTask)
272
+
273
+ if (loadOnMount && isFirstLoad && adUnitId.isNotEmpty() && hasRegisteredAssetView()) {
274
+ loadAdHandler.postDelayed(loadAdTask, 50)
275
+ }
276
+ }
277
+
278
+ override fun requestLayout() {
279
+ super.requestLayout()
280
+
281
+ // https://stackoverflow.com/a/39838774/5477988
282
+ // This is required to ensure ad refreshes render correctly in RN Android due to known issue
283
+ // where `getWidth()` and `getHeight()` return 0 on attach
284
+ try {
285
+ adView?.measure(
286
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
287
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
288
+ )
289
+
290
+ adView?.layout(0, 0, width, height)
291
+ } catch (_: Exception) {
292
+ // Ignore
293
+ }
294
+
295
+ try {
296
+ adViewContainer.parent?.let {
297
+ (it as ViewGroup).children.filter { it != adViewContainer && it is ViewGroup }.lastOrNull()
298
+ ?.let {
299
+ it.measure(
300
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
301
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
302
+ )
303
+
304
+ it.layout(0, 0, width, height)
305
+
306
+ findImageView(it as ViewGroup)?.let { adChoiceImageView ->
307
+ if ((adChoiceImageView.parent as View).measuredWidth == adChoiceImageView.measuredWidth) return@let
308
+
309
+ val adChoiceDrawable = adChoiceImageView.drawable ?: return@let
310
+
311
+ val ratio =
312
+ adChoiceDrawable.intrinsicHeight.toFloat() / (adChoiceImageView.parent as View).height
313
+
314
+ val w = ((adChoiceImageView.parent as View).width * ratio).roundToInt()
315
+ val h = ((adChoiceImageView.parent as View).height * ratio).roundToInt()
316
+
317
+ it.measure(
318
+ MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
319
+ MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)
320
+ )
321
+
322
+ it.layout(width - w, 0, width, height)
323
+
324
+ (adChoiceImageView.parent as View).let { v ->
325
+ v.measure(
326
+ MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
327
+ MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)
328
+ )
329
+
330
+ v.layout(0, 0, w, h)
331
+ }
332
+ }
333
+ }
334
+ }
335
+ } catch (_: Exception) {
336
+ // Ignore
337
+ }
338
+
339
+ try {
340
+ layoutMediaViewChildrenFallback()
341
+ } catch (_: Exception) {
342
+ // Ignore
343
+ }
344
+
345
+ try {
346
+ restoreRegisteredTextSpans()
347
+ } catch (_: Exception) {
348
+ // Ignore
349
+ }
350
+ }
351
+
352
+ private fun findImageView(root: ViewGroup): ImageView? {
353
+ for (i in 0 until root.childCount) {
354
+ val child = root.getChildAt(i)
355
+ if (child is ImageView) {
356
+ return child
357
+ } else if (child is ViewGroup) {
358
+ val result = findImageView(child)
359
+ if (result != null) return result
360
+ }
361
+ }
362
+ return null
363
+ }
364
+
365
+ // 미디어 그룹이 DaroMediaView가 아닌 경우(구버전 JS 조합)용 직계 자식 폴백.
366
+ private fun layoutMediaViewChildrenFallback() {
367
+ val mediaViewGroup = getMediaViewGroup() ?: return
368
+ if (mediaViewGroup is DaroMediaView) return
369
+
370
+ val width = mediaViewGroup.width
371
+ val height = mediaViewGroup.height
372
+
373
+ if (width <= 0 || height <= 0) return
374
+
375
+ mediaViewGroup.children.forEach { child ->
376
+ child.measure(
377
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
378
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
379
+ )
380
+
381
+ child.layout(0, 0, width, height)
382
+ }
383
+ }
384
+
385
+ private fun findDaroMediaViewId(): Int? {
386
+ return findDaroMediaView(adViewContainer)?.id?.takeIf { it != View.NO_ID }
387
+ }
388
+
389
+ private fun findDaroMediaView(root: ViewGroup): DaroMediaView? {
390
+ root.children.forEach { child ->
391
+ if (child is DaroMediaView) return child
392
+ if (child is ViewGroup) findDaroMediaView(child)?.let { return it }
393
+ }
394
+ return null
395
+ }
396
+
397
+ private fun getMediaViewGroup(): ViewGroup? {
398
+ return mediaViewId?.let { findRegisteredAssetView(it) as? ViewGroup }
399
+ }
400
+
401
+ private fun hasRegisteredAssetView(): Boolean {
402
+ return titleViewId != null ||
403
+ bodyViewId != null ||
404
+ callToActionViewId != null ||
405
+ iconViewId != null ||
406
+ mediaViewId != null
407
+ }
408
+
409
+ private fun areRegisteredAssetViewsMounted(): Boolean {
410
+ if (!hasRegisteredAssetView()) return false
411
+
412
+ titleViewId?.let {
413
+ if (findRegisteredAssetView(it) !is TextView) return false
414
+ }
415
+
416
+ bodyViewId?.let {
417
+ if (findRegisteredAssetView(it) !is TextView) return false
418
+ }
419
+
420
+ callToActionViewId?.let {
421
+ if (findRegisteredAssetView(it) !is TextView) return false
422
+ }
423
+
424
+ iconViewId?.let {
425
+ if (findRegisteredAssetView(it) !is ImageView) return false
426
+ }
427
+
428
+ mediaViewId?.let {
429
+ if (findRegisteredAssetView(it) !is ViewGroup) return false
430
+ }
431
+
432
+ return true
433
+ }
434
+
435
+ private fun findRegisteredAssetView(@IdRes id: Int): View? {
436
+ return adViewContainer.findViewById(id)
437
+ }
438
+
439
+ private fun scheduleLoadWhenAssetViewsMounted() {
440
+ if (pendingLoadAssetViewRetryCount >= MAX_LOAD_ASSET_VIEW_RETRY_COUNT) {
441
+ pendingLoadAssetViewRetryCount = 0
442
+ return
443
+ }
444
+
445
+ pendingLoadAssetViewRetryCount += 1
446
+ loadAdHandler.removeCallbacks(retryLoadAdTask)
447
+ loadAdHandler.postDelayed(retryLoadAdTask, LOAD_ASSET_VIEW_RETRY_DELAY_MS)
448
+ }
449
+
450
+ private fun cancelPendingLoadIfNoRegisteredAssetView() {
451
+ if (hasRegisteredAssetView()) return
452
+
453
+ pendingLoadAssetViewRetryCount = 0
454
+ loadAdHandler.removeCallbacks(loadAdTask)
455
+ loadAdHandler.removeCallbacks(retryLoadAdTask)
456
+ }
457
+
458
+ /*
459
+ * Mapping View
460
+ * */
461
+
462
+ @IdRes
463
+ private var titleViewId: Int? = null
464
+
465
+ @IdRes
466
+ private var bodyViewId: Int? = null
467
+
468
+ @IdRes
469
+ private var callToActionViewId: Int? = null
470
+
471
+ @IdRes
472
+ private var iconViewId: Int? = null
473
+
474
+ @IdRes
475
+ private var mediaViewId: Int? = null
476
+
477
+ fun setTitleView(tag: Int) {
478
+ if (tag == View.NO_ID || tag == 0) {
479
+ titleViewId = null
480
+ cancelPendingLoadIfNoRegisteredAssetView()
481
+ return
482
+ }
483
+
484
+ if (titleViewId == tag) return
485
+
486
+ this.titleViewId = tag
487
+ adViewContainer.findViewById<ReactTextView>(tag)?.let {
488
+ it.saveSpannableToMap()
489
+ }
490
+ scheduleInitialLoadIfNeeded()
491
+ }
492
+
493
+ fun setBodyView(tag: Int) {
494
+ if (tag == View.NO_ID || tag == 0) {
495
+ bodyViewId = null
496
+ cancelPendingLoadIfNoRegisteredAssetView()
497
+ return
498
+ }
499
+
500
+ if (bodyViewId == tag) return
501
+
502
+ this.bodyViewId = tag
503
+ adViewContainer.findViewById<ReactTextView>(tag)?.let {
504
+ it.saveSpannableToMap()
505
+ }
506
+ scheduleInitialLoadIfNeeded()
507
+ }
508
+
509
+ fun setCallToActionView(tag: Int) {
510
+ if (tag == View.NO_ID || tag == 0) {
511
+ callToActionViewId = null
512
+ cancelPendingLoadIfNoRegisteredAssetView()
513
+ return
514
+ }
515
+
516
+ if (callToActionViewId == tag) return
517
+
518
+ this.callToActionViewId = tag
519
+ adViewContainer.findViewById<ReactTextView>(tag)?.let {
520
+ it.saveSpannableToMap()
521
+ }
522
+ scheduleInitialLoadIfNeeded()
523
+ }
524
+
525
+ fun setIconView(tag: Int) {
526
+ if (tag == View.NO_ID || tag == 0) {
527
+ iconViewId = null
528
+ cancelPendingLoadIfNoRegisteredAssetView()
529
+ return
530
+ }
531
+
532
+ if (iconViewId == tag) return
533
+
534
+ this.iconViewId = tag
535
+ scheduleInitialLoadIfNeeded()
536
+ }
537
+
538
+ fun setMediaView(tag: Int) {
539
+ if (tag == View.NO_ID || tag == 0) {
540
+ mediaViewId = null
541
+ cancelPendingLoadIfNoRegisteredAssetView()
542
+ return
543
+ }
544
+
545
+ if (mediaViewId == tag) return
546
+
547
+ this.mediaViewId = tag
548
+ scheduleInitialLoadIfNeeded()
549
+ }
550
+
551
+ fun setAdChoicesPosition(value: String?) {
552
+ adChoicesPosition = when (value) {
553
+ "topLeft" -> DaroNativeAdChoicePlacement.TOP_LEFT
554
+ "topRight" -> DaroNativeAdChoicePlacement.TOP_RIGHT
555
+ "bottomLeft" -> DaroNativeAdChoicePlacement.BOTTOM_LEFT
556
+ else -> DaroNativeAdChoicePlacement.BOTTOM_RIGHT
557
+ }
558
+ }
559
+
560
+ /*
561
+ * Setting View
562
+ * */
563
+
564
+ private fun installFallbackAssetViews() {
565
+ adViewContainer.removeAllViews()
566
+
567
+ titleViewId?.let { adViewContainer.addView(TextView(context).apply { id = it }) }
568
+ bodyViewId?.let { adViewContainer.addView(TextView(context).apply { id = it }) }
569
+ callToActionViewId?.let { adViewContainer.addView(TextView(context).apply { id = it }) }
570
+ iconViewId?.let { adViewContainer.addView(ImageView(context).apply { id = it }) }
571
+ mediaViewId?.let { adViewContainer.addView(FrameLayout(context).apply { id = it }) }
572
+ }
573
+
574
+ private val testSpanMap: MutableMap<Int, Spanned> = mutableMapOf()
575
+
576
+ private fun captureRegisteredTextSpans() {
577
+ titleViewId?.let { adViewContainer.findViewById<ReactTextView>(it) }?.saveSpannableToMap()
578
+ bodyViewId?.let { adViewContainer.findViewById<ReactTextView>(it) }?.saveSpannableToMap()
579
+ callToActionViewId?.let { adViewContainer.findViewById<ReactTextView>(it) }
580
+ ?.saveSpannableToMap()
581
+ }
582
+
583
+ private fun restoreRegisteredTextSpans() {
584
+ titleViewId?.let { adViewContainer.findViewById<ReactTextView>(it) }?.restoreSpannableFromMap()
585
+ bodyViewId?.let { adViewContainer.findViewById<ReactTextView>(it) }?.restoreSpannableFromMap()
586
+ callToActionViewId?.let { adViewContainer.findViewById<ReactTextView>(it) }
587
+ ?.restoreSpannableFromMap()
588
+ }
589
+
590
+ private fun ReactTextView.saveSpannableToMap() {
591
+ val text: CharSequence? = getText()
592
+
593
+ if (text is Spanned) {
594
+ testSpanMap[id] = text
595
+ }
596
+ }
597
+
598
+ private fun ReactTextView.restoreSpannableFromMap() {
599
+ testSpanMap[id]?.let {
600
+ val newSpannable = replaceTextPreserveSpans(it, text.toString())
601
+ text = newSpannable
602
+ }
603
+ }
604
+
605
+ fun replaceTextPreserveSpans(oldSpanned: Spanned, newText: String): SpannableString {
606
+ val newSpannable = SpannableString(newText)
607
+
608
+ val spans = oldSpanned.getSpans<Any>(0, oldSpanned.length, Any::class.java)
609
+ for (span in spans) {
610
+ val start = oldSpanned.getSpanStart(span)
611
+ val end = oldSpanned.getSpanEnd(span)
612
+ val flags = oldSpanned.getSpanFlags(span)
613
+
614
+ val newStart = start.coerceAtMost(newText.length)
615
+ val newEnd = if (end == oldSpanned.length) newText.length else min(end, newText.length)
616
+
617
+ if (newStart < newEnd) {
618
+ newSpannable.setSpan(span, newStart, newEnd, flags)
619
+ }
620
+ }
621
+
622
+ return newSpannable
623
+ }
624
+ }