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.
- package/android/build.gradle +2 -8
- package/android/src/main/java/com/fireworksdk/bridge/FireworkSDKPackage.kt +6 -2
- package/android/src/main/java/com/fireworksdk/bridge/models/FWEventName.kt +4 -0
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWStoryBlockManager.kt +274 -0
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWVideoFeedManager.kt +16 -9
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +13 -0
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +11 -0
- package/android/src/main/res/layout/fw_bridge_fragment_videofeed.xml +0 -4
- package/ios/Components/StoryBlock.swift +105 -0
- package/ios/Components/StoryBlockManager.m +29 -0
- package/ios/Components/StoryBlockManager.swift +31 -0
- package/ios/Components/VideoFeed.swift +8 -16
- package/ios/FireworkSdk.xcodeproj/project.pbxproj +26 -4
- package/ios/Models/NativeToRN/FireworkSDK+Json.swift +23 -5
- package/ios/Models/RNToNative/RCTConvert+StoryBlock.swift +28 -0
- package/ios/Models/RNToNative/RCTConvert+VideoFeed.swift +2 -2
- package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +1 -1
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule+CTA.swift +2 -0
- package/ios/Modules/Shopping/{CartViewController.swift → FWCartViewController.swift} +8 -7
- package/ios/Modules/Shopping/ShoppingModule.swift +4 -3
- package/ios/Utils/UINavigationController+FWSwizzle.h +16 -0
- package/ios/Utils/UINavigationController+FWSwizzle.m +49 -0
- package/ios/Utils/UIViewController+AttachChild.swift +8 -11
- package/lib/commonjs/components/FWStoryBlock.js +18 -0
- package/lib/commonjs/components/FWStoryBlock.js.map +1 -0
- package/lib/commonjs/components/StoryBlock.js +174 -0
- package/lib/commonjs/components/StoryBlock.js.map +1 -0
- package/lib/commonjs/components/VideoFeed.js +31 -17
- package/lib/commonjs/components/VideoFeed.js.map +1 -1
- package/lib/commonjs/index.js +8 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/StoryBlockSource.js +2 -0
- package/lib/commonjs/models/StoryBlockSource.js.map +1 -0
- package/lib/module/components/FWStoryBlock.js +8 -0
- package/lib/module/components/FWStoryBlock.js.map +1 -0
- package/lib/module/components/StoryBlock.js +150 -0
- package/lib/module/components/StoryBlock.js.map +1 -0
- package/lib/module/components/VideoFeed.js +31 -16
- package/lib/module/components/VideoFeed.js.map +1 -1
- package/lib/module/index.js +2 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/StoryBlockSource.js +2 -0
- package/lib/module/models/StoryBlockSource.js.map +1 -0
- package/lib/typescript/components/FWStoryBlock.d.ts +2 -0
- package/lib/typescript/components/StoryBlock.d.ts +42 -0
- package/lib/typescript/index.d.ts +3 -1
- package/lib/typescript/models/StoryBlockSource.d.ts +1 -0
- package/package.json +1 -1
- package/react-native-firework-sdk.podspec +1 -1
- package/src/components/FWStoryBlock.tsx +10 -0
- package/src/components/StoryBlock.tsx +180 -0
- package/src/components/VideoFeed.tsx +30 -23
- package/src/index.tsx +4 -0
- package/src/models/StoryBlockSource.ts +5 -0
package/android/build.gradle
CHANGED
|
@@ -168,16 +168,9 @@ def kotlin_version = getExtOrDefault('kotlinVersion')
|
|
|
168
168
|
|
|
169
169
|
dependencies {
|
|
170
170
|
|
|
171
|
-
|
|
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(
|
|
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
|
+
}
|
package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWStoryBlockManager.kt
ADDED
|
@@ -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
|
+
}
|
package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWVideoFeedManager.kt
CHANGED
|
@@ -72,11 +72,11 @@ class FWVideoFeedManager : SimpleViewManager<FWVideoFeed>() {
|
|
|
72
72
|
}
|
|
73
73
|
VideoContentStatus.LoadingContentFailed -> {
|
|
74
74
|
FWLogUtils.d { "VideoContentStatus.LoadingContentFailed" }
|
|
75
|
-
FWEventUtils.receiveVideoFeedLoadFinishedFailedEvent(reactContext,
|
|
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,
|
|
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,
|
|
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,
|
|
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:
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
|
package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt
CHANGED
|
@@ -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
|
+
}
|