react-native-firework-sdk 1.3.1-beta.9 → 1.4.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 (54) hide show
  1. package/android/build.gradle +2 -8
  2. package/android/src/main/java/com/fireworksdk/bridge/FireworkSDKPackage.kt +6 -2
  3. package/android/src/main/java/com/fireworksdk/bridge/models/FWEventName.kt +4 -0
  4. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWStoryBlockManager.kt +274 -0
  5. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWVideoFeedManager.kt +16 -9
  6. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +13 -0
  7. package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +11 -0
  8. package/android/src/main/res/layout/fw_bridge_fragment_videofeed.xml +0 -4
  9. package/ios/Components/StoryBlock.swift +105 -0
  10. package/ios/Components/StoryBlockManager.m +29 -0
  11. package/ios/Components/StoryBlockManager.swift +31 -0
  12. package/ios/Components/VideoFeed.swift +8 -16
  13. package/ios/FireworkSdk.xcodeproj/project.pbxproj +26 -4
  14. package/ios/Models/NativeToRN/FireworkSDK+Json.swift +23 -5
  15. package/ios/Models/RNToNative/RCTConvert+StoryBlock.swift +28 -0
  16. package/ios/Models/RNToNative/RCTConvert+VideoFeed.swift +2 -2
  17. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +1 -1
  18. package/ios/Modules/FireworkSDKModule/FireworkSDKModule+CTA.swift +2 -0
  19. package/ios/Modules/Shopping/{CartViewController.swift → FWCartViewController.swift} +8 -7
  20. package/ios/Modules/Shopping/ShoppingModule.swift +4 -3
  21. package/ios/Utils/UINavigationController+FWSwizzle.h +16 -0
  22. package/ios/Utils/UINavigationController+FWSwizzle.m +49 -0
  23. package/ios/Utils/UIViewController+AttachChild.swift +8 -11
  24. package/lib/commonjs/components/FWStoryBlock.js +18 -0
  25. package/lib/commonjs/components/FWStoryBlock.js.map +1 -0
  26. package/lib/commonjs/components/StoryBlock.js +174 -0
  27. package/lib/commonjs/components/StoryBlock.js.map +1 -0
  28. package/lib/commonjs/components/VideoFeed.js +31 -17
  29. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  30. package/lib/commonjs/index.js +8 -0
  31. package/lib/commonjs/index.js.map +1 -1
  32. package/lib/commonjs/models/StoryBlockSource.js +2 -0
  33. package/lib/commonjs/models/StoryBlockSource.js.map +1 -0
  34. package/lib/module/components/FWStoryBlock.js +8 -0
  35. package/lib/module/components/FWStoryBlock.js.map +1 -0
  36. package/lib/module/components/StoryBlock.js +150 -0
  37. package/lib/module/components/StoryBlock.js.map +1 -0
  38. package/lib/module/components/VideoFeed.js +31 -16
  39. package/lib/module/components/VideoFeed.js.map +1 -1
  40. package/lib/module/index.js +2 -1
  41. package/lib/module/index.js.map +1 -1
  42. package/lib/module/models/StoryBlockSource.js +2 -0
  43. package/lib/module/models/StoryBlockSource.js.map +1 -0
  44. package/lib/typescript/components/FWStoryBlock.d.ts +2 -0
  45. package/lib/typescript/components/StoryBlock.d.ts +42 -0
  46. package/lib/typescript/index.d.ts +3 -1
  47. package/lib/typescript/models/StoryBlockSource.d.ts +1 -0
  48. package/package.json +1 -1
  49. package/react-native-firework-sdk.podspec +1 -1
  50. package/src/components/FWStoryBlock.tsx +10 -0
  51. package/src/components/StoryBlock.tsx +180 -0
  52. package/src/components/VideoFeed.tsx +30 -23
  53. package/src/index.tsx +4 -0
  54. package/src/models/StoryBlockSource.ts +5 -0
@@ -168,16 +168,9 @@ def kotlin_version = getExtOrDefault('kotlinVersion')
168
168
 
169
169
  dependencies {
170
170
 
171
- // optional 1: firework sdk release verison
172
- def firework_sdk_version = 'debug~landmark-SNAPSHOT'
171
+ def firework_sdk_version = 'v5.14.3'
173
172
  implementation "com.github.loopsocial:firework_sdk:$firework_sdk_version"
174
173
 
175
- // optional 2: firework sdk local version,
176
- // project settings.gradle
177
- // include ':fireworklibrary'
178
- // project(':fireworklibrary').projectDir = new File('../../../firework_sdk/fireworklibrary')
179
- // implementation project(path: ':fireworklibrary')
180
-
181
174
  // noinspection GradleDynamicVersion
182
175
  api 'com.facebook.react:react-native:+'
183
176
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
@@ -191,6 +184,7 @@ dependencies {
191
184
  implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
192
185
 
193
186
  implementation "com.google.code.gson:gson:2.9.0"
187
+ implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
194
188
  }
195
189
 
196
190
  configurations.all {
@@ -4,6 +4,7 @@ import com.facebook.react.ReactPackage
4
4
  import com.facebook.react.bridge.NativeModule
5
5
  import com.facebook.react.bridge.ReactApplicationContext
6
6
  import com.facebook.react.uimanager.ViewManager
7
+ import com.fireworksdk.bridge.reactnative.manager.FWStoryBlockManager
7
8
  import com.fireworksdk.bridge.reactnative.manager.FWVideoFeedManager
8
9
  import com.fireworksdk.bridge.reactnative.module.FWLiveStreamModule
9
10
  import com.fireworksdk.bridge.reactnative.module.FWNavigatorModule
@@ -17,11 +18,14 @@ class FireworkSDKPackage : ReactPackage {
17
18
  FireworkSDKModule(reactContext),
18
19
  FWVideoShoppingModule(reactContext),
19
20
  FWLiveStreamModule(reactContext),
20
- FWNavigatorModule(reactContext)
21
+ FWNavigatorModule(reactContext),
21
22
  )
22
23
  }
23
24
 
24
25
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
25
- return listOf(FWVideoFeedManager())
26
+ return listOf(
27
+ FWVideoFeedManager(),
28
+ FWStoryBlockManager(reactContext),
29
+ )
26
30
  }
27
31
  }
@@ -43,3 +43,7 @@ enum class FWLiveStreamEventName(val rawValue: String) {
43
43
  UserSendLike("fw:livestream:user-send-like"),
44
44
  UserSendChat("fw:livestream:user-send-chat"),
45
45
  }
46
+
47
+ enum class FWStoryBlockEventName(val rawValue: String) {
48
+ StoryBlockLoadFinished("onStoryBlockLoadFinished"),
49
+ }
@@ -0,0 +1,274 @@
1
+ package com.fireworksdk.bridge.reactnative.manager
2
+
3
+ import android.content.BroadcastReceiver
4
+ import android.content.Context
5
+ import android.content.Intent
6
+ import android.content.IntentFilter
7
+ import android.view.Choreographer
8
+ import android.view.View
9
+ import android.view.ViewGroup
10
+ import android.widget.FrameLayout
11
+ import androidx.annotation.Nullable
12
+ import androidx.appcompat.app.AppCompatActivity
13
+ import androidx.localbroadcastmanager.content.LocalBroadcastManager
14
+ import com.facebook.react.bridge.Dynamic
15
+ import com.facebook.react.bridge.ReactApplicationContext
16
+ import com.facebook.react.bridge.ReadableArray
17
+ import com.facebook.react.bridge.ReadableMap
18
+ import com.facebook.react.common.MapBuilder
19
+ import com.facebook.react.uimanager.ThemedReactContext
20
+ import com.facebook.react.uimanager.ViewGroupManager
21
+ import com.facebook.react.uimanager.annotations.ReactProp
22
+ import com.facebook.react.uimanager.annotations.ReactPropGroup
23
+ import com.fireworksdk.bridge.models.FWStoryBlockEventName
24
+ import com.fireworksdk.bridge.models.FWVideoFeedPropsModel
25
+ import com.fireworksdk.bridge.models.FWVideoFeedSource
26
+ import com.fireworksdk.bridge.reactnative.module.FireworkSDKModule
27
+ import com.fireworksdk.bridge.reactnative.utils.FWEventUtils
28
+ import com.fireworksdk.bridge.utils.FWLogUtils
29
+ import com.loopnow.fireworklibrary.FeedType
30
+ import com.loopnow.fireworklibrary.FwSDK
31
+ import com.loopnow.fireworklibrary.models.VideoContentStatus
32
+ import com.loopnow.fireworklibrary.views.FireworkPlayerFragment
33
+ import com.loopnow.fireworklibrary.views.OnVideoContentStatusListener
34
+
35
+
36
+ class FWStoryBlockManager(
37
+ private val reactContext: ReactApplicationContext
38
+ ) : ViewGroupManager<FrameLayout>() {
39
+
40
+ private val videoFeedPropsModel: FWVideoFeedPropsModel by lazy { FWVideoFeedPropsModel() }
41
+
42
+ private var broadcastReceiver: BroadcastReceiver = MyReceiver()
43
+ private var fireworkPlayerFragment: FireworkPlayerFragment? = null
44
+ private var propWidth: Int? = null
45
+ private var propHeight: Int? = null
46
+ private var viewId: Int? = null
47
+
48
+ override fun getName(): String {
49
+ return REACT_CLASS
50
+ }
51
+
52
+ override fun createViewInstance(reactContext: ThemedReactContext): FrameLayout {
53
+ val filter = IntentFilter()
54
+ filter.addAction(FW_STORY_BLOCK_INIT_ACTION)
55
+ LocalBroadcastManager.getInstance(reactContext).registerReceiver(broadcastReceiver, filter)
56
+
57
+ return FrameLayout(reactContext)
58
+ }
59
+
60
+ @Nullable
61
+ override fun getCommandsMap(): Map<String, Int>? {
62
+ return MapBuilder.of("create", COMMAND_CREATE)
63
+ }
64
+
65
+ override fun receiveCommand(
66
+ root: FrameLayout,
67
+ commandId: String?,
68
+ args: ReadableArray?
69
+ ) {
70
+ super.receiveCommand(root, commandId, args)
71
+ val reactNativeViewId = requireNotNull(args).getInt(0)
72
+
73
+ FWLogUtils.d { "FWStoryBlockManager receiveCommand commandId: $commandId, reactNativeViewId: $reactNativeViewId" }
74
+ when (commandId?.toInt()) {
75
+ COMMAND_CREATE -> createFragment(root, reactNativeViewId)
76
+ else -> {}
77
+ }
78
+ }
79
+
80
+ @ReactProp(name = "source")
81
+ fun setSource(view: FrameLayout, source: String?) {
82
+ videoFeedPropsModel.source = source
83
+ }
84
+
85
+ @ReactProp(name = "channel")
86
+ fun setChannel(view: FrameLayout, channel: String?) {
87
+ videoFeedPropsModel.channel = channel
88
+ }
89
+
90
+ @ReactProp(name = "playlist")
91
+ fun setPlaylist(view: FrameLayout, playlist: String?) {
92
+ videoFeedPropsModel.playlist = playlist
93
+ }
94
+
95
+ @ReactProp(name = "dynamicContentParameters")
96
+ fun setDynamicContentParameters(view: FrameLayout, parameters: ReadableMap?) {
97
+ val parametersMap = parameters?.toHashMap() as? HashMap<String, List<String>>
98
+ videoFeedPropsModel.dynamicContentParameters = parametersMap
99
+ }
100
+
101
+ @ReactPropGroup(names = ["width", "height"], customType = "Style")
102
+ fun setStyle(view: FrameLayout, index: Int, value: Dynamic) {
103
+ // if (index == 0) propWidth = value
104
+ // if (index == 1) propHeight = value
105
+ }
106
+
107
+ private fun setupLayout(view: View) {
108
+ Choreographer.getInstance().postFrameCallback(object : Choreographer.FrameCallback {
109
+ override fun doFrame(frameTimeNanos: Long) {
110
+ manuallyLayoutChildren(view)
111
+ view.viewTreeObserver.dispatchOnGlobalLayout()
112
+ Choreographer.getInstance().postFrameCallback(this)
113
+ }
114
+ })
115
+ }
116
+
117
+ /**
118
+ * Layout all children properly
119
+ */
120
+ private fun manuallyLayoutChildren(view: View) {
121
+ // propWidth and propHeight coming from react-native props
122
+ // val width = requireNotNull(propWidth)
123
+ // val height = requireNotNull(propHeight)
124
+
125
+ view.measure(
126
+ View.MeasureSpec.makeMeasureSpec(view.measuredWidth, View.MeasureSpec.EXACTLY),
127
+ View.MeasureSpec.makeMeasureSpec(view.measuredHeight, View.MeasureSpec.EXACTLY)
128
+ )
129
+
130
+ view.layout(view.left, view.top, view.right, view.bottom)
131
+ }
132
+
133
+
134
+ private fun createFragment(root: FrameLayout, reactNativeViewId: Int?) {
135
+ reactNativeViewId ?: return
136
+ val activity = (reactContext.currentActivity as AppCompatActivity?) ?: return
137
+
138
+ viewId = reactNativeViewId
139
+
140
+ addStoryBlockListener(reactContext)
141
+
142
+ val parentView = root.findViewById(reactNativeViewId) as ViewGroup
143
+ // parentView.setBackgroundColor(Color.YELLOW)
144
+ setupLayout(parentView)
145
+
146
+ val fireworkPlayerFragment = FireworkPlayerFragment()
147
+ this.fireworkPlayerFragment = fireworkPlayerFragment
148
+
149
+ FWLogUtils.d { "FWStoryBlockManager createFragment doOnAttach before" }
150
+ parentView.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
151
+ override fun onViewAttachedToWindow(v: View?) {
152
+ FWLogUtils.d { "FWStoryBlockManager createFragment doOnAttach" }
153
+ // Log.e("isAttachedToWindow", parentView.isAttachedToWindow.toString())
154
+ activity.supportFragmentManager
155
+ .beginTransaction()
156
+ .replace(reactNativeViewId, fireworkPlayerFragment, reactNativeViewId.toString())
157
+ .commitNow()
158
+ parentView.requestLayout()
159
+ // Log.e("isAttachedToWindow", fireworkPlayerFragment.isAdded.toString())
160
+ setStoryBlockParameters()
161
+ }
162
+
163
+ override fun onViewDetachedFromWindow(v: View?) {
164
+ }
165
+
166
+ })
167
+
168
+ // activity.lifecycleScope.launch {
169
+ //// withContext(Dispatchers.Default) {
170
+ //// while (!FwSDK.initialized) {
171
+ //// delay(2000)
172
+ //// }
173
+ //// }
174
+ //
175
+ // withContext(Dispatchers.Main) {
176
+ // if(FwSDK.initialized) {
177
+ // delay(2000)
178
+ // Log.e("isAttachedToWindow", parentView.isAttachedToWindow.toString())
179
+ //// FeedFactory.getVideoFeed(13, FeedType.DISCOVER, null, null)
180
+ // fireworkPlayerFragment.setStoryBlockParameters(FeedType.DISCOVER)
181
+ //// fireworkPlayerFragment.setParameters(13, null)
182
+ // }
183
+ // }
184
+ // }
185
+
186
+ }
187
+
188
+ private fun addStoryBlockListener(reactContext: ReactApplicationContext) {
189
+ val reactNativeViewId = viewId
190
+ reactNativeViewId ?: return
191
+
192
+ FwSDK.addOnPlayerVideoContentStatusListener(object: OnVideoContentStatusListener {
193
+ override fun currentStatus(status: VideoContentStatus, extra: String) {
194
+ when (status) {
195
+ VideoContentStatus.LoadingContent -> {
196
+ FWLogUtils.d { "FWStoryBlockManager VideoContentStatus.LoadingContent" }
197
+ }
198
+ VideoContentStatus.LoadingContentFailed -> {
199
+ FWLogUtils.d { "FWStoryBlockManager VideoContentStatus.LoadingContentFailed" }
200
+ FWEventUtils.receiveStoryBlockLoadFinishedFailedEvent(reactContext, reactNativeViewId, VideoContentStatus.LoadingContentFailed.rawValue, extra)
201
+ }
202
+ VideoContentStatus.ContentLoaded -> {
203
+ FWLogUtils.d { "FWStoryBlockManager VideoContentStatus.ContentLoaded" }
204
+ FWEventUtils.receiveStoryBlockLoadFinishedSuccessEvent(reactContext, reactNativeViewId)
205
+ }
206
+ VideoContentStatus.ContentOver -> {
207
+ FWLogUtils.d { "FWStoryBlockManager VideoContentStatus.ContentOver" }
208
+ }
209
+ VideoContentStatus.ContentExpired -> {
210
+ FWLogUtils.d { "FWStoryBlockManager VideoContentStatus.ContentExpired" }
211
+ }
212
+ else -> {}
213
+ }
214
+ }
215
+ })
216
+ }
217
+
218
+ override fun onDropViewInstance(view: FrameLayout) {
219
+ LocalBroadcastManager.getInstance(reactContext).unregisterReceiver(broadcastReceiver)
220
+ super.onDropViewInstance(view)
221
+ }
222
+
223
+ override fun getExportedCustomBubblingEventTypeConstants(): MutableMap<String, Any>? {
224
+ return MapBuilder.builder<String, Any>()
225
+ .put(FWStoryBlockEventName.StoryBlockLoadFinished.rawValue, MapBuilder.of("phasedRegistrationNames", MapBuilder.of("bubbled", FWStoryBlockEventName.StoryBlockLoadFinished.rawValue)))
226
+ .build()
227
+ }
228
+
229
+ companion object {
230
+ private const val REACT_CLASS = "FWStoryBlock"
231
+ const val FW_STORY_BLOCK_INIT_ACTION = "FW_STORY_BLOCK_INIT_ACTION"
232
+ const val FW_STORY_BLOCK_INIT_INTENT = "FW_STORY_BLOCK_INIT_INTENT"
233
+ private const val COMMAND_CREATE = 1
234
+ }
235
+
236
+ private fun setStoryBlockParameters() {
237
+ FWLogUtils.d { "FWStoryBlockManager setStoryBlockParameters viewId: $viewId, source: ${videoFeedPropsModel.source}, initSuccess: ${FireworkSDKModule.initSuccess}" }
238
+ val source = videoFeedPropsModel.source
239
+ if (source.isNullOrBlank()) {
240
+ return
241
+ }
242
+
243
+ val dynamicContentParameters = videoFeedPropsModel.dynamicContentParameters
244
+ val channel = videoFeedPropsModel.channel
245
+ val playlist = videoFeedPropsModel.playlist
246
+
247
+ if (FireworkSDKModule.initSuccess) {
248
+ when (source) {
249
+ FWVideoFeedSource.DynamicContent.rawValue -> {
250
+ fireworkPlayerFragment?.setStoryBlockParameters(FeedType.DYNAMIC_CONTENT, channel, playlist, dynamicContentParameters)
251
+ }
252
+ FWVideoFeedSource.Playlist.rawValue -> {
253
+ fireworkPlayerFragment?.setStoryBlockParameters(FeedType.PLAYLIST, channel, playlist)
254
+ }
255
+ FWVideoFeedSource.Channel.rawValue -> {
256
+ fireworkPlayerFragment?.setStoryBlockParameters(FeedType.CHANNEL, channel)
257
+ }
258
+ else -> {
259
+ fireworkPlayerFragment?.setStoryBlockParameters(FeedType.DISCOVER)
260
+ }
261
+ }
262
+ }
263
+ }
264
+
265
+ inner class MyReceiver : BroadcastReceiver() {
266
+
267
+ override fun onReceive(context: Context?, intent: Intent) {
268
+ val initSuccess = intent.getBooleanExtra(FW_STORY_BLOCK_INIT_INTENT, false)
269
+ if (initSuccess) {
270
+ setStoryBlockParameters()
271
+ }
272
+ }
273
+ }
274
+ }
@@ -72,11 +72,11 @@ class FWVideoFeedManager : SimpleViewManager<FWVideoFeed>() {
72
72
  }
73
73
  VideoContentStatus.LoadingContentFailed -> {
74
74
  FWLogUtils.d { "VideoContentStatus.LoadingContentFailed" }
75
- FWEventUtils.receiveVideoFeedLoadFinishedFailedEvent(reactContext, videoFeedView.id, VideoContentStatus.LoadingContentFailed.rawValue, extra)
75
+ FWEventUtils.receiveVideoFeedLoadFinishedFailedEvent(reactContext, videoFeed.id, VideoContentStatus.LoadingContentFailed.rawValue, extra)
76
76
  }
77
77
  VideoContentStatus.ContentLoaded -> {
78
78
  FWLogUtils.d { "VideoContentStatus.ContentLoaded" }
79
- FWEventUtils.receiveVideoFeedLoadFinishedSuccessEvent(reactContext, videoFeedView.id)
79
+ FWEventUtils.receiveVideoFeedLoadFinishedSuccessEvent(reactContext, videoFeed.id)
80
80
  }
81
81
  else -> {
82
82
  FWLogUtils.d { "VideoContentStatus: $status" }
@@ -114,11 +114,14 @@ class FWVideoFeedManager : SimpleViewManager<FWVideoFeed>() {
114
114
  }
115
115
  VideoContentStatus.LoadingContentFailed -> {
116
116
  FWLogUtils.d { "VideoContentStatus.LoadingContentFailed" }
117
- FWEventUtils.receiveVideoFeedLoadFinishedFailedEvent(reactContext, playlistGroupFeedView.id, VideoContentStatus.LoadingContentFailed.rawValue, extra)
117
+ FWEventUtils.receiveVideoFeedLoadFinishedFailedEvent(reactContext, videoFeed.id, VideoContentStatus.LoadingContentFailed.rawValue, extra)
118
118
  }
119
119
  VideoContentStatus.ContentLoaded -> {
120
120
  FWLogUtils.d { "VideoContentStatus.ContentLoaded" }
121
- FWEventUtils.receiveVideoFeedLoadFinishedSuccessEvent(reactContext, playlistGroupFeedView.id)
121
+ FWEventUtils.receiveVideoFeedLoadFinishedSuccessEvent(reactContext, videoFeed.id)
122
+ }
123
+ else -> {
124
+ FWLogUtils.d { "VideoContentStatus: $status" }
122
125
  }
123
126
  }
124
127
  }
@@ -178,11 +181,15 @@ class FWVideoFeedManager : SimpleViewManager<FWVideoFeed>() {
178
181
  return map
179
182
  }
180
183
 
181
- override fun receiveCommand(root: FWVideoFeed, commandId: Int, args: ReadableArray?) {
182
- when (commandId) {
183
- FWCommandConstant.FW_COMMAND_VIDEO_FEED_REFRESH -> {
184
- root.refresh()
185
- }
184
+ override fun receiveCommand(root: FWVideoFeed, commandId: String?, args: ReadableArray?) {
185
+ super.receiveCommand(root, commandId, args)
186
+ FWLogUtils.d { "FWVideoFeedManager receiveCommand commandId: $commandId" }
187
+ when (commandId?.toInt()) {
188
+ FWCommandConstant.FW_COMMAND_VIDEO_FEED_REFRESH -> {
189
+ FWLogUtils.d { "FWVideoFeedManager call refresh" }
190
+ root.refresh()
191
+ }
192
+ else -> {}
186
193
  }
187
194
  }
188
195
 
@@ -1,8 +1,10 @@
1
1
  package com.fireworksdk.bridge.reactnative.module
2
2
 
3
3
  import android.annotation.SuppressLint
4
+ import android.content.Intent
4
5
  import android.content.pm.PackageManager
5
6
  import android.provider.Settings
7
+ import androidx.localbroadcastmanager.content.LocalBroadcastManager
6
8
  import com.facebook.react.bridge.*
7
9
  import com.fireworksdk.bridge.models.FWVideoPlaybackDetails
8
10
  import com.fireworksdk.bridge.models.FWVideoPlaybackSubEventName
@@ -12,6 +14,7 @@ import org.json.JSONObject
12
14
  import com.facebook.react.bridge.ReactMethod
13
15
  import com.fireworksdk.bridge.models.FWAdBadgeConfigModel
14
16
  import com.fireworksdk.bridge.FWInitializationProvider
17
+ import com.fireworksdk.bridge.reactnative.manager.FWStoryBlockManager
15
18
  import com.fireworksdk.bridge.reactnative.models.FireworkSDKInterface
16
19
  import com.fireworksdk.bridge.reactnative.pages.FWContainerActivity
17
20
  import com.fireworksdk.bridge.reactnative.utils.FWEventUtils
@@ -131,6 +134,15 @@ class FireworkSDKModule(
131
134
  when (status) {
132
135
  SdkStatus.Initialized -> {
133
136
  FWEventUtils.sendInitSuccessEvent(reactApplicationContext)
137
+
138
+ initSuccess = true
139
+ val intent = Intent()
140
+ intent.action = FWStoryBlockManager.FW_STORY_BLOCK_INIT_ACTION
141
+ intent.putExtra(
142
+ FWStoryBlockManager.FW_STORY_BLOCK_INIT_INTENT,
143
+ initSuccess
144
+ )
145
+ LocalBroadcastManager.getInstance(reactApplicationContext).sendBroadcast(intent)
134
146
  }
135
147
  SdkStatus.InitializationFailed -> {
136
148
  FWEventUtils.sendInitFailedEvent(reactApplicationContext, extra)
@@ -278,6 +290,7 @@ class FireworkSDKModule(
278
290
  companion object {
279
291
  var appComponentName: String? = null
280
292
  var customCTALinkContentPageRouteName: String? = null
293
+ var initSuccess: Boolean = false
281
294
  }
282
295
 
283
296
  }
@@ -194,6 +194,17 @@ object FWEventUtils {
194
194
  receiveEvent(reactContext, targetTag, FWFeedViewEventName.VideoFeedLoadFinished.rawValue, eventMap)
195
195
  }
196
196
 
197
+ fun receiveStoryBlockLoadFinishedSuccessEvent(reactContext: ReactContext, targetTag: Int) {
198
+ receiveEvent(reactContext, targetTag, FWStoryBlockEventName.StoryBlockLoadFinished.rawValue, null)
199
+ }
200
+
201
+ fun receiveStoryBlockLoadFinishedFailedEvent(reactContext: ReactContext, targetTag: Int, name: String, reason: String?) {
202
+ val eventMap = Arguments.createMap()
203
+ eventMap.putString("name", name)
204
+ eventMap.putString("reason", reason)
205
+ receiveEvent(reactContext, targetTag, FWStoryBlockEventName.StoryBlockLoadFinished.rawValue, eventMap)
206
+ }
207
+
197
208
  private fun receiveEvent(reactContext: ReactContext, targetTag: Int, eventName: String, event: WritableMap?) {
198
209
  reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(
199
210
  targetTag,
@@ -10,10 +10,6 @@
10
10
  android:id="@+id/fw_bridge_videofeed"
11
11
  android:layout_width="match_parent"
12
12
  android:layout_height="match_parent"
13
- app:feedLayout="horizontal"
14
- app:showTitle="true"
15
- app:titlePosition="alignBottom"
16
- app:feedType="discover"
17
13
  app:imageStyle="@style/FWFeedViewImageStyle"
18
14
  app:textStyle="@style/FWFeedViewCaptionStyle"
19
15
  />
@@ -0,0 +1,105 @@
1
+ //
2
+ // StoryBlock.swift
3
+ // react-native-firework-sdk
4
+ //
5
+ // Created by linjie jiang on 2022/8/11.
6
+ //
7
+
8
+ import UIKit
9
+ import FireworkVideo
10
+
11
+ @objc
12
+ public enum StoryBlockSourceType: Int {
13
+ case discover, channel, playlist, dynamicContent
14
+ }
15
+
16
+ public protocol StoryBlockViewDelegate: AnyObject {
17
+ func storyBlockDidLoadFeed(_ view: StoryBlock);
18
+ func storyBlock(_ view: StoryBlock, didFailToLoadFeed error: StoryBlockError)
19
+ }
20
+
21
+ @objc
22
+ public class StoryBlock: UIView, StoryBlockViewControllerDelegate {
23
+ @objc public var sourceType: StoryBlockSourceType = .discover
24
+ @objc public var channel: String = ""
25
+ @objc public var playlist: String = ""
26
+ @objc public var dynamicContentParameters: [String: [String]] = [:]
27
+
28
+ public weak var delegate: StoryBlockViewDelegate?
29
+
30
+ @objc var onStoryBlockLoadFinished: RCTBubblingEventBlock?
31
+
32
+ private var storyBlockVC: StoryBlockViewController?
33
+
34
+ private var source: StoryBlockContentSource {
35
+ switch sourceType {
36
+ case .discover:
37
+ return .discover
38
+ case .channel:
39
+ return .channel(channelID: channel)
40
+ case .playlist:
41
+ return .channelPlaylist(channelID: channel, playlistID: playlist)
42
+ case .dynamicContent:
43
+ return .dynamicContent(channelID: channel, parameters: dynamicContentParameters)
44
+ }
45
+ }
46
+
47
+ public override init(frame: CGRect) {
48
+ super.init(frame: frame)
49
+ self.clipsToBounds = true
50
+ }
51
+
52
+ required init?(coder: NSCoder) {
53
+ super.init(coder: coder)
54
+ self.clipsToBounds = true
55
+ }
56
+
57
+ public override func layoutSubviews() {
58
+ super.layoutSubviews()
59
+ embed()
60
+ }
61
+
62
+ private func embed() {
63
+ guard let parentVC = parentViewController else {
64
+ return
65
+ }
66
+ guard self.storyBlockVC == nil else {
67
+ return
68
+ }
69
+
70
+ let storyBlockVC = StoryBlockViewController(source: source)
71
+ storyBlockVC.delegate = self
72
+ self.storyBlockVC = storyBlockVC
73
+
74
+ parentVC.attachChild(storyBlockVC, to: self)
75
+ }
76
+
77
+
78
+ public override func removeFromSuperview() {
79
+ super.removeFromSuperview()
80
+
81
+ guard let storyBlockVC = self.storyBlockVC else {
82
+ return
83
+ }
84
+
85
+ storyBlockVC.pause()
86
+ storyBlockVC.detachFromParent()
87
+ self.storyBlockVC = nil
88
+ }
89
+
90
+ public func storyBlockDidLoadFeed(_ viewController: StoryBlockViewController) {
91
+ guard let delegate = self.delegate else {
92
+ return
93
+ }
94
+
95
+ delegate.storyBlockDidLoadFeed(self)
96
+ }
97
+
98
+ public func storyBlock(_ viewController: StoryBlockViewController, didFailToLoadFeed error: StoryBlockError) {
99
+ guard let delegate = self.delegate else {
100
+ return
101
+ }
102
+
103
+ delegate.storyBlock(self, didFailToLoadFeed: error)
104
+ }
105
+ }
@@ -0,0 +1,29 @@
1
+ //
2
+ // StoryBlockManager.m
3
+ // react-native-firework-sdk
4
+ //
5
+ // Created by linjie jiang on 2022/8/11.
6
+ //
7
+
8
+ #import <React/RCTBridgeModule.h>
9
+ #import <React/RCTViewManager.h>
10
+ #import <React/RCTUIManager.h>
11
+ #import "react_native_firework_sdk-Swift.h"
12
+
13
+ @interface RCT_EXTERN_REMAP_MODULE(FWStoryBlock, StoryBlockManager, NSObject)
14
+
15
+ RCT_CUSTOM_VIEW_PROPERTY(source, StoryBlockSource, StoryBlock) {
16
+ if (json) {
17
+ StoryBlockSourceType sourceType = [RCTConvert storyBlockSourceType: json];
18
+ view.sourceType = sourceType;
19
+ }
20
+ }
21
+ RCT_EXPORT_VIEW_PROPERTY(channel, NSString)
22
+ RCT_EXPORT_VIEW_PROPERTY(playlist, NSString)
23
+ RCT_EXPORT_VIEW_PROPERTY(dynamicContentParameters, NSDictionary)
24
+
25
+
26
+ RCT_EXPORT_VIEW_PROPERTY(onStoryBlockLoadFinished, RCTBubblingEventBlock)
27
+
28
+ @end
29
+
@@ -0,0 +1,31 @@
1
+ //
2
+ // StoryBlockManager.swift
3
+ // react-native-firework-sdk
4
+ //
5
+ // Created by linjie jiang on 2022/8/11.
6
+ //
7
+
8
+ import Foundation
9
+ import FireworkVideo
10
+
11
+ @objc(StoryBlockManager)
12
+ class StoryBlockManager: RCTViewManager, StoryBlockViewDelegate {
13
+ override func view() -> UIView! {
14
+ let storyBlock = StoryBlock()
15
+ storyBlock.delegate = self
16
+
17
+ return storyBlock
18
+ }
19
+
20
+ override class func requiresMainQueueSetup() -> Bool {
21
+ return true
22
+ }
23
+
24
+ func storyBlockDidLoadFeed(_ view: StoryBlock) {
25
+ view.onStoryBlockLoadFinished?(nil)
26
+ }
27
+
28
+ func storyBlock(_ view: StoryBlock, didFailToLoadFeed error: StoryBlockError) {
29
+ view.onStoryBlockLoadFinished?(error.jsObject)
30
+ }
31
+ }