react-native-firework-sdk 2.8.6 → 2.10.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.
Files changed (89) hide show
  1. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/FireworkVideoUI +0 -0
  2. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Info.plist +0 -0
  3. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/FireworkVideoUI +0 -0
  4. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Info.plist +0 -0
  5. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/_CodeSignature/CodeResources +1 -1
  6. package/android/build.gradle +2 -1
  7. package/android/gradle.properties +1 -1
  8. package/android/src/main/java/com/fireworksdk/bridge/components/base/FWLoading.kt +22 -0
  9. package/android/src/main/java/com/fireworksdk/bridge/components/storyblock/StoryBlockFragment.kt +240 -18
  10. package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/FWVideoFeed.kt +19 -9
  11. package/android/src/main/java/com/fireworksdk/bridge/models/FWAdConfigurationDeserializer.kt +49 -0
  12. package/android/src/main/java/com/fireworksdk/bridge/models/FWAdConfigurationModel.kt +13 -0
  13. package/android/src/main/java/com/fireworksdk/bridge/models/FWAdConfigurationSerializer.kt +42 -0
  14. package/android/src/main/java/com/fireworksdk/bridge/models/FWButtonInfoDeserializer.kt +21 -0
  15. package/android/src/main/java/com/fireworksdk/bridge/models/FWButtonInfoModel.kt +6 -0
  16. package/android/src/main/java/com/fireworksdk/bridge/models/FWButtonInfoSerializer.kt +17 -0
  17. package/android/src/main/java/com/fireworksdk/bridge/models/FWPlayerButtonConfigurationDeserializer.kt +33 -0
  18. package/android/src/main/java/com/fireworksdk/bridge/models/FWPlayerButtonConfigurationModel.kt +10 -0
  19. package/android/src/main/java/com/fireworksdk/bridge/models/FWPlayerButtonConfigurationSerializer.kt +25 -0
  20. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfiguration.kt +7 -0
  21. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfigurationDeserializer.kt +17 -0
  22. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfigurationSerializer.kt +13 -0
  23. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedPropsModel.kt +1 -0
  24. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedPropsModelDeserializer.kt +3 -0
  25. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedPropsModelSerializer.kt +2 -0
  26. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModel.kt +3 -1
  27. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelDeserializer.kt +7 -1
  28. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelSerializer.kt +4 -0
  29. package/android/src/main/java/com/fireworksdk/bridge/models/enums/FWErrorAction.kt +18 -0
  30. package/android/src/main/java/com/fireworksdk/bridge/models/enums/FWEventName.kt +3 -0
  31. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWStoryBlockManager.kt +50 -26
  32. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWVideoFeedManager.kt +47 -8
  33. package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FWVideoShoppingInterface.kt +1 -0
  34. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWNavigatorModule.kt +0 -10
  35. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt +42 -0
  36. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +5 -3
  37. package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +24 -6
  38. package/android/src/main/java/com/fireworksdk/bridge/utils/FWConfigUtil.kt +95 -0
  39. package/android/src/main/res/layout/fw_bridge_story_block.xml +6 -0
  40. package/android/src/main/res/layout/fw_loading.xml +14 -0
  41. package/ios/Components/VideoFeed.swift +1 -1
  42. package/ios/FireworkVideoUI/Podfile +1 -1
  43. package/ios/FireworkVideoUI/Podfile.lock +5 -5
  44. package/ios/Modules/FWNavigatorModule/RNSScreenStackView+Window.h +20 -0
  45. package/ios/Modules/FWNavigatorModule/RNSScreenStackView+Window.m +84 -0
  46. package/lib/commonjs/VideoShopping.js +1 -4
  47. package/lib/commonjs/VideoShopping.js.map +1 -1
  48. package/lib/commonjs/components/StoryBlock.js +32 -42
  49. package/lib/commonjs/components/StoryBlock.js.map +1 -1
  50. package/lib/commonjs/components/VideoFeed.js +29 -11
  51. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  52. package/lib/commonjs/index.js +8 -0
  53. package/lib/commonjs/index.js.map +1 -1
  54. package/lib/commonjs/utils/VideoFeedUtil.js +73 -0
  55. package/lib/commonjs/utils/VideoFeedUtil.js.map +1 -0
  56. package/lib/module/VideoShopping.js +1 -5
  57. package/lib/module/VideoShopping.js.map +1 -1
  58. package/lib/module/components/StoryBlock.js +32 -40
  59. package/lib/module/components/StoryBlock.js.map +1 -1
  60. package/lib/module/components/VideoFeed.js +28 -11
  61. package/lib/module/components/VideoFeed.js.map +1 -1
  62. package/lib/module/index.js +2 -1
  63. package/lib/module/index.js.map +1 -1
  64. package/lib/module/utils/VideoFeedUtil.js +65 -0
  65. package/lib/module/utils/VideoFeedUtil.js.map +1 -0
  66. package/lib/typescript/VideoShopping.d.ts +0 -1
  67. package/lib/typescript/components/StoryBlock.d.ts +15 -4
  68. package/lib/typescript/components/VideoFeed.d.ts +12 -1
  69. package/lib/typescript/index.d.ts +2 -1
  70. package/lib/typescript/models/ButtonInfo.d.ts +0 -1
  71. package/lib/typescript/models/ProductInfoViewConfiguration.d.ts +3 -3
  72. package/lib/typescript/models/StoryBlockConfiguration.d.ts +0 -2
  73. package/lib/typescript/models/VideoPlayerButtonConfiguration.d.ts +0 -6
  74. package/lib/typescript/models/VideoPlayerConfiguration.d.ts +0 -2
  75. package/lib/typescript/utils/VideoFeedUtil.d.ts +10 -0
  76. package/package.json +1 -1
  77. package/react-native-firework-sdk.podspec +1 -1
  78. package/src/VideoShopping.ts +1 -4
  79. package/src/components/StoryBlock.tsx +40 -44
  80. package/src/components/VideoFeed.tsx +32 -11
  81. package/src/index.ts +2 -0
  82. package/src/models/ButtonInfo.ts +0 -1
  83. package/src/models/ProductInfoViewConfiguration.ts +3 -3
  84. package/src/models/StoryBlockConfiguration.ts +0 -2
  85. package/src/models/VideoPlayerButtonConfiguration.ts +0 -6
  86. package/src/models/VideoPlayerConfiguration.ts +0 -2
  87. package/src/utils/VideoFeedUtil.ts +74 -0
  88. package/android/src/main/java/com/fireworksdk/bridge/utils/FWStatusBarUtil.kt +0 -28
  89. package/android/src/main/java/com/fireworksdk/bridge/utils/FWStoryBlockUtil.kt +0 -30
@@ -14,7 +14,7 @@
14
14
  </data>
15
15
  <key>Info.plist</key>
16
16
  <data>
17
- dRwGqwAERLUXdGSS28BxDgMmbF8=
17
+ JPxz3YyYbfRHXYqKbt1EHDZI0ew=
18
18
  </data>
19
19
  <key>Modules/FireworkVideoUI.swiftmodule/arm64-apple-ios-simulator.abi.json</key>
20
20
  <data>
@@ -40,7 +40,7 @@ android {
40
40
  // LOG_LEVEL: VERBOSE(2), DEBUG(3), INFO(4), WARN(5), ERROR(6), ASSERT(7)
41
41
  buildTypes {
42
42
  debug {
43
- buildConfigField 'int', 'LOG_LEVEL', '3'
43
+ buildConfigField 'int', 'LOG_LEVEL', '7'
44
44
  consumerProguardFiles 'proguard-rules.pro', "devsupport.pro"
45
45
  }
46
46
  release {
@@ -143,5 +143,6 @@ dependencies {
143
143
 
144
144
  def fireworkSdkVersion = getExtOrDefault('fwNativeVersion')
145
145
  implementation "com.firework:sdk:$fireworkSdkVersion"
146
+ implementation "com.firework.feature:uiKit:$fireworkSdkVersion"
146
147
  }
147
148
 
@@ -5,4 +5,4 @@ FireworkSDK_kotlinVersion=1.6.10
5
5
  FireworkSDK_minSdkVersion=21
6
6
  FireworkSDK_compileSdkVersion=33
7
7
  FireworkSDK_targetSdkVersion=33
8
- FireworkSDK_fwNativeVersion=6.6.3
8
+ FireworkSDK_fwNativeVersion=6.8.1
@@ -0,0 +1,22 @@
1
+ package com.fireworksdk.bridge.components.base
2
+
3
+ import android.content.Context
4
+ import android.util.AttributeSet
5
+ import android.view.LayoutInflater
6
+ import android.view.ViewGroup
7
+ import android.widget.FrameLayout
8
+ import com.fireworksdk.bridge.R
9
+
10
+ class FWLoading(
11
+ context: Context,
12
+ attrs: AttributeSet?
13
+ ) : FrameLayout(context, attrs) {
14
+
15
+ constructor(context: Context) : this(context, null)
16
+
17
+ init {
18
+ val v =
19
+ LayoutInflater.from(context).inflate(R.layout.fw_loading, this, false)
20
+ addView(v, LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
21
+ }
22
+ }
@@ -1,16 +1,24 @@
1
1
  package com.fireworksdk.bridge.components.storyblock
2
2
 
3
+ import android.graphics.Color
3
4
  import android.graphics.Outline
4
5
  import android.os.Bundle
6
+ import android.os.Handler
7
+ import android.os.Looper
5
8
  import android.view.LayoutInflater
9
+ import android.view.SurfaceView
6
10
  import android.view.View
7
11
  import android.view.View.LAYOUT_DIRECTION_LOCALE
8
12
  import android.view.ViewGroup
13
+ import android.view.ViewGroup.LayoutParams
9
14
  import android.view.ViewOutlineProvider
10
15
  import android.widget.FrameLayout
16
+ import com.firework.error.FwErrorListener
11
17
  import com.firework.storyblock.FeedLoadListener
18
+ import com.firework.storyblock.FeedLoadState
12
19
  import com.firework.storyblock.FwStoryBlockView
13
20
  import com.fireworksdk.bridge.components.base.FWBaseFragment
21
+ import com.fireworksdk.bridge.components.base.FWLoading
14
22
  import com.fireworksdk.bridge.databinding.FwBridgeStoryBlockBinding
15
23
  import com.fireworksdk.bridge.models.FWVideoFeedPropsModel
16
24
  import com.fireworksdk.bridge.models.FWVideoFeedPropsModelDeserializer
@@ -19,6 +27,7 @@ import com.fireworksdk.bridge.utils.FWCommonUtil
19
27
  import com.fireworksdk.bridge.utils.FWConfigUtil
20
28
  import com.fireworksdk.bridge.utils.FWLanguageUtil
21
29
  import org.json.JSONObject
30
+ import java.lang.reflect.Method
22
31
 
23
32
  class StoryBlockFragment : FWBaseFragment() {
24
33
 
@@ -26,7 +35,7 @@ class StoryBlockFragment : FWBaseFragment() {
26
35
  private val binding: FwBridgeStoryBlockBinding get() = _binding!!
27
36
 
28
37
  private var feedLoadListener: FeedLoadListener? = null
29
- private var fullScreenStateChangeListener: FwStoryBlockView.OnFullscreenStateChangeListener? = null
38
+ private var errorListener: FwErrorListener? = null
30
39
  private var videoFeedPropsModel: FWVideoFeedPropsModel? = null
31
40
 
32
41
  private var isStoryBlockInitializer = false
@@ -34,6 +43,15 @@ class StoryBlockFragment : FWBaseFragment() {
34
43
 
35
44
  private var fwStoryBlockView: FwStoryBlockView? = null
36
45
 
46
+ private val runnable = Runnable {
47
+ removeLoadingViewFromIvsPlayerView(fwStoryBlockView)
48
+ }
49
+ private var hasAdded = false
50
+
51
+ private var loaderContainer: FrameLayout? = null
52
+
53
+ private var needIvsLoading = false
54
+
37
55
  override fun onCreateView(
38
56
  inflater: LayoutInflater,
39
57
  container: ViewGroup?,
@@ -47,15 +65,25 @@ class StoryBlockFragment : FWBaseFragment() {
47
65
  val model = FWVideoFeedPropsModelDeserializer.deserialize(videoFeedPropsModelJsonObject)
48
66
  videoFeedPropsModel = model
49
67
  }
68
+ val needIvsLoading = arguments?.getBoolean(NEED_IVS_LOADING) ?: false
69
+ this.needIvsLoading = needIvsLoading
70
+
71
+ loaderContainer = binding.fwLoadingWrapper.loaderContainer
50
72
 
51
73
  val right = videoFeedPropsModel?.marginRight
52
74
  if (right != null && right > 0) {
53
75
  val layoutParams = FrameLayout.LayoutParams(
54
- ViewGroup.LayoutParams.MATCH_PARENT,
55
- ViewGroup.LayoutParams.MATCH_PARENT
76
+ LayoutParams.MATCH_PARENT,
77
+ LayoutParams.MATCH_PARENT
56
78
  )
57
79
  layoutParams.setMargins(0, 0, FWCommonUtil.dpToPx(right.toFloat(), requireContext()), 0)
58
80
  binding.storyBlockContainer.layoutParams = layoutParams
81
+
82
+ if (needIvsLoading) {
83
+ loaderContainer?.visibility = View.VISIBLE
84
+ loaderContainer?.layoutParams = layoutParams
85
+ loaderContainer?.setBackgroundColor(Color.BLACK)
86
+ }
59
87
  }
60
88
 
61
89
  FWLanguageUtil.getInstance(requireContext()).updateBaseContextLocale(requireContext())
@@ -73,6 +101,7 @@ class StoryBlockFragment : FWBaseFragment() {
73
101
 
74
102
 
75
103
  override fun onDestroyView() {
104
+ fwStoryBlockView?.destroy()
76
105
  _binding = null
77
106
  super.onDestroyView()
78
107
  }
@@ -81,9 +110,9 @@ class StoryBlockFragment : FWBaseFragment() {
81
110
  val viewOptionsBuilder = FWConfigUtil.generateViewOptionsBuilder(context, videoFeedPropsModel)
82
111
  fwStoryBlockView?.init(
83
112
  childFragmentManager,
84
- lifecycle,
113
+ viewLifecycleOwner,
85
114
  viewOptionsBuilder.build(),
86
- binding.storyBlockContainer,
115
+ true
87
116
  )
88
117
  isStoryBlockInitializer = true
89
118
 
@@ -92,8 +121,8 @@ class StoryBlockFragment : FWBaseFragment() {
92
121
  binding.root.requestLayout()
93
122
  }
94
123
  // must call it after init()
95
- fwStoryBlockView?.setFeedLoadListener(feedLoadListener)
96
- fwStoryBlockView?.setOnFullscreenStateChangeListener(fullScreenStateChangeListener)
124
+ setFeedLoadListener(feedLoadListener)
125
+ setOnErrorListener(errorListener)
97
126
  }
98
127
 
99
128
  // may be called before onCreateView
@@ -110,15 +139,23 @@ class StoryBlockFragment : FWBaseFragment() {
110
139
  fun setFeedLoadListener(feedLoadListener: FeedLoadListener?) {
111
140
  this.feedLoadListener = feedLoadListener
112
141
  if (isStoryBlockInitializer) {
113
- fwStoryBlockView?.setFeedLoadListener(feedLoadListener)
142
+ fwStoryBlockView?.setFeedLoadListener { feedLoadState ->
143
+ feedLoadListener?.onFeedLoadStateChanged(feedLoadState)
144
+ if (feedLoadState !== FeedLoadState.Loading) {
145
+ hideLoading()
146
+ }
147
+ }
114
148
  }
115
149
  }
116
150
 
117
- // may be called before onCreateView
118
- fun setOnFullScreenStateChangedListener(listener: FwStoryBlockView.OnFullscreenStateChangeListener?) {
119
- this.fullScreenStateChangeListener = listener
151
+ fun setOnErrorListener(errorListener: FwErrorListener?) {
152
+ errorListener ?: return
153
+ this.errorListener = errorListener
120
154
  if (isStoryBlockInitializer) {
121
- fwStoryBlockView?.setOnFullscreenStateChangeListener(fullScreenStateChangeListener)
155
+ fwStoryBlockView?.setOnErrorListener { fwError ->
156
+ hideLoading()
157
+ errorListener.onFwError(fwError)
158
+ }
122
159
  }
123
160
  }
124
161
 
@@ -130,29 +167,150 @@ class StoryBlockFragment : FWBaseFragment() {
130
167
  fwStoryBlockView?.pause()
131
168
  }
132
169
 
133
- fun toggleFullScreen() {
134
- fwStoryBlockView?.toggleFullscreen()
170
+ fun onViewportEntered() {
171
+ fwStoryBlockView?.onViewportEntered()
172
+ if (hasAdded && needIvsLoading) {
173
+ hasAdded = false
174
+ removeLoadingViewFromIvsPlayerView()
175
+ }
176
+ }
177
+
178
+ fun onViewportLeft() {
179
+ fwStoryBlockView?.onViewportLeft()
180
+ if (!hasAdded && needIvsLoading) {
181
+ hasAdded = true
182
+ addLoadingViewToIvsPlayerView()
183
+ }
184
+ }
185
+
186
+ private fun addLoadingViewToIvsPlayerView() {
187
+ Handler(Looper.getMainLooper()).removeCallbacks(runnable)
188
+
189
+ val ivsPlayerViewList = mutableListOf<ViewGroup>()
190
+ searchVisibleIvsPlayerView(fwStoryBlockView, ivsPlayerViewList)
191
+ for (view in ivsPlayerViewList) {
192
+ val loading = FWLoading(view.context)
193
+ loading.setBackgroundColor(Color.BLACK)
194
+ view.addView(loading, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
195
+ }
196
+ }
197
+
198
+ private fun removeLoadingViewFromIvsPlayerView() {
199
+ val storyBlockView = fwStoryBlockView
200
+ storyBlockView ?: return
201
+
202
+ Handler(Looper.getMainLooper()).removeCallbacks(runnable)
203
+ Handler(Looper.getMainLooper()).postDelayed(runnable, 1000)
204
+ }
205
+
206
+
207
+ fun hideIvsPlayerView() {
208
+ val ivsPlayerViewList = mutableListOf<ViewGroup>()
209
+ searchVisibleIvsPlayerView(fwStoryBlockView, ivsPlayerViewList)
210
+ hideIvsPlayerSurfaceView(ivsPlayerViewList)
211
+ }
212
+
213
+ fun showIvsPlayerView() {
214
+ val ivsPlayerViewList = mutableListOf<ViewGroup>()
215
+ searchVisibleIvsPlayerView(fwStoryBlockView, ivsPlayerViewList)
216
+ showIvsPlayerSurfaceView(ivsPlayerViewList)
135
217
  }
136
218
 
137
- fun isFullScreen(): Boolean {
138
- return fwStoryBlockView?.isFullscreen() ?: false
219
+ fun removeIvsPlayerView() {
220
+ val ivsPlayerViewList = mutableListOf<ViewGroup>()
221
+ searchVisibleIvsPlayerView(fwStoryBlockView, ivsPlayerViewList)
222
+ removeIvsPlayerSurfaceView(ivsPlayerViewList)
139
223
  }
140
224
 
141
- fun getStoryBlockView(): FwStoryBlockView? {
142
- return fwStoryBlockView
225
+ fun playIvsPlayer() {
226
+ val ivsPlayerViewList = mutableListOf<ViewGroup>()
227
+ searchVisibleIvsPlayerView(fwStoryBlockView, ivsPlayerViewList)
228
+ playIvsPlayerView(ivsPlayerViewList)
229
+ }
230
+
231
+ fun pauseIvsPlayer() {
232
+ val ivsPlayerViewList = mutableListOf<ViewGroup>()
233
+ searchVisibleIvsPlayerView(fwStoryBlockView, ivsPlayerViewList)
234
+ pauseIvsPlayerView(ivsPlayerViewList)
235
+ }
236
+
237
+ private fun searchVisibleIvsPlayerView(viewGroup: ViewGroup?, list: MutableList<ViewGroup>) {
238
+ viewGroup ?: return
239
+
240
+ val childCount = viewGroup.childCount
241
+ for (index in 0 until childCount) {
242
+ val view = viewGroup.getChildAt(index)
243
+ if (view is ViewGroup) {
244
+ val className = view.javaClass.name
245
+ if (className.equals("com.amazonaws.ivs.player.PlayerView")
246
+ || className.equals("com.amazonaws.ivs.player.CustomPlayerView")) {
247
+ list.add(view)
248
+ } else {
249
+ searchVisibleIvsPlayerView(view, list)
250
+ }
251
+ }
252
+ }
253
+ }
254
+
255
+ private fun hideIvsPlayerSurfaceView(list: List<ViewGroup>?) {
256
+ list ?: return
257
+ for (viewGroup in list) {
258
+ val childCount = viewGroup.childCount
259
+ for (index in 0 until childCount) {
260
+ val view = viewGroup.getChildAt(index)
261
+ if (view is SurfaceView) {
262
+ view.visibility = View.INVISIBLE
263
+ }
264
+ }
265
+ }
266
+ }
267
+
268
+ private fun showIvsPlayerSurfaceView(list: List<ViewGroup>?) {
269
+ list ?: return
270
+ for (viewGroup in list) {
271
+ val childCount = viewGroup.childCount
272
+ for (index in 0 until childCount) {
273
+ val view = viewGroup.getChildAt(index)
274
+ if (view is SurfaceView) {
275
+ view.visibility = View.VISIBLE
276
+ }
277
+ }
278
+ }
279
+ }
280
+
281
+ private fun removeIvsPlayerSurfaceView(list: List<ViewGroup>?) {
282
+ list ?: return
283
+ for (viewGroup in list) {
284
+ val childCount = viewGroup.childCount
285
+ for (index in 0 until childCount) {
286
+ val view = viewGroup.getChildAt(index)
287
+ if (view is SurfaceView) {
288
+ viewGroup.removeView(view)
289
+ }
290
+ }
291
+ }
292
+ }
293
+
294
+ fun openFullscreen() {
295
+ fwStoryBlockView?.openFullscreen()
143
296
  }
144
297
 
145
298
  companion object {
146
299
  private const val VIDEO_FEED_PROPS_MODEL = "videoFeedPropsModel"
300
+ private const val NEED_IVS_LOADING = "needIvsLoading"
147
301
 
148
302
  fun newInstance(
149
303
  videoFeedPropsModel: FWVideoFeedPropsModel?,
304
+ needIvsLoading: Boolean? = false,
150
305
  ): StoryBlockFragment {
151
306
  return StoryBlockFragment().apply {
152
307
  arguments = Bundle().apply {
153
308
  videoFeedPropsModel?.let {
154
309
  putString(VIDEO_FEED_PROPS_MODEL, FWVideoFeedPropsModelSerializer.serialize(it).toString())
155
310
  }
311
+ needIvsLoading?.let {
312
+ putBoolean(NEED_IVS_LOADING, needIvsLoading)
313
+ }
156
314
  }
157
315
  }
158
316
  }
@@ -172,6 +330,70 @@ class StoryBlockFragment : FWBaseFragment() {
172
330
  }
173
331
  binding.storyBlockContainer.outlineProvider = outlineProvider
174
332
  binding.storyBlockContainer.clipToOutline = true
333
+
334
+ loaderContainer?.outlineProvider = outlineProvider
335
+ loaderContainer?.clipToOutline = true
336
+ }
337
+ }
338
+
339
+ private fun pauseIvsPlayerView(list: List<ViewGroup>?) {
340
+ list ?: return
341
+ for (view in list) {
342
+ if (view.javaClass.name.equals("com.amazonaws.ivs.player.CustomPlayerView")) {
343
+ val filed = view.javaClass.getDeclaredField("player")
344
+ filed.isAccessible = true
345
+ val player = filed.get(view)
346
+ val pauseMethod: Method = player.javaClass.getDeclaredMethod("pause")
347
+ pauseMethod.invoke(player)
348
+ } else if (view.javaClass.name.equals("com.amazonaws.ivs.player.PlayerView")) {
349
+ val getPlayerMethod: Method = view.javaClass.getDeclaredMethod("getPlayer")
350
+ val player = getPlayerMethod.invoke(view)
351
+ val pauseMethod: Method = player.javaClass.getDeclaredMethod("pause")
352
+ pauseMethod.invoke(player)
353
+ }
354
+ }
355
+ }
356
+
357
+ private fun playIvsPlayerView(list: List<ViewGroup>?) {
358
+ list ?: return
359
+ for (view in list) {
360
+ if (view.javaClass.name.equals("com.amazonaws.ivs.player.CustomPlayerView")) {
361
+ val filed = view.javaClass.getDeclaredField("player")
362
+ filed.isAccessible = true
363
+ val player = filed.get(view)
364
+ val pauseMethod: Method = player.javaClass.getDeclaredMethod("play")
365
+ pauseMethod.invoke(player)
366
+ } else if (view.javaClass.name.equals("com.amazonaws.ivs.player.PlayerView")) {
367
+ val getPlayerMethod: Method = view.javaClass.getDeclaredMethod("getPlayer")
368
+ val player = getPlayerMethod.invoke(view)
369
+ val playMethod: Method = player.javaClass.getDeclaredMethod("play")
370
+ playMethod.invoke(player)
371
+ }
372
+ }
373
+ }
374
+
375
+ private fun removeLoadingViewFromIvsPlayerView(viewGroup: ViewGroup?) {
376
+ viewGroup ?: return
377
+
378
+ val childCount = viewGroup.childCount
379
+ for (index in 0 until childCount) {
380
+ val view = viewGroup.getChildAt(index)
381
+ if (view is ViewGroup) {
382
+ val className = view.javaClass.name
383
+ if (className.equals("com.fireworksdk.bridge.components.base.FWLoading")) {
384
+ viewGroup.removeView(view)
385
+ } else {
386
+ removeLoadingViewFromIvsPlayerView(view)
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ private fun hideLoading() {
393
+ if (loaderContainer?.visibility == View.VISIBLE) {
394
+ Handler(Looper.getMainLooper()).postDelayed({
395
+ loaderContainer?.visibility = View.GONE
396
+ }, 1000)
175
397
  }
176
398
  }
177
399
  }
@@ -4,6 +4,7 @@ import android.content.Context
4
4
  import android.util.AttributeSet
5
5
  import android.view.ViewGroup
6
6
  import android.widget.FrameLayout
7
+ import com.firework.error.FwErrorListener
7
8
  import com.firework.videofeed.FeedViewStateListener
8
9
  import com.firework.videofeed.FwVideoFeedView
9
10
  import com.fireworksdk.bridge.models.*
@@ -52,17 +53,26 @@ class FWVideoFeed(
52
53
 
53
54
  fun setOnFeedViewStateListener(feedViewStateListener: FeedViewStateListener?) {
54
55
  this.feedViewStateListener = feedViewStateListener
55
- if (feedViewStateListener != null) {
56
- videoFeedView.setOnFeedViewStateListener { feedViewState ->
57
- if (!onWindowFocusChanged) {
58
- videoFeedView.dispatchWindowFocusChanged(true)
59
- onWindowFocusChanged = true
60
- }
56
+ videoFeedView.setOnFeedViewStateListener { feedViewState ->
57
+ if (!onWindowFocusChanged) {
58
+ videoFeedView.dispatchWindowFocusChanged(true)
59
+ onWindowFocusChanged = true
60
+ }
61
61
 
62
- feedViewStateListener.onLoadStateChanged(
63
- feedViewState
64
- )
62
+ feedViewStateListener?.onLoadStateChanged(
63
+ feedViewState
64
+ )
65
+ }
66
+ }
67
+
68
+ fun setOnErrorListener(errorListener: FwErrorListener?) {
69
+ videoFeedView.setOnErrorListener { error ->
70
+ if (!onWindowFocusChanged) {
71
+ videoFeedView.dispatchWindowFocusChanged(true)
72
+ onWindowFocusChanged = true
65
73
  }
74
+
75
+ errorListener?.onFwError(error)
66
76
  }
67
77
  }
68
78
 
@@ -0,0 +1,49 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONObject
4
+
5
+ object FWAdConfigurationDeserializer {
6
+
7
+ private const val VAST_ATTRIBUTES_KEY = "vastAttributes"
8
+ private const val REQUIRES_ADS_KEY = "requiresAds"
9
+ private const val ADS_FETCH_TIMEOUT_KEY = "adsFetchTimeout"
10
+
11
+ private const val NAME_KEY = "name"
12
+ private const val VALUE_KEY = "value"
13
+
14
+ fun deserialize(responseJson: JSONObject?): FWAdConfigurationModel? {
15
+ responseJson ?: return null
16
+
17
+ val vastAttributesJsonArray = if (responseJson.has(VAST_ATTRIBUTES_KEY)) responseJson.optJSONArray(VAST_ATTRIBUTES_KEY) else null
18
+ var vastAttributes: MutableList<FWAdConfigurationModel.FWVastAttributeModel>? = null
19
+ if (vastAttributesJsonArray != null) {
20
+ vastAttributes = mutableListOf()
21
+ (0 until vastAttributesJsonArray.length()).forEach {
22
+ val item = vastAttributesJsonArray.getJSONObject(it)
23
+ val vastAttribute = deserializeVastAttribute(item)
24
+ if (vastAttribute != null) {
25
+ vastAttributes.add(vastAttribute)
26
+ }
27
+ }
28
+ }
29
+
30
+ val requiresAds = responseJson.optBoolean(REQUIRES_ADS_KEY, false)
31
+ val adsFetchTimeout = if (!responseJson.isNull(ADS_FETCH_TIMEOUT_KEY)) responseJson.optInt(ADS_FETCH_TIMEOUT_KEY) else null
32
+
33
+ return FWAdConfigurationModel(
34
+ vastAttributes = vastAttributes,
35
+ requiresAds = requiresAds,
36
+ adsFetchTimeout = adsFetchTimeout,
37
+ )
38
+ }
39
+
40
+ private fun deserializeVastAttribute(responseJson: JSONObject?): FWAdConfigurationModel.FWVastAttributeModel? {
41
+ responseJson ?: return null
42
+ val name = if (responseJson.has(NAME_KEY)) responseJson.optString(NAME_KEY) else null
43
+ val value = if (responseJson.has(VALUE_KEY)) responseJson.optString(VALUE_KEY) else null
44
+ return FWAdConfigurationModel.FWVastAttributeModel(
45
+ name = name,
46
+ value =value
47
+ )
48
+ }
49
+ }
@@ -0,0 +1,13 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ data class FWAdConfigurationModel(
4
+ val vastAttributes: List<FWVastAttributeModel>? = null,
5
+ val requiresAds: Boolean? = null,
6
+ val adsFetchTimeout: Int? = null
7
+ ) {
8
+
9
+ data class FWVastAttributeModel(
10
+ val name: String? = null,
11
+ val value: String? = null
12
+ )
13
+ }
@@ -0,0 +1,42 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONArray
4
+ import org.json.JSONObject
5
+
6
+ object FWAdConfigurationSerializer {
7
+
8
+ private const val VAST_ATTRIBUTES_KEY = "vastAttributes"
9
+ private const val REQUIRES_ADS_KEY = "requiresAds"
10
+ private const val ADS_FETCH_TIMEOUT_KEY = "adsFetchTimeout"
11
+
12
+ private const val NAME_KEY = "name"
13
+ private const val VALUE_KEY = "value"
14
+
15
+ fun serialize(model: FWAdConfigurationModel?): JSONObject? {
16
+ model ?: return null
17
+ val jsonObject = JSONObject()
18
+
19
+ val list = model.vastAttributes
20
+ if (list != null) {
21
+ val vastAttributesJsonArray = JSONArray()
22
+ for (item in model.vastAttributes) {
23
+ val vastAttributes = serializeVastAttribute(item)
24
+ vastAttributesJsonArray.put(vastAttributes)
25
+ }
26
+ jsonObject.put(VAST_ATTRIBUTES_KEY, vastAttributesJsonArray)
27
+ }
28
+
29
+ jsonObject.put(REQUIRES_ADS_KEY, model.requiresAds)
30
+ jsonObject.put(ADS_FETCH_TIMEOUT_KEY, model.adsFetchTimeout)
31
+ return jsonObject
32
+ }
33
+
34
+ private fun serializeVastAttribute(model: FWAdConfigurationModel.FWVastAttributeModel?): JSONObject? {
35
+ model ?: return null
36
+ val jsonObject = JSONObject()
37
+ jsonObject.put(NAME_KEY, model.name)
38
+ jsonObject.put(VALUE_KEY, model.value)
39
+
40
+ return jsonObject
41
+ }
42
+ }
@@ -0,0 +1,21 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONObject
4
+
5
+ object FWButtonInfoDeserializer {
6
+
7
+ private const val IMAGE_NAME_KEY = "imageName"
8
+ private const val TINT_COLOR_KEY = "tintColor"
9
+
10
+ fun deserialize(responseJson: JSONObject?): FWButtonInfoModel? {
11
+ responseJson ?: return null
12
+
13
+ val imageName = if (responseJson.has(IMAGE_NAME_KEY)) responseJson.optString(IMAGE_NAME_KEY) else null
14
+ val tintColor = if (responseJson.has(TINT_COLOR_KEY)) responseJson.optString(TINT_COLOR_KEY) else null
15
+
16
+ return FWButtonInfoModel(
17
+ imageName = imageName,
18
+ tintColor = tintColor
19
+ )
20
+ }
21
+ }
@@ -0,0 +1,6 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ data class FWButtonInfoModel (
4
+ val imageName: String? = null,
5
+ val tintColor: String? = null
6
+ )
@@ -0,0 +1,17 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONObject
4
+
5
+ object FWButtonInfoSerializer {
6
+
7
+ private const val IMAGE_NAME_KEY = "imageName"
8
+ private const val TINT_COLOR_KEY = "tintColor"
9
+
10
+ fun serialize(model: FWButtonInfoModel?): JSONObject? {
11
+ model ?: return null
12
+ val jsonObject = JSONObject()
13
+ jsonObject.put(IMAGE_NAME_KEY, model.imageName)
14
+ jsonObject.put(TINT_COLOR_KEY, model.tintColor)
15
+ return jsonObject
16
+ }
17
+ }
@@ -0,0 +1,33 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONObject
4
+
5
+ object FWPlayerButtonConfigurationDeserializer {
6
+
7
+ private const val VIDEO_DETAIL_BUTTON_KEY = "videoDetailButton"
8
+ private const val CLOSE_BUTTON_KEY = "closeButton"
9
+ private const val MUTE_BUTTON_KEY = "muteButton"
10
+ private const val UNMUTE_BUTTON_KEY = "unmuteButton"
11
+ private const val PLAY_BUTTON_KEY = "playButton"
12
+ private const val PAUSE_BUTTON_KEY = "pauseButton"
13
+
14
+ fun deserialize(responseJson: JSONObject?): FWPlayerButtonConfigurationModel? {
15
+ responseJson ?: return null
16
+
17
+ val videoDetailButtonJsonObject = responseJson.optJSONObject(VIDEO_DETAIL_BUTTON_KEY)
18
+ val closeButtonJsonObject = responseJson.optJSONObject(CLOSE_BUTTON_KEY)
19
+ val muteButtonJsonObject = responseJson.optJSONObject(MUTE_BUTTON_KEY)
20
+ val unmuteButtonJsonObject = responseJson.optJSONObject(UNMUTE_BUTTON_KEY)
21
+ val playButtonJsonObject = responseJson.optJSONObject(PLAY_BUTTON_KEY)
22
+ val pauseButtonJsonObject = responseJson.optJSONObject(PAUSE_BUTTON_KEY)
23
+
24
+ return FWPlayerButtonConfigurationModel(
25
+ videoDetailButton = FWButtonInfoDeserializer.deserialize(videoDetailButtonJsonObject),
26
+ closeButton = FWButtonInfoDeserializer.deserialize(closeButtonJsonObject),
27
+ muteButton = FWButtonInfoDeserializer.deserialize(muteButtonJsonObject),
28
+ unmuteButton = FWButtonInfoDeserializer.deserialize(unmuteButtonJsonObject),
29
+ playButton = FWButtonInfoDeserializer.deserialize(playButtonJsonObject),
30
+ pauseButton = FWButtonInfoDeserializer.deserialize(pauseButtonJsonObject),
31
+ )
32
+ }
33
+ }
@@ -0,0 +1,10 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ data class FWPlayerButtonConfigurationModel(
4
+ val videoDetailButton: FWButtonInfoModel? = null,
5
+ val closeButton: FWButtonInfoModel? = null,
6
+ val muteButton: FWButtonInfoModel? = null,
7
+ val unmuteButton: FWButtonInfoModel? = null,
8
+ val playButton: FWButtonInfoModel? = null,
9
+ val pauseButton: FWButtonInfoModel? = null,
10
+ )