react-native-firework-sdk 2.17.0 → 2.17.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 (112) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/gradle.properties +1 -1
  3. package/android/src/main/java/com/fireworksdk/bridge/components/storyblock/StoryBlockContainer.kt +13 -0
  4. package/android/src/main/java/com/fireworksdk/bridge/components/storyblock/StoryBlockContainerView.kt +103 -0
  5. package/android/src/main/java/com/fireworksdk/bridge/components/storyblock/StoryBlockFragment.kt +9 -0
  6. package/android/src/main/java/com/fireworksdk/bridge/components/storyblock/StoryBlockFrameLayout.kt +5 -4
  7. package/android/src/main/java/com/fireworksdk/bridge/models/FWChatConfigModelDeserializer.kt +21 -0
  8. package/android/src/main/java/com/fireworksdk/bridge/models/FWControlsInsetModel.kt +3 -0
  9. package/android/src/main/java/com/fireworksdk/bridge/models/FWControlsInsetModelDeserializer.kt +15 -0
  10. package/android/src/main/java/com/fireworksdk/bridge/models/FWControlsInsetModelSerializer.kt +17 -0
  11. package/android/src/main/java/com/fireworksdk/bridge/models/FWLiveStreamEventDetailsModel.kt +2 -1
  12. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfiguration.kt +28 -1
  13. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfigurationDeserializer.kt +72 -1
  14. package/android/src/main/java/com/fireworksdk/bridge/models/FWShoppingCustomCta.kt +3 -3
  15. package/android/src/main/java/com/fireworksdk/bridge/models/FWTextShadowModelDeserializer.kt +30 -0
  16. package/android/src/main/java/com/fireworksdk/bridge/models/FWTrackPurchaseModel.kt +3 -0
  17. package/android/src/main/java/com/fireworksdk/bridge/models/FWTrackPurchaseModelDeserializer.kt +14 -0
  18. package/android/src/main/java/com/fireworksdk/bridge/models/FWTrackPurchaseModelSerializer.kt +7 -1
  19. package/android/src/main/java/com/fireworksdk/bridge/models/FWTrackPurchaseProduct.kt +7 -0
  20. package/android/src/main/java/com/fireworksdk/bridge/models/FWTrackPurchaseProductDeserializer.kt +36 -0
  21. package/android/src/main/java/com/fireworksdk/bridge/models/FWTrackPurchaseProductSerializer.kt +29 -0
  22. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModel.kt +17 -1
  23. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelDeserializer.kt +16 -1
  24. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelSerializer.kt +33 -1
  25. package/android/src/main/java/com/fireworksdk/bridge/models/enums/FWEventName.kt +5 -1
  26. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +15 -5
  27. package/android/src/main/java/com/fireworksdk/bridge/utils/FWColorUtil.kt +15 -0
  28. package/android/src/main/java/com/fireworksdk/bridge/utils/FWCommonUtil.kt +2 -2
  29. package/android/src/main/java/com/fireworksdk/bridge/utils/FWConfigUtil.kt +59 -1
  30. package/android/src/main/java/com/fireworksdk/bridge/utils/FWGlobalDataUtil.kt +2 -0
  31. package/android/src/main/java/com/fireworksdk/bridge/utils/FWModelUtils.kt +32 -0
  32. package/ios/Components/StoryBlock.swift +23 -0
  33. package/ios/Components/StoryBlockConfiguration.swift +4 -0
  34. package/ios/Components/VideoFeed.swift +12 -0
  35. package/ios/Components/VideoPlayerConfiguration.swift +16 -0
  36. package/ios/Models/Common/ControlsInset.swift +12 -0
  37. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.m +1 -0
  38. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +10 -95
  39. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +5 -0
  40. package/ios/Modules/FireworkSDKModule/TrackPurchaseParameters.swift +18 -0
  41. package/lib/commonjs/FWNavigator.js +18 -0
  42. package/lib/commonjs/FWNavigator.js.map +1 -1
  43. package/lib/commonjs/components/StoryBlock.js +8 -0
  44. package/lib/commonjs/components/StoryBlock.js.map +1 -1
  45. package/lib/commonjs/components/VideoFeed.js +6 -0
  46. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  47. package/lib/commonjs/index.js.map +1 -1
  48. package/lib/commonjs/models/ControlsInset.js +2 -0
  49. package/lib/commonjs/models/ControlsInset.js.map +1 -0
  50. package/lib/commonjs/models/StatusBarStyle.js +2 -0
  51. package/lib/commonjs/models/StatusBarStyle.js.map +1 -0
  52. package/lib/commonjs/modules/FWNavigatorModule.js.map +1 -1
  53. package/lib/module/FWNavigator.js +18 -0
  54. package/lib/module/FWNavigator.js.map +1 -1
  55. package/lib/module/components/StoryBlock.js +8 -0
  56. package/lib/module/components/StoryBlock.js.map +1 -1
  57. package/lib/module/components/VideoFeed.js +6 -0
  58. package/lib/module/components/VideoFeed.js.map +1 -1
  59. package/lib/module/index.js.map +1 -1
  60. package/lib/module/models/ControlsInset.js +2 -0
  61. package/lib/module/models/ControlsInset.js.map +1 -0
  62. package/lib/module/models/StatusBarStyle.js +2 -0
  63. package/lib/module/models/StatusBarStyle.js.map +1 -0
  64. package/lib/module/modules/FWNavigatorModule.js.map +1 -1
  65. package/lib/typescript/commonjs/src/FWNavigator.d.ts +7 -0
  66. package/lib/typescript/commonjs/src/FWNavigator.d.ts.map +1 -1
  67. package/lib/typescript/commonjs/src/components/StoryBlock.d.ts.map +1 -1
  68. package/lib/typescript/commonjs/src/components/VideoFeed.d.ts.map +1 -1
  69. package/lib/typescript/commonjs/src/index.d.ts +4 -1
  70. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  71. package/lib/typescript/commonjs/src/models/ControlsInset.d.ts +4 -0
  72. package/lib/typescript/commonjs/src/models/ControlsInset.d.ts.map +1 -0
  73. package/lib/typescript/commonjs/src/models/StatusBarStyle.d.ts +2 -0
  74. package/lib/typescript/commonjs/src/models/StatusBarStyle.d.ts.map +1 -0
  75. package/lib/typescript/commonjs/src/models/StoryBlockConfiguration.d.ts +22 -1
  76. package/lib/typescript/commonjs/src/models/StoryBlockConfiguration.d.ts.map +1 -1
  77. package/lib/typescript/commonjs/src/models/TrackPurchaseParameters.d.ts +26 -0
  78. package/lib/typescript/commonjs/src/models/TrackPurchaseParameters.d.ts.map +1 -1
  79. package/lib/typescript/commonjs/src/models/VideoPlayerConfiguration.d.ts +13 -0
  80. package/lib/typescript/commonjs/src/models/VideoPlayerConfiguration.d.ts.map +1 -1
  81. package/lib/typescript/commonjs/src/modules/FWNavigatorModule.d.ts +1 -0
  82. package/lib/typescript/commonjs/src/modules/FWNavigatorModule.d.ts.map +1 -1
  83. package/lib/typescript/module/src/FWNavigator.d.ts +7 -0
  84. package/lib/typescript/module/src/FWNavigator.d.ts.map +1 -1
  85. package/lib/typescript/module/src/components/StoryBlock.d.ts.map +1 -1
  86. package/lib/typescript/module/src/components/VideoFeed.d.ts.map +1 -1
  87. package/lib/typescript/module/src/index.d.ts +4 -1
  88. package/lib/typescript/module/src/index.d.ts.map +1 -1
  89. package/lib/typescript/module/src/models/ControlsInset.d.ts +4 -0
  90. package/lib/typescript/module/src/models/ControlsInset.d.ts.map +1 -0
  91. package/lib/typescript/module/src/models/StatusBarStyle.d.ts +2 -0
  92. package/lib/typescript/module/src/models/StatusBarStyle.d.ts.map +1 -0
  93. package/lib/typescript/module/src/models/StoryBlockConfiguration.d.ts +22 -1
  94. package/lib/typescript/module/src/models/StoryBlockConfiguration.d.ts.map +1 -1
  95. package/lib/typescript/module/src/models/TrackPurchaseParameters.d.ts +26 -0
  96. package/lib/typescript/module/src/models/TrackPurchaseParameters.d.ts.map +1 -1
  97. package/lib/typescript/module/src/models/VideoPlayerConfiguration.d.ts +13 -0
  98. package/lib/typescript/module/src/models/VideoPlayerConfiguration.d.ts.map +1 -1
  99. package/lib/typescript/module/src/modules/FWNavigatorModule.d.ts +1 -0
  100. package/lib/typescript/module/src/modules/FWNavigatorModule.d.ts.map +1 -1
  101. package/package.json +1 -1
  102. package/react_native_firework_sdk.podspec +1 -1
  103. package/src/FWNavigator.ts +18 -0
  104. package/src/components/StoryBlock.tsx +11 -0
  105. package/src/components/VideoFeed.tsx +7 -0
  106. package/src/index.tsx +6 -0
  107. package/src/models/ControlsInset.ts +3 -0
  108. package/src/models/StatusBarStyle.ts +1 -0
  109. package/src/models/StoryBlockConfiguration.ts +26 -1
  110. package/src/models/TrackPurchaseParameters.ts +29 -0
  111. package/src/models/VideoPlayerConfiguration.ts +16 -0
  112. package/src/modules/FWNavigatorModule.ts +1 -0
@@ -96,7 +96,7 @@ repositories {
96
96
  google()
97
97
 
98
98
  maven {
99
- setUrl("https://s01.oss.sonatype.org/content/repositories/snapshots/")
99
+ setUrl("https://central.sonatype.com/repository/maven-snapshots/")
100
100
  mavenContent {
101
101
  snapshotsOnly()
102
102
  }
@@ -6,4 +6,4 @@ FireworkSDK_targetSdkVersion=33
6
6
  FireworkSDK_compileSdkVersion=33
7
7
  FireworkSDK_kotlinVersion=1.8.22
8
8
  FireworkSDK_fwPlayerLaunchMode=singleTask
9
- FireworkSDK_fwNativeVersion=6.24.0
9
+ FireworkSDK_fwNativeVersion=6.24.1
@@ -0,0 +1,13 @@
1
+ package com.fireworksdk.bridge.components.storyblock
2
+
3
+ import com.fireworksdk.bridge.models.FWVideoFeedPropsModel
4
+
5
+ /**
6
+ * Interface for StoryBlock containers to provide a common API
7
+ * for both FrameLayout and FragmentContainerView implementations
8
+ */
9
+ interface StoryBlockContainer {
10
+ var storyBlockFragment: StoryBlockFragment?
11
+ var videoFeedPropsModel: FWVideoFeedPropsModel
12
+ fun destroy()
13
+ }
@@ -0,0 +1,103 @@
1
+ package com.fireworksdk.bridge.components.storyblock
2
+
3
+ import android.content.Context
4
+ import android.util.AttributeSet
5
+ import android.widget.FrameLayout
6
+ import androidx.fragment.app.FragmentActivity
7
+ import com.fireworksdk.bridge.models.FWVideoFeedPropsModel
8
+ import com.fireworksdk.bridge.utils.FWLogUtils
9
+
10
+ /**
11
+ * StoryBlockContainerView provides safe Fragment management with automatic lifecycle handling.
12
+ * This eliminates the need for manual Fragment transaction management and reduces crash risks.
13
+ */
14
+ class StoryBlockContainerView(
15
+ context: Context,
16
+ attrs: AttributeSet?
17
+ ) : FrameLayout(context, attrs), StoryBlockContainer {
18
+
19
+ override var storyBlockFragment: StoryBlockFragment? = null
20
+ override var videoFeedPropsModel: FWVideoFeedPropsModel = FWVideoFeedPropsModel()
21
+
22
+ private var isFragmentAttached = false
23
+ private var pendingFragment: StoryBlockFragment? = null
24
+
25
+ constructor(context: Context) : this(context, null)
26
+
27
+ override fun onAttachedToWindow() {
28
+ super.onAttachedToWindow()
29
+ // Try to attach pending fragment when view is attached
30
+ pendingFragment?.let { fragment ->
31
+ attachFragmentSafely(fragment)
32
+ pendingFragment = null
33
+ }
34
+ }
35
+
36
+ override fun onDetachedFromWindow() {
37
+ super.onDetachedFromWindow()
38
+ // Fragment will be automatically detached by FragmentManager
39
+ isFragmentAttached = false
40
+ }
41
+
42
+ /**
43
+ * Safely attach fragment to this container
44
+ */
45
+ fun attachFragmentSafely(fragment: StoryBlockFragment) {
46
+ if (isFragmentAttached || fragment.isAdded) {
47
+ return
48
+ }
49
+
50
+ val activity = context as? FragmentActivity ?: run {
51
+ FWLogUtils.e { "Context is not FragmentActivity, cannot attach fragment" }
52
+ return
53
+ }
54
+
55
+ if (activity.isFinishing || activity.isDestroyed) {
56
+ FWLogUtils.w { "Activity is finishing or destroyed, cannot attach fragment" }
57
+ return
58
+ }
59
+
60
+ try {
61
+ val fragmentManager = activity.supportFragmentManager
62
+ fragmentManager.beginTransaction()
63
+ .replace(id, fragment, id.toString())
64
+ .commitAllowingStateLoss()
65
+
66
+ // Delay state update to ensure transaction is committed
67
+ post {
68
+ isFragmentAttached = fragment.isAdded
69
+ if (isFragmentAttached) {
70
+ FWLogUtils.d { "Fragment attached successfully to container $id" }
71
+ } else {
72
+ FWLogUtils.w { "Fragment attachment may have failed, fragment.isAdded = false" }
73
+ }
74
+ }
75
+ } catch (e: Exception) {
76
+ FWLogUtils.e { "Failed to attach fragment: ${e.message}" }
77
+ // Store fragment for later attachment
78
+ pendingFragment = fragment
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Set fragment to be attached when container is ready
84
+ */
85
+ fun setFragment(fragment: StoryBlockFragment) {
86
+ storyBlockFragment = fragment
87
+ if (isAttachedToWindow) {
88
+ attachFragmentSafely(fragment)
89
+ } else {
90
+ pendingFragment = fragment
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Clean up resources when the view is destroyed
96
+ */
97
+ override fun destroy() {
98
+ // Fragment will be automatically cleaned up by FragmentManager
99
+ isFragmentAttached = false
100
+ pendingFragment = null
101
+ storyBlockFragment = null
102
+ }
103
+ }
@@ -109,8 +109,17 @@ class StoryBlockFragment : FWBaseFragment() {
109
109
 
110
110
 
111
111
  override fun onDestroyView() {
112
+ // clean resource
112
113
  fwStoryBlockView?.destroy()
114
+ fwStoryBlockView = null
115
+ loaderContainer = null
113
116
  _binding = null
117
+
118
+ // clean listener
119
+ feedLoadListener = null
120
+ errorListener = null
121
+ shoppingOverlayStateListener = null
122
+ createViewCallback = null
114
123
  super.onDestroyView()
115
124
  }
116
125
 
@@ -5,15 +5,16 @@ import android.util.AttributeSet
5
5
  import android.widget.FrameLayout
6
6
  import com.fireworksdk.bridge.models.FWVideoFeedPropsModel
7
7
 
8
+ @Deprecated("Replace by StoryBlockContainerView")
8
9
  class StoryBlockFrameLayout(
9
10
  context: Context,
10
11
  attrs: AttributeSet?
11
- ) : FrameLayout(context, attrs) {
12
+ ) : FrameLayout(context, attrs), StoryBlockContainer {
12
13
 
13
- var storyBlockFragment: StoryBlockFragment? = null
14
- var videoFeedPropsModel: FWVideoFeedPropsModel = FWVideoFeedPropsModel()
14
+ override var storyBlockFragment: StoryBlockFragment? = null
15
+ override var videoFeedPropsModel: FWVideoFeedPropsModel = FWVideoFeedPropsModel()
15
16
 
16
17
  constructor(context: Context) : this(context, null)
17
18
 
18
- fun destroy() {}
19
+ override fun destroy() {}
19
20
  }
@@ -0,0 +1,21 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONObject
4
+
5
+ object FWChatConfigModelDeserializer {
6
+
7
+ private const val TEXT_COLOR_KEY = "textColor"
8
+ private const val TEXT_SHADOW_KEY = "textShadow"
9
+
10
+ fun deserialize(responseJson: JSONObject?): FWVideoPlayerConfigModel.FWChatStyleModel? {
11
+ responseJson ?: return null
12
+
13
+ val textColor = if (responseJson.has(TEXT_COLOR_KEY)) responseJson.optString(TEXT_COLOR_KEY) else null
14
+ val textShadow = FWTextShadowModelDeserializer.deserialize(responseJson.optJSONObject(TEXT_SHADOW_KEY))
15
+
16
+ return FWVideoPlayerConfigModel.FWChatStyleModel(
17
+ textColor = textColor,
18
+ textShadow = textShadow,
19
+ )
20
+ }
21
+ }
@@ -0,0 +1,3 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ data class FWControlsInsetModel(val top: Int? = null)
@@ -0,0 +1,15 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONObject
4
+
5
+ object FWControlsInsetModelDeserializer {
6
+ private const val TOP = "top"
7
+
8
+ fun deserialize(jsonObject: JSONObject?): FWControlsInsetModel? {
9
+ jsonObject ?: return null
10
+
11
+ return FWControlsInsetModel(
12
+ top = jsonObject.optInt(TOP, 0),
13
+ )
14
+ }
15
+ }
@@ -0,0 +1,17 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONObject
4
+
5
+ object FWControlsInsetModelSerializer {
6
+
7
+ private const val TOP = "top"
8
+
9
+ fun serialize(model: FWControlsInsetModel?): JSONObject? {
10
+ model ?: return null
11
+
12
+ val jsonObject = JSONObject()
13
+ model.top?.let { jsonObject.put(TOP, it) }
14
+
15
+ return jsonObject
16
+ }
17
+ }
@@ -4,5 +4,6 @@ data class FWLiveStreamEventDetailsModel(
4
4
  val id: String? = null,
5
5
  val feedId: String? = null,
6
6
  val videoType: String? = null,
7
- val liveStreamStatus: String? = null
7
+ val liveStreamStatus: String? = null,
8
+ val playbackDetails: FWVideoPlaybackDetails? = null,
8
9
  )
@@ -15,6 +15,7 @@ data class FWProductInfoViewConfiguration(
15
15
  val backgroundColor: String? = null,
16
16
  val textColor: String? = null,
17
17
  val fontSize: Int? = null,
18
+ val fontInfo: FWFontInfoModel? = null,
18
19
  )
19
20
 
20
21
  data class LinkButtonConfiguration(
@@ -24,12 +25,38 @@ data class FWProductInfoViewConfiguration(
24
25
  data class ProductCardConfiguration(
25
26
  val ctaButtonText: FWProductCardCtaButtonTextValue? = null,
26
27
  val theme: FWProductCardTheme? = null,
27
- val cornerRadius: Int? = null,
28
+ val cornerRadius: Double? = null,
28
29
  val priceConfiguration: ProductCardPriceConfiguration? = null,
29
30
  val isCtaButtonHidden: Boolean? = null,
31
+ val ctaButtonStyle: ProductCardCTAButtonStyle? = null,
32
+ val width: Double? = null,
33
+ val height: Double? = null,
34
+ val backgroundColor: String? = null,
35
+ val iconConfiguration: ProductCardIconConfiguration? = null,
36
+ val nameLabel: ProductCardLabelConfiguration? = null,
30
37
  )
31
38
 
32
39
  data class ProductCardPriceConfiguration(
33
40
  val isHidden: Boolean? = null,
41
+ val isPriceFirst: Boolean? = null,
42
+ val priceLabel: ProductCardLabelConfiguration? = null,
43
+ val originalPriceLabel: ProductCardLabelConfiguration? = null,
44
+ )
45
+
46
+ data class ProductCardCTAButtonStyle(
47
+ val textColor: String? = null,
48
+ val fontSize: Int? = null,
49
+ val fontInfo: FWFontInfoModel? = null,
50
+ )
51
+
52
+ data class ProductCardLabelConfiguration(
53
+ val textColor: String? = null,
54
+ val fontSize: Int? = null,
55
+ val numberOfLines: Int? = null,
56
+ val fontInfo: FWFontInfoModel? = null,
57
+ )
58
+
59
+ data class ProductCardIconConfiguration(
60
+ val cornerRadius: Double? = null,
34
61
  )
35
62
  }
@@ -15,6 +15,7 @@ object FWProductInfoViewConfigurationDeserializer {
15
15
  private const val BACKGROUND_COLOR_KEY = "backgroundColor"
16
16
  private const val TEXT_COLOR_KEY = "textColor"
17
17
  private const val FONT_SIZE_KEY = "fontSize"
18
+ private const val ANDROID_FONT_INFO_KEY = "androidFontInfo"
18
19
 
19
20
  private const val IS_HIDDEN_KEY = "isHidden"
20
21
 
@@ -23,6 +24,19 @@ object FWProductInfoViewConfigurationDeserializer {
23
24
  private const val CORNER_RADIUS_KEY = "cornerRadius"
24
25
  private const val PRICE_CONFIGURATION_KEY = "priceConfiguration"
25
26
  private const val IS_CTA_BUTTON_HIDDEN_KEY = "isCtaButtonHidden"
27
+ private const val CTA_BUTTON_STYLE_KEY = "ctaButtonStyle"
28
+ private const val WIDTH_KEY = "width"
29
+ private const val HEIGHT_KEY = "height"
30
+ private const val ICON_CONFIGURATION_KEY = "iconConfiguration"
31
+ private const val NAME_LABEL_KEY = "nameLabel"
32
+
33
+ // Price configuration keys
34
+ private const val IS_PRICE_FIRST_KEY = "isPriceFirst"
35
+ private const val PRICE_LABEL_KEY = "priceLabel"
36
+ private const val ORIGINAL_PRICE_LABEL_KEY = "originalPriceLabel"
37
+
38
+ // Label configuration keys
39
+ private const val NUMBER_OF_LINES_KEY = "numberOfLines"
26
40
 
27
41
  fun deserialize(responseJson: JSONObject?): FWProductInfoViewConfiguration? {
28
42
  responseJson ?: return null
@@ -45,12 +59,14 @@ object FWProductInfoViewConfigurationDeserializer {
45
59
  val backgroundColor = if (ctaButtonConfiguration.has(BACKGROUND_COLOR_KEY)) ctaButtonConfiguration.optString(BACKGROUND_COLOR_KEY) else null
46
60
  val textColor = if (ctaButtonConfiguration.has(TEXT_COLOR_KEY)) ctaButtonConfiguration.optString(TEXT_COLOR_KEY) else null
47
61
  val fontSize = if (ctaButtonConfiguration.has(FONT_SIZE_KEY)) ctaButtonConfiguration.optInt(FONT_SIZE_KEY) else null
62
+ val fontInfo = FWFontInfoModelDeserializer.deserialize(ctaButtonConfiguration.optJSONObject(ANDROID_FONT_INFO_KEY))
48
63
 
49
64
  return FWProductInfoViewConfiguration.CtaButtonConfiguration(
50
65
  text = FWCtaButtonTextValue.deserialize(textString),
51
66
  backgroundColor = backgroundColor,
52
67
  textColor = textColor,
53
68
  fontSize = fontSize,
69
+ fontInfo = fontInfo,
54
70
  )
55
71
  }
56
72
 
@@ -69,9 +85,15 @@ object FWProductInfoViewConfigurationDeserializer {
69
85
 
70
86
  val ctaButtonTextString = if (productCardConfigJson.has(CTA_BUTTON_TEXT_KEY)) productCardConfigJson.optString(CTA_BUTTON_TEXT_KEY) else null
71
87
  val themeString = if (productCardConfigJson.has(THEME_KEY)) productCardConfigJson.optString(THEME_KEY) else null
72
- val cornerRadius = if (productCardConfigJson.has(CORNER_RADIUS_KEY)) productCardConfigJson.optInt(CORNER_RADIUS_KEY) else null
88
+ val cornerRadius = if (productCardConfigJson.has(CORNER_RADIUS_KEY)) productCardConfigJson.optDouble(CORNER_RADIUS_KEY) else null
73
89
  val priceConfiguration = deserializeProductCardPriceConfiguration(productCardConfigJson.optJSONObject(PRICE_CONFIGURATION_KEY))
74
90
  val isCtaButtonHidden = if (productCardConfigJson.has(IS_CTA_BUTTON_HIDDEN_KEY)) productCardConfigJson.optBoolean(IS_CTA_BUTTON_HIDDEN_KEY) else null
91
+ val ctaButtonStyle = deserializeProductCardCTAButtonStyle(productCardConfigJson.optJSONObject(CTA_BUTTON_STYLE_KEY))
92
+ val width = if (productCardConfigJson.has(WIDTH_KEY)) productCardConfigJson.optDouble(WIDTH_KEY) else null
93
+ val height = if (productCardConfigJson.has(HEIGHT_KEY)) productCardConfigJson.optDouble(HEIGHT_KEY) else null
94
+ val backgroundColor = if (productCardConfigJson.has(BACKGROUND_COLOR_KEY)) productCardConfigJson.optString(BACKGROUND_COLOR_KEY) else null
95
+ val iconConfiguration = deserializeProductCardIconConfiguration(productCardConfigJson.optJSONObject(ICON_CONFIGURATION_KEY))
96
+ val nameLabel = deserializeProductCardLabelConfiguration(productCardConfigJson.optJSONObject(NAME_LABEL_KEY))
75
97
 
76
98
  return FWProductInfoViewConfiguration.ProductCardConfiguration(
77
99
  ctaButtonText = FWProductCardCtaButtonTextValue.deserialize(ctaButtonTextString),
@@ -79,15 +101,64 @@ object FWProductInfoViewConfigurationDeserializer {
79
101
  cornerRadius = cornerRadius,
80
102
  priceConfiguration = priceConfiguration,
81
103
  isCtaButtonHidden = isCtaButtonHidden,
104
+ ctaButtonStyle = ctaButtonStyle,
105
+ width = width,
106
+ height = height,
107
+ backgroundColor = backgroundColor,
108
+ iconConfiguration = iconConfiguration,
109
+ nameLabel = nameLabel,
82
110
  )
83
111
  }
84
112
 
85
113
  private fun deserializeProductCardPriceConfiguration(productCardPriceConfigurationJson: JSONObject?): FWProductInfoViewConfiguration.ProductCardPriceConfiguration {
86
114
  productCardPriceConfigurationJson ?: return FWProductInfoViewConfiguration.ProductCardPriceConfiguration()
87
115
  val isHidden = if (productCardPriceConfigurationJson.has(IS_HIDDEN_KEY)) productCardPriceConfigurationJson.optBoolean(IS_HIDDEN_KEY) else null
116
+ val isPriceFirst = if (productCardPriceConfigurationJson.has(IS_PRICE_FIRST_KEY)) productCardPriceConfigurationJson.optBoolean(IS_PRICE_FIRST_KEY) else null
117
+ val priceLabel = deserializeProductCardLabelConfiguration(productCardPriceConfigurationJson.optJSONObject(PRICE_LABEL_KEY))
118
+ val originalPriceLabel = deserializeProductCardLabelConfiguration(productCardPriceConfigurationJson.optJSONObject(ORIGINAL_PRICE_LABEL_KEY))
88
119
 
89
120
  return FWProductInfoViewConfiguration.ProductCardPriceConfiguration(
90
121
  isHidden = isHidden,
122
+ isPriceFirst = isPriceFirst,
123
+ priceLabel = priceLabel,
124
+ originalPriceLabel = originalPriceLabel,
125
+ )
126
+ }
127
+
128
+ private fun deserializeProductCardCTAButtonStyle(ctaButtonStyleJson: JSONObject?): FWProductInfoViewConfiguration.ProductCardCTAButtonStyle {
129
+ ctaButtonStyleJson ?: return FWProductInfoViewConfiguration.ProductCardCTAButtonStyle()
130
+ val textColor = if (ctaButtonStyleJson.has(TEXT_COLOR_KEY)) ctaButtonStyleJson.optString(TEXT_COLOR_KEY) else null
131
+ val fontSize = if (ctaButtonStyleJson.has(FONT_SIZE_KEY)) ctaButtonStyleJson.optInt(FONT_SIZE_KEY) else null
132
+ val fontInfo = FWFontInfoModelDeserializer.deserialize(ctaButtonStyleJson.optJSONObject(ANDROID_FONT_INFO_KEY))
133
+
134
+ return FWProductInfoViewConfiguration.ProductCardCTAButtonStyle(
135
+ textColor = textColor,
136
+ fontSize = fontSize,
137
+ fontInfo = fontInfo,
138
+ )
139
+ }
140
+
141
+ private fun deserializeProductCardLabelConfiguration(labelConfigJson: JSONObject?): FWProductInfoViewConfiguration.ProductCardLabelConfiguration {
142
+ labelConfigJson ?: return FWProductInfoViewConfiguration.ProductCardLabelConfiguration()
143
+ val textColor = if (labelConfigJson.has(TEXT_COLOR_KEY)) labelConfigJson.optString(TEXT_COLOR_KEY) else null
144
+ val fontSize = if (labelConfigJson.has(FONT_SIZE_KEY)) labelConfigJson.optInt(FONT_SIZE_KEY) else null
145
+ val numberOfLines = if (labelConfigJson.has(NUMBER_OF_LINES_KEY)) labelConfigJson.optInt(NUMBER_OF_LINES_KEY) else null
146
+ val fontInfo = FWFontInfoModelDeserializer.deserialize(labelConfigJson.optJSONObject(ANDROID_FONT_INFO_KEY))
147
+
148
+ return FWProductInfoViewConfiguration.ProductCardLabelConfiguration(
149
+ textColor = textColor,
150
+ fontSize = fontSize,
151
+ numberOfLines = numberOfLines,
152
+ fontInfo = fontInfo,
153
+ )
154
+ }
155
+
156
+ private fun deserializeProductCardIconConfiguration(iconConfigJson: JSONObject?): FWProductInfoViewConfiguration.ProductCardIconConfiguration {
157
+ iconConfigJson ?: return FWProductInfoViewConfiguration.ProductCardIconConfiguration()
158
+ val cornerRadius = if (iconConfigJson.has(CORNER_RADIUS_KEY)) iconConfigJson.optDouble(CORNER_RADIUS_KEY) else null
159
+
160
+ return FWProductInfoViewConfiguration.ProductCardIconConfiguration(
161
+ cornerRadius = cornerRadius,
91
162
  )
92
163
  }
93
164
  }
@@ -1,7 +1,7 @@
1
1
  package com.fireworksdk.bridge.models
2
2
 
3
3
  data class FWShoppingCustomCta(
4
- val url: String,
5
- val titleKey: String,
6
- val title: String,
4
+ val url: String?,
5
+ val titleKey: String?,
6
+ val title: String?,
7
7
  )
@@ -0,0 +1,30 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONObject
4
+
5
+ object FWTextShadowModelDeserializer {
6
+
7
+ private const val OPACITY_KEY = "opacity"
8
+ private const val COLOR_KEY = "color"
9
+ private const val OFFSET_X_KEY = "offsetX"
10
+ private const val OFFSET_Y_KEY = "offsetY"
11
+ private const val RADIUS_KEY = "radius"
12
+
13
+ fun deserialize(responseJson: JSONObject?): FWVideoPlayerConfigModel.FWTextShadowModel? {
14
+ responseJson ?: return null
15
+
16
+ val opacity = if (responseJson.has(OPACITY_KEY)) responseJson.optDouble(OPACITY_KEY) else null
17
+ val color = if (responseJson.has(COLOR_KEY)) responseJson.optString(COLOR_KEY) else null
18
+ val offsetX = if (responseJson.has(OFFSET_X_KEY)) responseJson.optDouble(OFFSET_X_KEY) else null
19
+ val offsetY = if (responseJson.has(OFFSET_Y_KEY)) responseJson.optDouble(OFFSET_Y_KEY) else null
20
+ val radius = if (responseJson.has(RADIUS_KEY)) responseJson.optDouble(RADIUS_KEY) else null
21
+
22
+ return FWVideoPlayerConfigModel.FWTextShadowModel(
23
+ opacity = opacity,
24
+ color = color,
25
+ offsetX = offsetX,
26
+ offsetY = offsetY,
27
+ radius = radius,
28
+ )
29
+ }
30
+ }
@@ -6,4 +6,7 @@ data class FWTrackPurchaseModel(
6
6
  val currencyCode: String? = null,
7
7
  val countryCode: String? = null,
8
8
  val additionalInfo: Map<String, String>? = null,
9
+ val shippingPrice: Double? = null,
10
+ val subtotal: Double? = null,
11
+ val products: List<FWTrackPurchaseProduct>? = null,
9
12
  )
@@ -8,6 +8,9 @@ object FWTrackPurchaseModelDeserializer {
8
8
  private const val VALUE_KEY = "value"
9
9
  private const val CURRENCY_CODE_KEY = "currencyCode"
10
10
  private const val COUNTRY_KEY = "countryCode"
11
+ private const val SHIPPING_PRICE_KEY = "shippingPrice"
12
+ private const val SUB_TOTAL_KEY = "subtotal"
13
+ private const val PRODUCTS_KEY = "products"
11
14
  private const val ADDITIONAL_INFO_KEY = "additionalInfo"
12
15
 
13
16
 
@@ -17,7 +20,15 @@ object FWTrackPurchaseModelDeserializer {
17
20
  val value = if (responseJson.has(VALUE_KEY)) responseJson.optDouble(VALUE_KEY) else null
18
21
  val currencyCode = if (responseJson.has(CURRENCY_CODE_KEY)) responseJson.optString(CURRENCY_CODE_KEY) else null
19
22
  val countryCode = if (responseJson.has(COUNTRY_KEY)) responseJson.optString(COUNTRY_KEY) else null
23
+ val shoppingPrice = if (responseJson.has(SHIPPING_PRICE_KEY)) responseJson.optDouble(SHIPPING_PRICE_KEY) else null
24
+ val subtotal = if (responseJson.has(SUB_TOTAL_KEY)) responseJson.optDouble(SUB_TOTAL_KEY) else null
20
25
  val additionalInfoObject = if (responseJson.has(ADDITIONAL_INFO_KEY)) responseJson.optJSONObject(ADDITIONAL_INFO_KEY) else null
26
+ val productsObject = if (responseJson.has(PRODUCTS_KEY)) responseJson.optJSONArray(PRODUCTS_KEY) else null
27
+
28
+ var products: List<FWTrackPurchaseProduct>? = null
29
+ if (productsObject != null) {
30
+ products = FWTrackPurchaseProductDeserializer.deserializeArray(productsObject)
31
+ }
21
32
 
22
33
  var additionalInfo: Map<String, String>? = null
23
34
 
@@ -39,6 +50,9 @@ object FWTrackPurchaseModelDeserializer {
39
50
  currencyCode = currencyCode,
40
51
  countryCode = countryCode,
41
52
  additionalInfo = additionalInfo,
53
+ shippingPrice = shoppingPrice,
54
+ subtotal = subtotal,
55
+ products = products,
42
56
  )
43
57
  }
44
58
 
@@ -9,6 +9,9 @@ object FWTrackPurchaseModelSerializer {
9
9
  private const val CURRENCY_CODE_KEY = "currencyCode"
10
10
  private const val COUNTRY_KEY = "countryCode"
11
11
  private const val ADDITIONAL_INFO_KEY = "additionalInfo"
12
+ private const val SHIPPING_PRICE_KEY = "shippingPrice"
13
+ private const val SUB_TOTAL_KEY = "subtotal"
14
+ private const val PRODUCTS_KEY = "products"
12
15
 
13
16
  fun serialize(model: FWTrackPurchaseModel?): JSONObject? {
14
17
  model ?: return null
@@ -17,7 +20,10 @@ object FWTrackPurchaseModelSerializer {
17
20
  jsonObject.put(VALUE_KEY, model.value)
18
21
  jsonObject.put(CURRENCY_CODE_KEY, model.currencyCode)
19
22
  jsonObject.put(COUNTRY_KEY, model.countryCode)
20
-
23
+ jsonObject.put(SHIPPING_PRICE_KEY, model.shippingPrice)
24
+ jsonObject.put(SUB_TOTAL_KEY, model.subtotal)
25
+ jsonObject.put(PRODUCTS_KEY, FWTrackPurchaseProductSerializer.serializeArray(model.products))
26
+
21
27
  if (model.additionalInfo != null) {
22
28
  val additionalInfoJsonObject = JSONObject()
23
29
  val keys = model.additionalInfo.keys
@@ -0,0 +1,7 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ data class FWTrackPurchaseProduct(
4
+ val extProductId: String? = null,
5
+ val price: Double? = null,
6
+ val quantity: Int? = null,
7
+ )
@@ -0,0 +1,36 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONArray
4
+ import org.json.JSONObject
5
+
6
+ object FWTrackPurchaseProductDeserializer {
7
+
8
+ private const val EXT_PRODUCT_ID_KEY = "extProductId"
9
+ private const val PRICE_KEY = "price"
10
+ private const val QUANTITY_KEY = "quantity"
11
+
12
+ fun deserializeArray(productJsonArray: JSONArray?): List<FWTrackPurchaseProduct>? {
13
+ productJsonArray ?: return null
14
+ val list = mutableListOf<FWTrackPurchaseProduct>()
15
+ (0 until productJsonArray.length()).forEach {
16
+ val value = productJsonArray.getJSONObject(it)
17
+ val item = deserialize(value)
18
+ item?.let { product -> list.add(product) }
19
+ }
20
+ return list
21
+ }
22
+
23
+ fun deserialize(responseJson: JSONObject?): FWTrackPurchaseProduct? {
24
+ responseJson ?: return null
25
+
26
+ val extProductId = if (responseJson.has(EXT_PRODUCT_ID_KEY)) responseJson.optString(EXT_PRODUCT_ID_KEY) else null
27
+ val price = if (responseJson.has(PRICE_KEY)) responseJson.optDouble(PRICE_KEY) else null
28
+ val quantity = if (responseJson.has(QUANTITY_KEY)) responseJson.optInt(QUANTITY_KEY) else null
29
+
30
+ return FWTrackPurchaseProduct(
31
+ extProductId = extProductId,
32
+ price = price,
33
+ quantity = quantity,
34
+ )
35
+ }
36
+ }
@@ -0,0 +1,29 @@
1
+ package com.fireworksdk.bridge.models
2
+
3
+ import org.json.JSONArray
4
+ import org.json.JSONObject
5
+
6
+ object FWTrackPurchaseProductSerializer {
7
+
8
+ private const val EXT_PRODUCT_ID_KEY = "extProductId"
9
+ private const val PRICE_KEY = "price"
10
+ private const val QUANTITY_KEY = "quantity"
11
+
12
+ fun serializeArray(model: List<FWTrackPurchaseProduct>?): JSONArray? {
13
+ model ?: return null
14
+ val jsonArray = JSONArray()
15
+ for (item in model) {
16
+ jsonArray.put(serialize(item))
17
+ }
18
+ return jsonArray
19
+ }
20
+
21
+ fun serialize(model: FWTrackPurchaseProduct?): JSONObject? {
22
+ model ?: return null
23
+ val jsonObject = JSONObject()
24
+ jsonObject.put(EXT_PRODUCT_ID_KEY, model.extProductId)
25
+ jsonObject.put(PRICE_KEY, model.price)
26
+ jsonObject.put(QUANTITY_KEY, model.quantity)
27
+ return jsonObject
28
+ }
29
+ }
@@ -27,7 +27,10 @@ data class FWVideoPlayerConfigModel(
27
27
  val showFullScreenIcon: Boolean? = null,
28
28
  val enableAutoPlay: Boolean? = null,
29
29
  val enableAutoPause: Boolean? = null,
30
- val enableSmallSizeInCompact: Boolean? = null
30
+ val enableSmallSizeInCompact: Boolean? = null,
31
+ val chatStyle: FWChatStyleModel? = null,
32
+ val shouldExtendMediaOutsideSafeArea: Boolean? = null,
33
+ val additionalControlsInset: FWControlsInsetModel? = null,
31
34
  ) {
32
35
 
33
36
  data class FWCtaButtonStyleModel(
@@ -41,4 +44,17 @@ data class FWVideoPlayerConfigModel(
41
44
  val type: FWCtaDelayType? = null,
42
45
  val value: Double? = null,
43
46
  )
47
+
48
+ data class FWChatStyleModel(
49
+ val textColor: String? = null,
50
+ val textShadow: FWTextShadowModel? = null,
51
+ )
52
+
53
+ data class FWTextShadowModel(
54
+ val opacity: Double? = null,
55
+ val color: String? = null,
56
+ val offsetX: Double? = null,
57
+ val offsetY: Double? = null,
58
+ val radius: Double? = null,
59
+ )
44
60
  }