react-native-firework-sdk 1.3.0-beta.2 → 1.3.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.
- package/android/build.gradle +2 -2
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/fireworksdk/bridge/{reactnative/FWInitializationProvider.kt → FWInitializationProvider.kt} +1 -1
- package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedConfigModel.kt +3 -1
- package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModel.kt +1 -0
- package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoShoppingProduct.kt +1 -0
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWVideoFeedManager.kt +5 -2
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWNavigatorModule.kt +1 -1
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt +44 -30
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +1 -1
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +5 -5
- package/android/src/main/java/com/fireworksdk/bridge/utils/FWVideoPlayerUtils.kt +18 -0
- package/ios/Components/VideoFeed.swift +95 -35
- package/ios/Components/VideoFeedConfiguration.swift +15 -3
- package/ios/Components/VideoPlayerConfiguration.swift +3 -2
- package/ios/Models/RNToNative/RCTConvert+FireworkSDKModule.swift +24 -4
- package/ios/Models/RNToNative/RCTConvert+VideoFeed.swift +1 -1
- package/ios/Modules/Shopping/CartViewController.swift +22 -39
- package/ios/Modules/Shopping/Product.swift +1 -0
- package/ios/Modules/Shopping/ProductInfoViewConfiguration.swift +1 -6
- package/ios/Modules/Shopping/ShoppingModule.m +1 -0
- package/ios/Modules/Shopping/ShoppingModule.swift +28 -16
- package/lib/commonjs/VideoShopping.js +25 -9
- package/lib/commonjs/VideoShopping.js.map +1 -1
- package/lib/commonjs/components/VideoFeed.js +28 -3
- package/lib/commonjs/components/VideoFeed.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/modules/ShoppingModule.js.map +1 -1
- package/lib/module/VideoShopping.js +24 -9
- package/lib/module/VideoShopping.js.map +1 -1
- package/lib/module/components/VideoFeed.js +28 -3
- package/lib/module/components/VideoFeed.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/modules/ShoppingModule.js.map +1 -1
- package/lib/typescript/VideoShopping.d.ts +15 -1
- package/lib/typescript/components/VideoFeed.d.ts +1 -0
- package/lib/typescript/index.d.ts +3 -3
- package/lib/typescript/models/ProductUnit.d.ts +12 -0
- package/lib/typescript/models/VideoFeedConfiguration.d.ts +33 -5
- package/lib/typescript/models/VideoPlayerConfiguration.d.ts +5 -1
- package/lib/typescript/modules/ShoppingModule.d.ts +1 -0
- package/package.json +2 -6
- package/react-native-firework-sdk.podspec +1 -1
- package/src/VideoShopping.ts +30 -3
- package/src/components/VideoFeed.tsx +22 -1
- package/src/index.tsx +4 -1
- package/src/models/ProductUnit.ts +13 -0
- package/src/models/VideoFeedConfiguration.ts +34 -5
- package/src/models/VideoPlayerConfiguration.ts +5 -1
- package/src/modules/ShoppingModule.ts +1 -0
package/android/build.gradle
CHANGED
|
@@ -38,7 +38,7 @@ android {
|
|
|
38
38
|
defaultConfig {
|
|
39
39
|
minSdkVersion 21
|
|
40
40
|
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
|
|
41
|
-
versionCode
|
|
41
|
+
versionCode 1
|
|
42
42
|
versionName "1.0.0"
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -168,7 +168,7 @@ def kotlin_version = getExtOrDefault('kotlinVersion')
|
|
|
168
168
|
dependencies {
|
|
169
169
|
|
|
170
170
|
// optional 1: firework sdk release verison
|
|
171
|
-
def firework_sdk_version = 'v5.
|
|
171
|
+
def firework_sdk_version = 'v5.13.2'
|
|
172
172
|
implementation "com.github.loopsocial:firework_sdk:$firework_sdk_version"
|
|
173
173
|
|
|
174
174
|
// optional 2: firework sdk local version,
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
|
|
13
13
|
/>
|
|
14
14
|
<provider
|
|
15
|
-
android:authorities="
|
|
16
|
-
android:name=".
|
|
15
|
+
android:authorities="${applicationId}.fwBridgeProvider"
|
|
16
|
+
android:name="com.fireworksdk.bridge.FWInitializationProvider"
|
|
17
17
|
android:exported="false"
|
|
18
18
|
/>
|
|
19
19
|
<meta-data
|
|
@@ -11,7 +11,9 @@ data class FWVideoFeedConfigModel(
|
|
|
11
11
|
var titlePosition: String? = null,
|
|
12
12
|
var playIcon: FWPlayIconModel? = null,
|
|
13
13
|
var showAdBadge: Boolean? = null,
|
|
14
|
-
var customLayoutName: String? = null
|
|
14
|
+
var customLayoutName: String? = null,
|
|
15
|
+
var enableAutoplay: Boolean? = null,
|
|
16
|
+
val gridColumns: Int? = null,
|
|
15
17
|
) : Parcelable {
|
|
16
18
|
|
|
17
19
|
@Parcelize
|
package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWVideoFeedManager.kt
CHANGED
|
@@ -78,6 +78,9 @@ class FWVideoFeedManager : SimpleViewManager<FWVideoFeed>() {
|
|
|
78
78
|
FWLogUtils.d { "VideoContentStatus.ContentLoaded" }
|
|
79
79
|
FWEventUtils.receiveVideoFeedLoadFinishedSuccessEvent(reactContext, videoFeedView.id)
|
|
80
80
|
}
|
|
81
|
+
else -> {
|
|
82
|
+
FWLogUtils.d { "VideoContentStatus: $status" }
|
|
83
|
+
}
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
})
|
|
@@ -86,13 +89,13 @@ class FWVideoFeedManager : SimpleViewManager<FWVideoFeed>() {
|
|
|
86
89
|
private fun addPlaylistGroupFeedListener(reactContext: ThemedReactContext, videoFeed: FWVideoFeed?) {
|
|
87
90
|
val playlistGroupFeedView = videoFeed?.playlistGroupFeedView
|
|
88
91
|
playlistGroupFeedView?.itemClickHandler = object : OnPlaylistGroupItemClickedListener {
|
|
89
|
-
override fun onItemClicked(index: Int, id: String
|
|
92
|
+
override fun onItemClicked(index: Int, title: String, id: String): Boolean {
|
|
90
93
|
val fwVideoFeedItemDetailsModel = FWVideoFeedItemDetailsModel(
|
|
91
94
|
index,
|
|
92
95
|
id,
|
|
93
96
|
0,
|
|
94
97
|
videoFeed?.videoFeedPropsModel?.source,
|
|
95
|
-
|
|
98
|
+
title,
|
|
96
99
|
videoFeed?.videoFeedPropsModel?.playlistGroup,
|
|
97
100
|
videoFeed?.videoFeedPropsModel?.playlist,
|
|
98
101
|
videoFeed?.videoFeedPropsModel?.channel,
|
package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWNavigatorModule.kt
CHANGED
|
@@ -2,7 +2,7 @@ package com.fireworksdk.bridge.reactnative.module
|
|
|
2
2
|
|
|
3
3
|
import android.app.Activity
|
|
4
4
|
import com.facebook.react.bridge.*
|
|
5
|
-
import com.fireworksdk.bridge.
|
|
5
|
+
import com.fireworksdk.bridge.FWInitializationProvider
|
|
6
6
|
import com.fireworksdk.bridge.reactnative.models.FWNavigatorInterface
|
|
7
7
|
import com.fireworksdk.bridge.reactnative.utils.FWEventUtils
|
|
8
8
|
import com.fireworksdk.bridge.utils.FWLogUtils
|
package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt
CHANGED
|
@@ -10,8 +10,7 @@ import com.fireworksdk.bridge.utils.FWLogUtils
|
|
|
10
10
|
import com.google.gson.reflect.TypeToken
|
|
11
11
|
import com.loopnow.fireworklibrary.baya.Baya
|
|
12
12
|
import com.loopnow.fireworklibrary.baya.UpdateCartStatus
|
|
13
|
-
import com.loopnow.fireworklibrary.data.
|
|
14
|
-
import com.loopnow.fireworklibrary.utils.Util
|
|
13
|
+
import com.loopnow.fireworklibrary.data.ProductBuilder
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
class FWVideoShoppingModule(
|
|
@@ -20,7 +19,7 @@ class FWVideoShoppingModule(
|
|
|
20
19
|
|
|
21
20
|
private var addToCartHandler: Triple<Int, String, String>? = null
|
|
22
21
|
private var cartClickHandler: Pair<Int, Activity>? = null
|
|
23
|
-
private val updateProductHandler: HashMap<String, List<
|
|
22
|
+
private val updateProductHandler: HashMap<String, List<ProductBuilder>> = HashMap()
|
|
24
23
|
|
|
25
24
|
@ReactMethod
|
|
26
25
|
override fun init() {
|
|
@@ -45,37 +44,52 @@ class FWVideoShoppingModule(
|
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
val products = updateProductHandler[videoId] ?: return
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
47
|
+
val newProducts = products.map { product ->
|
|
48
|
+
val vps = videoShoppingProducts.filter { vp ->
|
|
49
|
+
vp.productId == product.externalId
|
|
50
|
+
}
|
|
51
|
+
if (vps.isNullOrEmpty()) {
|
|
52
|
+
product.copy()
|
|
53
|
+
} else {
|
|
54
|
+
val videoShoppingProduct = vps[0]
|
|
55
|
+
|
|
56
|
+
product.copy(
|
|
57
|
+
name = videoShoppingProduct.name ?: product.name,
|
|
58
|
+
description = videoShoppingProduct.description ?: product.description,
|
|
59
|
+
units = product.units?.map { productBuilderUnit ->
|
|
60
|
+
val vpUs = videoShoppingProduct.units?.filter { vpU ->
|
|
61
|
+
vpU.unitId == productBuilderUnit.externalId
|
|
62
|
+
}
|
|
63
|
+
if (vpUs.isNullOrEmpty()) {
|
|
64
|
+
productBuilderUnit.copy()
|
|
65
|
+
} else {
|
|
66
|
+
val videoShoppingProductUnit = vpUs[0]
|
|
67
|
+
|
|
68
|
+
productBuilderUnit.copy(
|
|
69
|
+
image = productBuilderUnit.image?.copy(
|
|
70
|
+
url = videoShoppingProductUnit.imageUrl ?: productBuilderUnit.image?.url,
|
|
71
|
+
),
|
|
72
|
+
url = videoShoppingProductUnit.url ?: productBuilderUnit.url,
|
|
73
|
+
name = videoShoppingProductUnit.name ?: productBuilderUnit.name,
|
|
74
|
+
price = productBuilderUnit.price?.copy(
|
|
75
|
+
amount = videoShoppingProductUnit.price?.amount?.toString() ?: productBuilderUnit.price?.amount,
|
|
76
|
+
currencyCode = videoShoppingProductUnit.price?.currencyCode ?: productBuilderUnit.price?.currencyCode,
|
|
77
|
+
),
|
|
78
|
+
options = videoShoppingProductUnit.options?.map {
|
|
79
|
+
ProductBuilder.ProductBuilderUnit.ProductBuilderUnitOption(
|
|
80
|
+
name = it.name,
|
|
81
|
+
value = it.value,
|
|
82
|
+
)
|
|
83
|
+
} ?: productBuilderUnit.options
|
|
84
|
+
)
|
|
71
85
|
}
|
|
72
86
|
}
|
|
73
|
-
|
|
74
|
-
}
|
|
87
|
+
)
|
|
75
88
|
}
|
|
76
89
|
}
|
|
90
|
+
|
|
77
91
|
UiThreadUtil.runOnUiThread {
|
|
78
|
-
Baya.updateProductsComplete(videoId)
|
|
92
|
+
Baya.updateProductsComplete(videoId, newProducts)
|
|
79
93
|
}
|
|
80
94
|
updateProductHandler.remove(videoId)
|
|
81
95
|
}
|
|
@@ -161,7 +175,7 @@ class FWVideoShoppingModule(
|
|
|
161
175
|
|
|
162
176
|
private fun productListener() {
|
|
163
177
|
Baya.productInterface = object: Baya.ProductInterface {
|
|
164
|
-
override fun hydrateProducts(videoId: String, products: List<
|
|
178
|
+
override fun hydrateProducts(videoId: String, products: List<ProductBuilder>) {
|
|
165
179
|
FWLogUtils.d { "FWVideoShoppingModule hydrateProducts, videoId: $videoId" }
|
|
166
180
|
if (videoId.isNullOrBlank() || products.isNullOrEmpty()) {
|
|
167
181
|
return
|
package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt
CHANGED
|
@@ -11,7 +11,7 @@ import com.fireworksdk.bridge.utils.*
|
|
|
11
11
|
import org.json.JSONObject
|
|
12
12
|
import com.facebook.react.bridge.ReactMethod
|
|
13
13
|
import com.fireworksdk.bridge.models.FWAdBadgeConfigModel
|
|
14
|
-
import com.fireworksdk.bridge.
|
|
14
|
+
import com.fireworksdk.bridge.FWInitializationProvider
|
|
15
15
|
import com.fireworksdk.bridge.reactnative.models.FireworkSDKInterface
|
|
16
16
|
import com.fireworksdk.bridge.reactnative.pages.FWContainerActivity
|
|
17
17
|
import com.fireworksdk.bridge.reactnative.utils.FWEventUtils
|
|
@@ -5,12 +5,12 @@ import com.facebook.react.bridge.*
|
|
|
5
5
|
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
6
6
|
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
7
7
|
import com.fireworksdk.bridge.models.*
|
|
8
|
-
import com.fireworksdk.bridge.
|
|
8
|
+
import com.fireworksdk.bridge.FWInitializationProvider
|
|
9
9
|
import com.fireworksdk.bridge.reactnative.module.FireworkSDKModule
|
|
10
10
|
import com.fireworksdk.bridge.reactnative.pages.FWContainerActivity
|
|
11
11
|
import com.fireworksdk.bridge.utils.FWDateUtils
|
|
12
12
|
import com.fireworksdk.bridge.utils.FWLogUtils
|
|
13
|
-
import com.loopnow.fireworklibrary.data.
|
|
13
|
+
import com.loopnow.fireworklibrary.data.ProductBuilder
|
|
14
14
|
import java.util.*
|
|
15
15
|
|
|
16
16
|
object FWEventUtils {
|
|
@@ -19,7 +19,7 @@ object FWEventUtils {
|
|
|
19
19
|
FWLogUtils.d { "FWNavigatorModule pushNativeContainer: $props" }
|
|
20
20
|
val activity = FWInitializationProvider.INSTANCE.resumedActivity
|
|
21
21
|
|
|
22
|
-
if (activity == null) {
|
|
22
|
+
if (activity == null || FireworkSDKModule.appComponentName.isNullOrBlank()) {
|
|
23
23
|
promise?.resolve(false)
|
|
24
24
|
return
|
|
25
25
|
}
|
|
@@ -147,13 +147,13 @@ object FWEventUtils {
|
|
|
147
147
|
sendEvent(reactContext, FWVideoShoppingEventName.ClickCartIcon.rawValue, eventMap)
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
fun sendUpdateProductsDetailsEvent(reactContext: ReactContext, products: List<
|
|
150
|
+
fun sendUpdateProductsDetailsEvent(reactContext: ReactContext, products: List<ProductBuilder>?, videoId: String?) {
|
|
151
151
|
val eventMap = Arguments.createMap()
|
|
152
152
|
|
|
153
153
|
val productArray = Arguments.createArray()
|
|
154
154
|
if (!products.isNullOrEmpty()) {
|
|
155
155
|
for (product in products) {
|
|
156
|
-
productArray.pushString(product.
|
|
156
|
+
productArray.pushString(product.externalId)
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
|
|
@@ -65,6 +65,14 @@ object FWVideoPlayerUtils {
|
|
|
65
65
|
}
|
|
66
66
|
feedView?.setTitlePosition(titlePosition)
|
|
67
67
|
VideoFeedProperties.displayAdLabel = config?.showAdBadge == true
|
|
68
|
+
feedView?.viewModel?.apply {
|
|
69
|
+
val columns = config?.gridColumns ?: 0
|
|
70
|
+
gridColumns = if (columns > 0) {
|
|
71
|
+
columns
|
|
72
|
+
} else {
|
|
73
|
+
2
|
|
74
|
+
}
|
|
75
|
+
}
|
|
68
76
|
}
|
|
69
77
|
|
|
70
78
|
fun setVideoFeedConfig(context: Context, feedView: VideoFeedView?, config: FWVideoFeedConfigModel?) {
|
|
@@ -87,10 +95,20 @@ object FWVideoPlayerUtils {
|
|
|
87
95
|
else -> FeedTitlePosition.ALIGN_BOTTOM
|
|
88
96
|
}
|
|
89
97
|
feedView?.setTitlePosition(titlePosition)
|
|
98
|
+
feedView?.setAutoPlayOnFeed(config?.enableAutoplay == true)
|
|
90
99
|
VideoFeedProperties.displayAdLabel = config?.showAdBadge == true
|
|
100
|
+
feedView?.viewModel?.apply {
|
|
101
|
+
val columns = config?.gridColumns ?: 0
|
|
102
|
+
gridColumns = if (columns > 0) {
|
|
103
|
+
columns
|
|
104
|
+
} else {
|
|
105
|
+
2
|
|
106
|
+
}
|
|
107
|
+
}
|
|
91
108
|
}
|
|
92
109
|
|
|
93
110
|
fun setVideoPlayerConfig(config: FWVideoPlayerConfigModel?) {
|
|
111
|
+
VideoPlayerProperties.branding = config?.showBranding != false
|
|
94
112
|
VideoPlayerProperties.share = config?.showShareButton != false
|
|
95
113
|
VideoPlayerProperties.loop = config?.videoCompleteAction != FWVideoPlayerConstant.FW_VIDEO_COMPLETE_ACTION_ADVANCE_TO_NEXT
|
|
96
114
|
// VideoPlayerProperties.autoPlayOnComplete = config?.videoCompleteAction != FWVideoPlayerConstant.FW_VIDEO_COMPLETE_ACTION_LOOP
|
|
@@ -11,22 +11,7 @@ import FireworkVideo
|
|
|
11
11
|
|
|
12
12
|
@objc
|
|
13
13
|
public enum VideoFeedMode: Int {
|
|
14
|
-
case row,
|
|
15
|
-
|
|
16
|
-
fileprivate var videoFeedLayout: VideoFeedLayout {
|
|
17
|
-
switch self {
|
|
18
|
-
case .row:
|
|
19
|
-
return VideoFeedHorizontalLayout()
|
|
20
|
-
case .colume:
|
|
21
|
-
let layout = VideoFeedGridLayout()
|
|
22
|
-
layout.numberOfColumns = 1
|
|
23
|
-
return layout
|
|
24
|
-
case .grid:
|
|
25
|
-
let layout = VideoFeedGridLayout()
|
|
26
|
-
layout.numberOfColumns = 2
|
|
27
|
-
return layout
|
|
28
|
-
}
|
|
29
|
-
}
|
|
14
|
+
case row, column, grid
|
|
30
15
|
}
|
|
31
16
|
|
|
32
17
|
@objc
|
|
@@ -55,7 +40,8 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
|
|
|
55
40
|
guard let feedVC = feedVC else {
|
|
56
41
|
return
|
|
57
42
|
}
|
|
58
|
-
feedVC.viewConfiguration =
|
|
43
|
+
feedVC.viewConfiguration = convertToVideoFeedContentConfiguration()
|
|
44
|
+
feedVC.layout = videoFeedLayout
|
|
59
45
|
}
|
|
60
46
|
}
|
|
61
47
|
@objc public var playerViewConfig: VideoPlayerConfiguration? {
|
|
@@ -63,7 +49,7 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
|
|
|
63
49
|
guard let feedVC = feedVC else {
|
|
64
50
|
return
|
|
65
51
|
}
|
|
66
|
-
feedVC.viewConfiguration =
|
|
52
|
+
feedVC.viewConfiguration = convertToVideoFeedContentConfiguration()
|
|
67
53
|
}
|
|
68
54
|
}
|
|
69
55
|
@objc var onVideoFeedLoadFinished: RCTBubblingEventBlock?
|
|
@@ -87,6 +73,60 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
|
|
|
87
73
|
return .dynamicContent(channelID: channel, parameters: parameters ?? [:])
|
|
88
74
|
}
|
|
89
75
|
}
|
|
76
|
+
|
|
77
|
+
private var videoFeedLayout: VideoFeedLayout {
|
|
78
|
+
var resultLayout: VideoFeedLayout?
|
|
79
|
+
switch mode {
|
|
80
|
+
case .row:
|
|
81
|
+
let layout = VideoFeedHorizontalLayout()
|
|
82
|
+
resultLayout = layout
|
|
83
|
+
break
|
|
84
|
+
case .column:
|
|
85
|
+
let layout = VideoFeedGridLayout()
|
|
86
|
+
layout.numberOfColumns = 1
|
|
87
|
+
resultLayout = layout
|
|
88
|
+
break
|
|
89
|
+
case .grid:
|
|
90
|
+
let layout = VideoFeedGridLayout()
|
|
91
|
+
if let gridColumns = feedViewConfig?.gridColumns,
|
|
92
|
+
gridColumns > 0 {
|
|
93
|
+
layout.numberOfColumns = gridColumns
|
|
94
|
+
} else {
|
|
95
|
+
layout.numberOfColumns = 2
|
|
96
|
+
}
|
|
97
|
+
resultLayout = layout
|
|
98
|
+
break
|
|
99
|
+
}
|
|
100
|
+
if let config = feedViewConfig {
|
|
101
|
+
if let aspectRatio = config.aspectRatio {
|
|
102
|
+
if let horizontalLayout = resultLayout as? VideoFeedHorizontalLayout {
|
|
103
|
+
horizontalLayout.itemWidthRatio = aspectRatio
|
|
104
|
+
} else if let gridLayout = resultLayout as? VideoFeedGridLayout {
|
|
105
|
+
gridLayout.itemWidthRatio = aspectRatio
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if let contentPadding = config.contentPadding {
|
|
109
|
+
if let top = contentPadding.top {
|
|
110
|
+
resultLayout?.contentInsets.top = top
|
|
111
|
+
}
|
|
112
|
+
if let right = contentPadding.right {
|
|
113
|
+
resultLayout?.contentInsets.right = right
|
|
114
|
+
}
|
|
115
|
+
if let bottom = contentPadding.bottom {
|
|
116
|
+
resultLayout?.contentInsets.bottom = bottom
|
|
117
|
+
}
|
|
118
|
+
if let left = contentPadding.left {
|
|
119
|
+
resultLayout?.contentInsets.left = left
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if let itemSpacing = config.itemSpacing {
|
|
124
|
+
resultLayout?.itemSpacing = itemSpacing
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return resultLayout ?? VideoFeedHorizontalLayout()
|
|
129
|
+
}
|
|
90
130
|
|
|
91
131
|
public override func layoutSubviews() {
|
|
92
132
|
super.layoutSubviews()
|
|
@@ -103,11 +143,23 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
|
|
|
103
143
|
}
|
|
104
144
|
|
|
105
145
|
let feedVC = VideoFeedViewController(
|
|
106
|
-
layout:
|
|
146
|
+
layout: videoFeedLayout,
|
|
107
147
|
source: source
|
|
108
148
|
)
|
|
109
|
-
|
|
110
|
-
|
|
149
|
+
|
|
150
|
+
var viewConfiguration = convertToVideoFeedContentConfiguration()
|
|
151
|
+
if viewConfiguration.itemView.autoplay.isEnabled {
|
|
152
|
+
viewConfiguration.itemView.autoplay.isEnabled = false
|
|
153
|
+
feedVC.viewConfiguration = viewConfiguration
|
|
154
|
+
DispatchQueue.main.async {
|
|
155
|
+
if feedVC.viewConfiguration == viewConfiguration {
|
|
156
|
+
viewConfiguration.itemView.autoplay.isEnabled = true
|
|
157
|
+
feedVC.viewConfiguration = viewConfiguration
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
feedVC.viewConfiguration = viewConfiguration
|
|
162
|
+
}
|
|
111
163
|
feedVC.delegate = self
|
|
112
164
|
self.feedVC = feedVC
|
|
113
165
|
|
|
@@ -157,14 +209,14 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
|
|
|
157
209
|
}
|
|
158
210
|
|
|
159
211
|
extension VideoFeed {
|
|
160
|
-
private func
|
|
212
|
+
private func convertToVideoFeedContentConfiguration() -> VideoFeedContentConfiguration {
|
|
161
213
|
var videoConfig = VideoFeedContentConfiguration()
|
|
162
214
|
//set default value so that behavior will the same with Android
|
|
163
215
|
videoConfig.itemView.title.isHidden = false
|
|
164
216
|
videoConfig.itemView.titleLayoutConfiguration.titlePosition = .nested
|
|
165
217
|
|
|
166
|
-
let vfcConfig = VideoFeed.
|
|
167
|
-
let vpcConfig = VideoFeed.
|
|
218
|
+
let vfcConfig = VideoFeed.convertToVideoFeedItemContentConfiguration(feedViewConfig)
|
|
219
|
+
let vpcConfig = VideoFeed.convertToVideoPlayerContentConfiguration(playerViewConfig)
|
|
168
220
|
if let vfcConfig = vfcConfig {
|
|
169
221
|
videoConfig.itemView = vfcConfig
|
|
170
222
|
}
|
|
@@ -188,7 +240,7 @@ extension VideoFeed {
|
|
|
188
240
|
return videoConfig
|
|
189
241
|
}
|
|
190
242
|
|
|
191
|
-
private static func
|
|
243
|
+
private static func convertToVideoFeedItemContentConfiguration(_ config: VideoFeedConfiguration?) -> VideoFeedItemContentConfiguration? {
|
|
192
244
|
guard let config = config else {
|
|
193
245
|
return nil
|
|
194
246
|
}
|
|
@@ -199,7 +251,7 @@ extension VideoFeed {
|
|
|
199
251
|
vfcConfig.titleLayoutConfiguration.titlePosition = .nested
|
|
200
252
|
|
|
201
253
|
if let cornerRadius = config.cornerRadius {
|
|
202
|
-
vfcConfig.cornerRadius =
|
|
254
|
+
vfcConfig.cornerRadius = cornerRadius
|
|
203
255
|
}
|
|
204
256
|
if let title = config.title {
|
|
205
257
|
if let hidden = title.hidden {
|
|
@@ -209,7 +261,7 @@ extension VideoFeed {
|
|
|
209
261
|
vfcConfig.title.textColor = textcolor.uicolor()
|
|
210
262
|
}
|
|
211
263
|
if let fontSize = title.fontSize {
|
|
212
|
-
vfcConfig.title.font = UIFont.systemFont(ofSize:
|
|
264
|
+
vfcConfig.title.font = UIFont.systemFont(ofSize: fontSize)
|
|
213
265
|
}
|
|
214
266
|
}
|
|
215
267
|
if let playIcon = config.playIcon {
|
|
@@ -217,7 +269,7 @@ extension VideoFeed {
|
|
|
217
269
|
vfcConfig.playIcon.isHidden = hidden
|
|
218
270
|
}
|
|
219
271
|
if let iconWidth = playIcon.iconWidth {
|
|
220
|
-
vfcConfig.playIcon.iconWidth =
|
|
272
|
+
vfcConfig.playIcon.iconWidth = iconWidth
|
|
221
273
|
}
|
|
222
274
|
}
|
|
223
275
|
if let position = config.titlePosition {
|
|
@@ -234,11 +286,15 @@ extension VideoFeed {
|
|
|
234
286
|
if let showAdBadge = config.showAdBadge {
|
|
235
287
|
vfcConfig.sponsored.isHidden = !showAdBadge
|
|
236
288
|
}
|
|
289
|
+
|
|
290
|
+
if let enableAutoplay = config.enableAutoplay {
|
|
291
|
+
vfcConfig.autoplay.isEnabled = enableAutoplay
|
|
292
|
+
}
|
|
237
293
|
|
|
238
294
|
return vfcConfig
|
|
239
295
|
}
|
|
240
296
|
|
|
241
|
-
private static func
|
|
297
|
+
private static func convertToVideoPlayerContentConfiguration(_ config: VideoPlayerConfiguration?) -> VideoPlayerContentConfiguration? {
|
|
242
298
|
guard let config = config else {
|
|
243
299
|
return nil
|
|
244
300
|
}
|
|
@@ -265,13 +321,13 @@ extension VideoFeed {
|
|
|
265
321
|
}
|
|
266
322
|
if let ctaButtonStyle = config.ctaButtonStyle {
|
|
267
323
|
if let backgroundColor = ctaButtonStyle.backgroundColor {
|
|
268
|
-
vpcConfig.ctaButton.backgroundColor = backgroundColor.uicolor()
|
|
324
|
+
vpcConfig.ctaButton.contentConfiguration.backgroundColor = backgroundColor.uicolor()
|
|
269
325
|
}
|
|
270
326
|
if let textcolor = ctaButtonStyle.textColor {
|
|
271
|
-
vpcConfig.ctaButton.textColor = textcolor.uicolor()
|
|
327
|
+
vpcConfig.ctaButton.contentConfiguration.textColor = textcolor.uicolor()
|
|
272
328
|
}
|
|
273
329
|
if let fontSize = ctaButtonStyle.fontSize {
|
|
274
|
-
vpcConfig.ctaButton.font = UIFont.systemFont(ofSize:
|
|
330
|
+
vpcConfig.ctaButton.contentConfiguration.font = UIFont.systemFont(ofSize: fontSize)
|
|
275
331
|
}
|
|
276
332
|
}
|
|
277
333
|
if let showPlaybackButton = config.showPlaybackButton {
|
|
@@ -279,9 +335,13 @@ extension VideoFeed {
|
|
|
279
335
|
}
|
|
280
336
|
if let showMuteButton = config.showMuteButton {
|
|
281
337
|
vpcConfig.muteButton.isHidden = !showMuteButton
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
338
|
+
}
|
|
339
|
+
if let launchBehavior = config.launchBehavior {
|
|
340
|
+
vpcConfig.onFirstLaunch = launchBehavior.behavior()
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if let showBranding = config.showBranding {
|
|
344
|
+
vpcConfig.videoDetail.fireworkAttribution.isHidden = !showBranding
|
|
285
345
|
}
|
|
286
346
|
|
|
287
347
|
return vpcConfig
|
|
@@ -10,22 +10,34 @@ import Foundation
|
|
|
10
10
|
@objc
|
|
11
11
|
public class VideoFeedConfiguration: NSObject, Codable {
|
|
12
12
|
var backgroundColor: String?
|
|
13
|
-
var cornerRadius:
|
|
13
|
+
var cornerRadius: Double?
|
|
14
14
|
var title: VideoFeedTitleConfiguration?
|
|
15
15
|
var titlePosition: VideoFeedTitlePosition?
|
|
16
16
|
var playIcon: VideoFeedPlayIconConfiguration?
|
|
17
17
|
var showSponsored: Bool?
|
|
18
18
|
var showAdBadge: Bool?
|
|
19
|
+
var aspectRatio: Double?
|
|
20
|
+
var contentPadding: VideoFeedContentPadding?;
|
|
21
|
+
var itemSpacing: Double?
|
|
22
|
+
var enableAutoplay: Bool?
|
|
23
|
+
var gridColumns: Int?
|
|
19
24
|
|
|
20
25
|
class VideoFeedTitleConfiguration: NSObject, Codable {
|
|
21
26
|
public var hidden: Bool?
|
|
22
27
|
public var textColor: String?
|
|
23
|
-
public var fontSize:
|
|
28
|
+
public var fontSize: Double?
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
class VideoFeedPlayIconConfiguration: NSObject, Codable {
|
|
27
32
|
public var hidden: Bool?
|
|
28
|
-
public var iconWidth:
|
|
33
|
+
public var iconWidth: Double?
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class VideoFeedContentPadding: NSObject, Codable {
|
|
37
|
+
public var top: Double?
|
|
38
|
+
public var right: Double?
|
|
39
|
+
public var bottom: Double?
|
|
40
|
+
public var left: Double?
|
|
29
41
|
}
|
|
30
42
|
|
|
31
43
|
enum VideoFeedTitlePosition: String, Codable {
|
|
@@ -16,7 +16,8 @@ public class VideoPlayerConfiguration: NSObject, Codable {
|
|
|
16
16
|
var showPlaybackButton: Bool?
|
|
17
17
|
var showMuteButton: Bool?
|
|
18
18
|
var launchBehavior: VideoLaunchBehavior?
|
|
19
|
-
|
|
19
|
+
var showBranding: Bool?
|
|
20
|
+
|
|
20
21
|
public enum VideoPlayerStyle: String, Codable {
|
|
21
22
|
case full, fit
|
|
22
23
|
}
|
|
@@ -28,7 +29,7 @@ public class VideoPlayerConfiguration: NSObject, Codable {
|
|
|
28
29
|
public class VideoPlayerCTAStyle: NSObject, Codable {
|
|
29
30
|
var backgroundColor: String?
|
|
30
31
|
var textColor: String?
|
|
31
|
-
var fontSize:
|
|
32
|
+
var fontSize: Double?
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
public enum VideoLaunchBehavior: String, Codable {
|
|
@@ -16,14 +16,34 @@ extension RCTConvert {
|
|
|
16
16
|
if let style = videoPlayerStyle(config["playerStyle"] as? String) {
|
|
17
17
|
finalConfig.playerStyle = style
|
|
18
18
|
}
|
|
19
|
+
|
|
19
20
|
if let action = videoCompleteAction(config["videoCompleteAction"] as? String) {
|
|
20
21
|
finalConfig.videoCompleteAction = action
|
|
21
22
|
}
|
|
23
|
+
|
|
22
24
|
if let showShareButton = config["showShareButton"] as? Bool {
|
|
23
|
-
finalConfig.shareButton.isHidden = showShareButton
|
|
25
|
+
finalConfig.shareButton.isHidden = !showShareButton
|
|
24
26
|
}
|
|
27
|
+
|
|
25
28
|
if let ctaStyle = ctaButtonStyle(config["ctaButtonStyle"] as? Dictionary) {
|
|
26
|
-
finalConfig.ctaButton = ctaStyle
|
|
29
|
+
finalConfig.ctaButton.contentConfiguration = ctaStyle
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if let showPlaybackButton = config["showPlaybackButton"] as? Bool {
|
|
33
|
+
finalConfig.playbackButton.isHidden = !showPlaybackButton
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if let showMuteButton = config["showMuteButton"] as? Bool {
|
|
37
|
+
finalConfig.muteButton.isHidden = !showMuteButton
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if let launchBehaviorString = config["launchBehavior"] as? String,
|
|
41
|
+
let launchBehavior = VideoPlayerConfiguration.VideoLaunchBehavior(rawValue: launchBehaviorString) {
|
|
42
|
+
finalConfig.onFirstLaunch = launchBehavior.behavior()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if let showBranding = config["showBranding"] as? Bool {
|
|
46
|
+
finalConfig.videoDetail.fireworkAttribution.isHidden = !showBranding
|
|
27
47
|
}
|
|
28
48
|
|
|
29
49
|
return finalConfig
|
|
@@ -62,8 +82,8 @@ extension RCTConvert {
|
|
|
62
82
|
if let textColor = rStyle["textColor"] as? String {
|
|
63
83
|
btnContentConfig.textColor = textColor.uicolor()
|
|
64
84
|
}
|
|
65
|
-
if let fontSize = rStyle["fontSize"] as?
|
|
66
|
-
btnContentConfig.font = UIFont.systemFont(ofSize:
|
|
85
|
+
if let fontSize = rStyle["fontSize"] as? Double {
|
|
86
|
+
btnContentConfig.font = UIFont.systemFont(ofSize: fontSize)
|
|
67
87
|
}
|
|
68
88
|
|
|
69
89
|
return btnContentConfig
|