react-native-firework-sdk 1.7.1 → 2.0.0-beta.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 (141) hide show
  1. package/android/build.gradle +25 -43
  2. package/android/src/main/AndroidManifest.xml +4 -4
  3. package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/FWVideoFeed.kt +48 -194
  4. package/android/src/main/java/com/fireworksdk/bridge/constants/FWVideoPlayerConstant.kt +7 -0
  5. package/android/src/main/java/com/fireworksdk/bridge/models/FWAdBadgeConfigModel.kt +2 -0
  6. package/android/src/main/java/com/fireworksdk/bridge/models/FWAdBadgeConfigModelDeserializer.kt +24 -0
  7. package/android/src/main/java/com/fireworksdk/bridge/models/FWEventName.kt +1 -0
  8. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfiguration.kt +17 -0
  9. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfigurationDeserializer.kt +35 -0
  10. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedConfigModel.kt +12 -13
  11. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedConfigModelDeserializer.kt +67 -0
  12. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedItemDetailsModel.kt +1 -1
  13. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedPropsModel.kt +9 -10
  14. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedPropsModelDeserializer.kt +67 -0
  15. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlaybackDetails.kt +0 -3
  16. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModel.kt +19 -11
  17. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelDeserializer.kt +74 -0
  18. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoShoppingProduct.kt +17 -15
  19. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoShoppingProductDeserializer.kt +120 -0
  20. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWStoryBlockManager.kt +4 -130
  21. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWVideoFeedManager.kt +48 -100
  22. package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FWNavigatorInterface.kt +2 -0
  23. package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FWVideoShoppingInterface.kt +2 -1
  24. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWLiveStreamModule.kt +2 -50
  25. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWNavigatorModule.kt +17 -35
  26. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt +152 -108
  27. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +84 -130
  28. package/android/src/main/java/com/fireworksdk/bridge/reactnative/pages/FWContainerActivity.kt +1 -14
  29. package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/{FWDataUtils.kt → FWDataConvertUtils.kt} +1 -11
  30. package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +14 -5
  31. package/android/src/main/java/com/fireworksdk/bridge/utils/FWCommonUtil.kt +23 -0
  32. package/android/src/main/java/com/fireworksdk/bridge/utils/FWConfigUtil.kt +312 -0
  33. package/android/src/main/java/com/fireworksdk/bridge/utils/FWGlobalDataUtil.kt +14 -0
  34. package/android/src/main/java/com/fireworksdk/bridge/utils/FWLanguageUtil.kt +10 -14
  35. package/android/src/main/res/layout/fw_bridge_fragment_container.xml +2 -2
  36. package/android/src/main/res/values/colors.xml +2 -2
  37. package/android/src/main/res/values/styles.xml +0 -40
  38. package/ios/Components/StoryBlock.swift +1 -8
  39. package/ios/Components/StoryBlockManager.swift +4 -0
  40. package/ios/Components/VideoFeed.swift +9 -14
  41. package/ios/Components/VideoFeedConfiguration.swift +2 -0
  42. package/ios/Components/VideoFeedManager.m +2 -0
  43. package/ios/Components/VideoFeedManager.swift +4 -0
  44. package/ios/Components/VideoPlayerConfiguration.swift +1 -0
  45. package/ios/FireworkSdk.xcodeproj/project.pbxproj +12 -8
  46. package/ios/Models/Common/FontInfo.swift +57 -0
  47. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.m +2 -0
  48. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +295 -103
  49. package/ios/Modules/FireworkSDKModule/FireworkSDKModule+EventTracking.swift +0 -2
  50. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +12 -12
  51. package/ios/Modules/LiveStream/LiveStreamModule.swift +5 -3
  52. package/ios/Modules/Shopping/ProductInfoViewConfiguration.swift +7 -2
  53. package/ios/Modules/Shopping/ShoppingModule.m +1 -1
  54. package/ios/Modules/Shopping/ShoppingModule.swift +72 -63
  55. package/ios/Utils/FWSwizzleLoader.m +0 -1
  56. package/lib/commonjs/FWNavigator.js +14 -16
  57. package/lib/commonjs/FWNavigator.js.map +1 -1
  58. package/lib/commonjs/FireworkSDK.js +5 -34
  59. package/lib/commonjs/FireworkSDK.js.map +1 -1
  60. package/lib/commonjs/LiveStream.js +2 -2
  61. package/lib/commonjs/LiveStream.js.map +1 -1
  62. package/lib/commonjs/VideoShopping.js +59 -39
  63. package/lib/commonjs/VideoShopping.js.map +1 -1
  64. package/lib/commonjs/components/StoryBlock.js +3 -0
  65. package/lib/commonjs/components/StoryBlock.js.map +1 -1
  66. package/lib/commonjs/components/VideoFeed.js +14 -5
  67. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  68. package/lib/commonjs/index.js.map +1 -1
  69. package/lib/commonjs/models/FWEventName.js +1 -1
  70. package/lib/commonjs/models/FWEventName.js.map +1 -1
  71. package/lib/commonjs/models/IOSFontInfo.js +2 -0
  72. package/lib/commonjs/modules/FWNavigatorModule.js.map +1 -1
  73. package/lib/commonjs/modules/FireworkSDKModule.js.map +1 -1
  74. package/lib/commonjs/modules/ShoppingModule.js.map +1 -1
  75. package/lib/module/FWNavigator.js +15 -16
  76. package/lib/module/FWNavigator.js.map +1 -1
  77. package/lib/module/FireworkSDK.js +5 -32
  78. package/lib/module/FireworkSDK.js.map +1 -1
  79. package/lib/module/LiveStream.js +2 -2
  80. package/lib/module/LiveStream.js.map +1 -1
  81. package/lib/module/VideoShopping.js +58 -38
  82. package/lib/module/VideoShopping.js.map +1 -1
  83. package/lib/module/components/StoryBlock.js +3 -0
  84. package/lib/module/components/StoryBlock.js.map +1 -1
  85. package/lib/module/components/VideoFeed.js +14 -5
  86. package/lib/module/components/VideoFeed.js.map +1 -1
  87. package/lib/module/index.js.map +1 -1
  88. package/lib/module/models/FWEventName.js +1 -1
  89. package/lib/module/models/FWEventName.js.map +1 -1
  90. package/lib/module/models/IOSFontInfo.js +2 -0
  91. package/lib/module/modules/FWNavigatorModule.js.map +1 -1
  92. package/lib/module/modules/FireworkSDKModule.js.map +1 -1
  93. package/lib/module/modules/ShoppingModule.js.map +1 -1
  94. package/lib/typescript/FWNavigator.d.ts +11 -14
  95. package/lib/typescript/FireworkSDK.d.ts +5 -16
  96. package/lib/typescript/LiveStream.d.ts +2 -2
  97. package/lib/typescript/VideoShopping.d.ts +24 -19
  98. package/lib/typescript/components/StoryBlock.d.ts +4 -1
  99. package/lib/typescript/components/VideoFeed.d.ts +7 -3
  100. package/lib/typescript/index.d.ts +6 -5
  101. package/lib/typescript/models/FWEventName.d.ts +2 -2
  102. package/lib/typescript/models/FWEvents.d.ts +5 -6
  103. package/lib/typescript/models/IOSFontInfo.d.ts +19 -0
  104. package/lib/typescript/models/ProductInfoViewConfiguration.d.ts +23 -0
  105. package/lib/typescript/models/VideoFeedConfiguration.d.ts +22 -4
  106. package/lib/typescript/models/VideoPlayerConfiguration.d.ts +18 -2
  107. package/lib/typescript/modules/FWNavigatorModule.d.ts +2 -3
  108. package/lib/typescript/modules/FireworkSDKModule.d.ts +0 -2
  109. package/lib/typescript/modules/ShoppingModule.d.ts +2 -3
  110. package/package.json +1 -1
  111. package/react-native-firework-sdk.podspec +1 -1
  112. package/src/FWNavigator.ts +52 -0
  113. package/src/FireworkSDK.ts +5 -28
  114. package/src/LiveStream.ts +2 -2
  115. package/src/VideoShopping.ts +74 -54
  116. package/src/components/StoryBlock.tsx +4 -1
  117. package/src/components/VideoFeed.tsx +15 -5
  118. package/src/{index.tsx → index.ts} +17 -9
  119. package/src/models/FWEventName.ts +1 -1
  120. package/src/models/FWEvents.ts +6 -7
  121. package/src/models/IOSFontInfo.ts +29 -0
  122. package/src/models/ProductInfoViewConfiguration.ts +25 -0
  123. package/src/models/VideoFeedConfiguration.ts +23 -4
  124. package/src/models/VideoPlayerConfiguration.ts +19 -2
  125. package/src/modules/FWNavigatorModule.ts +2 -1
  126. package/src/modules/FireworkSDKModule.ts +0 -2
  127. package/src/modules/ShoppingModule.ts +2 -9
  128. package/android/src/main/java/com/fireworksdk/bridge/utils/FWGsonUtil.kt +0 -38
  129. package/android/src/main/java/com/fireworksdk/bridge/utils/FWVideoPlayerUtils.kt +0 -122
  130. package/android/src/main/res/layout/fw_bridge_fragment_playlistfeed.xml +0 -18
  131. package/android/src/main/res/layout/fw_bridge_fragment_shoppingcart.xml +0 -8
  132. package/android/src/main/res/layout/fw_bridge_fragment_videofeed.xml +0 -17
  133. package/ios/Utils/FWPiPManager.swift +0 -24
  134. package/ios/Utils/UIButton+FWSwizzle.swift +0 -33
  135. package/lib/commonjs/models/NewNativeContainerProps.js +0 -2
  136. package/lib/module/models/NewNativeContainerProps.js +0 -2
  137. package/lib/typescript/models/NewNativeContainerProps.d.ts +0 -6
  138. package/src/FWNavigator.tsx +0 -58
  139. package/src/models/NewNativeContainerProps.ts +0 -4
  140. /package/lib/commonjs/models/{NewNativeContainerProps.js.map → IOSFontInfo.js.map} +0 -0
  141. /package/lib/module/models/{NewNativeContainerProps.js.map → IOSFontInfo.js.map} +0 -0
@@ -7,6 +7,22 @@
7
7
 
8
8
  import FireworkVideo
9
9
 
10
+ private struct PlayerInfo {
11
+ enum PlayerMode: Int {
12
+ case fullscreen, floating
13
+ }
14
+ var playerVC: PlayerViewController
15
+ var mode: PlayerMode
16
+ }
17
+
18
+ private struct PlayerExitButtonInfo {
19
+ enum ExitButtonType: Int {
20
+ case close, floating
21
+ }
22
+ var button: UIButton
23
+ var type: ExitButtonType
24
+ }
25
+
10
26
  @objc(FWNavigatorModule)
11
27
  class FWNavigatorModule: RCTEventEmitter, FWNavigator {
12
28
  override func supportedEvents() -> [String]! {
@@ -17,6 +33,10 @@ class FWNavigatorModule: RCTEventEmitter, FWNavigator {
17
33
  return true
18
34
  }
19
35
 
36
+ override var methodQueue: DispatchQueue {
37
+ return DispatchQueue.main
38
+ }
39
+
20
40
  // swiftlint:disable function_body_length
21
41
 
22
42
  @objc(pushNativeContainer:resolver:rejecter:)
@@ -34,92 +54,72 @@ class FWNavigatorModule: RCTEventEmitter, FWNavigator {
34
54
  ])
35
55
  #endif
36
56
 
37
- DispatchQueue.main.async {
38
- guard let props = props as? [String: Any] else {
39
- resolver(false)
40
- return
41
- }
57
+ guard let props = props as? [String: Any] else {
58
+ resolver(false)
59
+ return
60
+ }
42
61
 
43
- guard let appComponentName = gAppComponentName, appComponentName.count > 0 else {
44
- resolver(false)
45
- return
46
- }
62
+ guard let appComponentName = gAppComponentName, appComponentName.count > 0 else {
63
+ resolver(false)
64
+ return
65
+ }
47
66
 
48
- guard let presentedVC = RCTPresentedViewController() else {
49
- resolver(false)
50
- return
51
- }
67
+ guard let presentedVC = RCTPresentedViewController() else {
68
+ resolver(false)
69
+ return
70
+ }
52
71
 
53
- #if DEBUG
54
- self.sendEvent(
55
- withName: FWEventName.logMessage.rawValue,
56
- body: [
57
- "message":
58
- "[iOS] Before creating containerViewController \(formatter.string(from: Date()))"
59
- ])
60
- #endif
72
+ #if DEBUG
73
+ self.sendEvent(
74
+ withName: FWEventName.logMessage.rawValue,
75
+ body: [
76
+ "message":
77
+ "[iOS] Before creating containerViewController \(formatter.string(from: Date()))"
78
+ ])
79
+ #endif
61
80
 
62
- let containerViewController = FWNavigatorContainerViewController()
81
+ let containerViewController = FWNavigatorContainerViewController()
63
82
 
64
- #if DEBUG
65
- self.sendEvent(
66
- withName: FWEventName.logMessage.rawValue,
67
- body: [
68
- "message":
69
- "[iOS] After creating containerViewController \(formatter.string(from: Date()))"
70
- ])
71
- #endif
83
+ #if DEBUG
84
+ self.sendEvent(
85
+ withName: FWEventName.logMessage.rawValue,
86
+ body: [
87
+ "message":
88
+ "[iOS] After creating containerViewController \(formatter.string(from: Date()))"
89
+ ])
90
+ #endif
72
91
 
73
- containerViewController.moduleName = appComponentName
74
- containerViewController.properties = props
75
- containerViewController.modalPresentationStyle = .fullScreen
76
- if presentedVC.modalPresentationStyle == .custom,
77
- let presentingVC = presentedVC.presentingViewController,
78
- presentingVC is FireworkVideo.PlayerViewController
79
- {
80
- containerViewController.modalPresentationStyle = .overFullScreen
81
- }
92
+ containerViewController.moduleName = appComponentName
93
+ containerViewController.properties = props
94
+ containerViewController.modalPresentationStyle = .fullScreen
95
+ if presentedVC.modalPresentationStyle == .custom,
96
+ let presentingVC = presentedVC.presentingViewController,
97
+ presentingVC is FireworkVideo.PlayerViewController
98
+ {
99
+ containerViewController.modalPresentationStyle = .overFullScreen
100
+ }
101
+
102
+ #if DEBUG
103
+ self.sendEvent(
104
+ withName: FWEventName.logMessage.rawValue,
105
+ body: [
106
+ "message":
107
+ "[iOS] Present containerViewController \(formatter.string(from: Date()))"
108
+ ])
109
+ #endif
82
110
 
111
+ presentedVC.present(containerViewController, animated: true) {
83
112
  #if DEBUG
84
113
  self.sendEvent(
85
114
  withName: FWEventName.logMessage.rawValue,
86
115
  body: [
87
116
  "message":
88
- "[iOS] Present containerViewController \(formatter.string(from: Date()))"
117
+ "[iOS] Finish presenting containerViewController \(formatter.string(from: Date()))"
89
118
  ])
90
119
  #endif
91
120
 
92
- presentedVC.present(containerViewController, animated: true) {
93
- #if DEBUG
94
- self.sendEvent(
95
- withName: FWEventName.logMessage.rawValue,
96
- body: [
97
- "message":
98
- "[iOS] Finish presenting containerViewController \(formatter.string(from: Date()))"
99
- ])
100
- #endif
101
-
102
- resolver(true)
103
- }
104
- }
105
- }
106
-
107
- func getCloseButton(view: UIView) -> UIButton? {
108
- if let button = view as? UIButton, let targetImage = button.image(for: .normal) {
109
- let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
110
- if targetImage.isEqual(UIImage(named: "closeX", in: iOSSDKBundle, compatibleWith: nil))
111
- || targetImage.isEqual(UIImage(named: "down-arrow-light", in: iOSSDKBundle, compatibleWith: nil)) {
112
- return button
113
- }
114
- }
115
-
116
- for subview in view.subviews {
117
- if let result = getCloseButton(view: subview) {
118
- return result
119
- }
121
+ resolver(true)
120
122
  }
121
-
122
- return nil
123
123
  }
124
124
 
125
125
  // swiftlint:enable function_body_length
@@ -128,45 +128,54 @@ class FWNavigatorModule: RCTEventEmitter, FWNavigator {
128
128
  func popNativeContainer(
129
129
  _ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
130
130
  ) {
131
- DispatchQueue.main.async {
132
- if let navigatorContainerVC = RCTPresentedViewController()
133
- as? FWNavigatorContainerViewController,
134
- navigatorContainerVC.presentingViewController != nil {
135
- navigatorContainerVC.dismiss(animated: true) {
136
- resolver(true)
137
- }
138
- } else if let cartViewController = gCartViewController {
139
- cartViewController.navigationController?.popViewController(animated: true)
140
- gCartViewController = nil
131
+ if let navigatorContainerVC = RCTPresentedViewController()
132
+ as? FWNavigatorContainerViewController,
133
+ navigatorContainerVC.presentingViewController != nil {
134
+ navigatorContainerVC.dismiss(animated: true) {
141
135
  resolver(true)
142
- } else if let presentedVC = RCTPresentedViewController(),
143
- let presentingVC = presentedVC.presentingViewController,
144
- presentingVC.presentingViewController == RCTKeyWindow()?.rootViewController {
145
- presentedVC.dismiss(animated: false) {
146
- DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.1) {
147
- if let closeButton = self.getCloseButton(view: presentingVC.view) {
148
- closeButton.sendActions(for: .touchUpInside)
136
+ }
137
+ } else if let cartViewController = gCartViewController {
138
+ cartViewController.navigationController?.popViewController(animated: true)
139
+ gCartViewController = nil
140
+ resolver(true)
141
+ } else if let presentedVC = RCTPresentedViewController(),
142
+ FWNavigatorModule.isIOSSDKViewController(presentedVC),
143
+ let presentingVC = presentedVC.presentingViewController,
144
+ presentingVC.presentingViewController == RCTKeyWindow()?.rootViewController,
145
+ FWNavigatorModule.isIOSSDKViewController(presentingVC) {
146
+ presentedVC.dismiss(animated: false) {
147
+ DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.1) {
148
+ if let buttonInfo = FWNavigatorModule.getPlayerExitButtonInfo(view: presentingVC.view) {
149
+ if buttonInfo.type == .close {
150
+ buttonInfo.button.sendActions(for: .touchUpInside)
149
151
  resolver(true)
150
152
  } else {
151
- presentingVC.dismiss(animated: true) {
152
- resolver(true)
153
- }
153
+ resolver(false)
154
+ }
155
+ } else {
156
+ presentingVC.dismiss(animated: true) {
157
+ resolver(true)
154
158
  }
155
159
  }
156
160
  }
157
- } else if let rootVC = RCTKeyWindow()?.rootViewController,
158
- let presentedVC = rootVC.presentedViewController {
159
- if let closeButton = self.getCloseButton(view: presentedVC.view) {
160
- closeButton.sendActions(for: .touchUpInside)
161
+ }
162
+ } else if let rootVC = RCTKeyWindow()?.rootViewController,
163
+ let presentedVC = rootVC.presentedViewController,
164
+ FWNavigatorModule.isIOSSDKViewController(presentedVC) {
165
+ if let buttonInfo = FWNavigatorModule.getPlayerExitButtonInfo(view: presentedVC.view) {
166
+ if buttonInfo.type == .close {
167
+ buttonInfo.button.sendActions(for: .touchUpInside)
161
168
  resolver(true)
162
169
  } else {
163
- presentedVC.dismiss(animated: true) {
164
- resolver(true)
165
- }
170
+ resolver(false)
166
171
  }
167
172
  } else {
168
- resolver(false)
173
+ presentedVC.dismiss(animated: true) {
174
+ resolver(true)
175
+ }
169
176
  }
177
+ } else {
178
+ resolver(false)
170
179
  }
171
180
  }
172
181
 
@@ -174,15 +183,198 @@ class FWNavigatorModule: RCTEventEmitter, FWNavigator {
174
183
  func canPopNativeContainer(
175
184
  _ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
176
185
  ) {
177
- DispatchQueue.main.async {
178
- if let presentedVC = RCTPresentedViewController(),
179
- presentedVC.presentingViewController != nil {
180
- resolver(true)
181
- } else if gCartViewController != nil {
186
+ if let navigatorContainerVC = RCTPresentedViewController()
187
+ as? FWNavigatorContainerViewController,
188
+ navigatorContainerVC.presentingViewController != nil {
189
+ resolver(true)
190
+ } else if let _ = gCartViewController {
191
+ resolver(true)
192
+ } else if let presentedVC = RCTPresentedViewController(),
193
+ FWNavigatorModule.isIOSSDKViewController(presentedVC),
194
+ let presentingVC = presentedVC.presentingViewController,
195
+ presentingVC.presentingViewController == RCTKeyWindow()?.rootViewController,
196
+ FWNavigatorModule.isIOSSDKViewController(presentingVC) {
197
+ if let buttonInfo = FWNavigatorModule.getPlayerExitButtonInfo(view: presentingVC.view) {
198
+ if buttonInfo.type == .close {
199
+ resolver(true)
200
+ } else {
201
+ resolver(false)
202
+ }
203
+ } else {
182
204
  resolver(true)
205
+ }
206
+ } else if let rootVC = RCTKeyWindow()?.rootViewController,
207
+ let presentedVC = rootVC.presentedViewController,
208
+ FWNavigatorModule.isIOSSDKViewController(presentedVC) {
209
+ if let buttonInfo = FWNavigatorModule.getPlayerExitButtonInfo(view: presentedVC.view) {
210
+ if buttonInfo.type == .close {
211
+ resolver(true)
212
+ } else {
213
+ resolver(false)
214
+ }
183
215
  } else {
216
+ resolver(true)
217
+ }
218
+ } else {
219
+ resolver(false)
220
+ }
221
+ }
222
+
223
+ @objc(startFloatingPlayer:rejecter:)
224
+ func startFloatingPlayer(
225
+ _ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
226
+ ) {
227
+ guard let playerInfo = FWNavigatorModule.getPlayerInfo() else {
228
+ resolver(false)
229
+ return
230
+ }
231
+
232
+ if playerInfo.mode == .fullscreen {
233
+ do {
234
+ try playerInfo.playerVC.startPictureInPicture()
235
+ resolver(true)
236
+ } catch {
184
237
  resolver(false)
185
238
  }
239
+ } else {
240
+ // current player is already in floating mode.
241
+ resolver(false)
242
+ }
243
+ }
244
+
245
+ @objc(stopFloatingPlayer:rejecter:)
246
+ func stopFloatingPlayer(
247
+ _ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
248
+ ) {
249
+ let result = FWNavigatorModule.stopFloatingPlayer()
250
+ resolver(result)
251
+ }
252
+ }
253
+
254
+ extension FWNavigatorModule {
255
+ private static func getPlayerExitButtonInfo(view: UIView) -> PlayerExitButtonInfo? {
256
+ if let button = view as? UIButton, let targetImage = button.image(for: .normal) {
257
+ let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
258
+ if targetImage.isEqual(UIImage(named: "closeX", in: iOSSDKBundle, compatibleWith: nil)) {
259
+ return PlayerExitButtonInfo(button: button, type: .close)
260
+ }
261
+
262
+ if targetImage.isEqual(UIImage(named: "down-arrow-light", in: iOSSDKBundle, compatibleWith: nil)) {
263
+ return PlayerExitButtonInfo(button: button, type: .floating)
264
+ }
265
+ }
266
+
267
+ for subview in view.subviews {
268
+ if let result = getPlayerExitButtonInfo(view: subview) {
269
+ return result
270
+ }
271
+ }
272
+
273
+ return nil
274
+ }
275
+
276
+ private static func getWindowList() -> [UIWindow] {
277
+ var windowList: [UIWindow] = []
278
+ if #available(iOS 13.0, *) {
279
+ for scene in UIApplication.shared.connectedScenes {
280
+ if let currentSene = scene as? UIWindowScene {
281
+ for window in currentSene.windows {
282
+ windowList.append(window)
283
+ }
284
+ }
285
+ }
286
+ } else {
287
+ for window in UIApplication.shared.windows {
288
+ windowList.append(window)
289
+ }
290
+ }
291
+
292
+ return windowList
293
+ }
294
+
295
+ private static func getFurthestAncestorController(_ controller: UIViewController) -> UIViewController {
296
+ guard let parentVC = controller.parent else {
297
+ return controller
298
+ }
299
+
300
+ return getFurthestAncestorController(parentVC)
301
+ }
302
+
303
+ private static func getPlayerViewController(_ viewController: UIViewController) -> PlayerViewController? {
304
+ if let playerVC = viewController as? PlayerViewController {
305
+ return playerVC
306
+ }
307
+
308
+ for childVC in viewController.children {
309
+ if let playerVC = getPlayerViewController(childVC) {
310
+ return playerVC
311
+ }
312
+ }
313
+
314
+ return nil
315
+ }
316
+
317
+ private static func getPlayerInfo() -> PlayerInfo? {
318
+ let windowList: [UIWindow] = getWindowList()
319
+
320
+ if let floatingPlayerWindow = windowList.first(where: { window in
321
+ NSStringFromClass(type(of: window)) == "FireworkVideo.FloatingPlayerController"
322
+ }) {
323
+ if let rootVC = floatingPlayerWindow.rootViewController,
324
+ let playerVC = getPlayerViewController(rootVC) {
325
+ return PlayerInfo(playerVC: playerVC, mode: .floating)
326
+ }
327
+ return nil
328
+ }
329
+
330
+ if let keyWindow = windowList.first(where: { window in
331
+ return window.isKeyWindow
332
+ }) {
333
+ if let rootVC = keyWindow.rootViewController,
334
+ let presentedVC = rootVC.presentedViewController {
335
+ let furthestAncestorController = getFurthestAncestorController(presentedVC)
336
+
337
+ if let playerVC = getPlayerViewController(furthestAncestorController) {
338
+ return PlayerInfo(playerVC: playerVC, mode: .fullscreen)
339
+ }
340
+ }
341
+
342
+ return nil
343
+ }
344
+
345
+ return nil
346
+ }
347
+
348
+ private static func isIOSSDKViewController(_ controller: UIViewController?) -> Bool {
349
+ guard let controller = controller else {
350
+ return false
351
+ }
352
+
353
+ let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
354
+ if Bundle(for: type(of: controller)) == iOSSDKBundle {
355
+ return true
356
+ }
357
+
358
+ return isIOSSDKViewController(controller.parent)
359
+ }
360
+ }
361
+
362
+ extension FWNavigatorModule {
363
+ static func stopFloatingPlayer() -> Bool {
364
+ guard let playerInfo = self.getPlayerInfo() else {
365
+ return false
366
+ }
367
+
368
+ if playerInfo.mode == .floating {
369
+ do {
370
+ try playerInfo.playerVC.stopPictureInPicture()
371
+ return true
372
+ } catch {
373
+ return false
374
+ }
375
+ } else {
376
+ // current player is in fullscreen player
377
+ return false
186
378
  }
187
379
  }
188
380
  }
@@ -127,7 +127,5 @@ extension FireworkSDKModule: FireworkVideoFeedDelegate {
127
127
 
128
128
  sendEvent(
129
129
  withName: FWEventName.videoFeedClick.rawValue, body: ["info": eventDetails.jsObject])
130
-
131
- FWPiPManager.shared.removeAllPiPControllers()
132
130
  }
133
131
  }
@@ -30,6 +30,10 @@ class FireworkSDKModule: RCTEventEmitter, FireworkVideoSDKDelegate {
30
30
  return true
31
31
  }
32
32
 
33
+ override var methodQueue: DispatchQueue {
34
+ return DispatchQueue.main
35
+ }
36
+
33
37
  @objc(initializeSDK:)
34
38
  func initializeSDK(_ userId: String? = nil) {
35
39
  #if DEBUG
@@ -42,12 +46,10 @@ class FireworkSDKModule: RCTEventEmitter, FireworkVideoSDKDelegate {
42
46
  sendEvent(withName: FWEventName.logMessage.rawValue, body: ["message": message])
43
47
  #endif
44
48
 
45
- DispatchQueue.main.async {
46
- FireworkVideoSDK.initializeSDK(delegate: self, userID: userId)
47
- FireworkVideoSDK.ctaDelegate = self
48
- FireworkVideoSDK.eventTracking.videoPlaybackDelegate = self
49
- FireworkVideoSDK.eventTracking.feedDelegate = self
50
- }
49
+ FireworkVideoSDK.initializeSDK(delegate: self, userID: userId)
50
+ FireworkVideoSDK.ctaDelegate = self
51
+ FireworkVideoSDK.eventTracking.videoPlaybackDelegate = self
52
+ FireworkVideoSDK.eventTracking.feedDelegate = self
51
53
  }
52
54
 
53
55
  @objc(openVideoPlayer:config:)
@@ -67,14 +69,12 @@ class FireworkSDKModule: RCTEventEmitter, FireworkVideoSDKDelegate {
67
69
  feedContentConfig.adBadge = adBadge
68
70
  }
69
71
 
70
- DispatchQueue.main.async {
71
- guard let presentedVC = RCTPresentedViewController() else {
72
- return
73
- }
72
+ guard let presentedVC = RCTPresentedViewController() else {
73
+ return
74
+ }
74
75
 
75
- VideoFeedViewController.openVideoPlayer(with: urlString, feedContentConfig, presentedVC) { _ in
76
+ VideoFeedViewController.openVideoPlayer(with: urlString, feedContentConfig, presentedVC) { _ in
76
77
 
77
- }
78
78
  }
79
79
  }
80
80
 
@@ -19,11 +19,13 @@ class LiveStreamModule: RCTEventEmitter, FireworkLiveStreamEventDelegate {
19
19
  return true
20
20
  }
21
21
 
22
+ override var methodQueue: DispatchQueue {
23
+ return DispatchQueue.main
24
+ }
25
+
22
26
  @objc
23
27
  func initialize() {
24
- DispatchQueue.main.async {
25
- FireworkVideoSDK.eventTracking.liveStreamEventDelegate = self
26
- }
28
+ FireworkVideoSDK.eventTracking.liveStreamEventDelegate = self
27
29
  }
28
30
  func fireworkLiveStreamUserDidJoin(_ liveStream: LiveStreamEventDetails) {
29
31
  sendEvent(
@@ -8,12 +8,17 @@
8
8
  import Foundation
9
9
 
10
10
  struct ProductInfoViewConfiguration: Codable {
11
- var addToCartButton: ButtonConfiguration?
11
+ var addToCartButton: AddToCartButtonConfiguration?
12
+ var linkButton: LinkButtonConfiguration?
12
13
 
13
- struct ButtonConfiguration: Codable {
14
+ struct AddToCartButtonConfiguration: Codable {
14
15
  var backgroundColor: String?
15
16
  var textColor: String?
16
17
  var fontSize: Double?
18
+ var iOSFontInfo: FontInfo?
17
19
  }
18
20
 
21
+ struct LinkButtonConfiguration: Codable {
22
+ var isHidden: Bool?
23
+ }
19
24
  }
@@ -13,10 +13,10 @@ _RCT_EXTERN_REMAP_METHOD(init, initialize, NO)
13
13
  RCT_EXTERN_METHOD(setCartIconVisible:(BOOL)visible)
14
14
  RCT_EXTERN_METHOD(setCartItemCount:(int)itemCounts)
15
15
  RCT_EXTERN_METHOD(updateVideoProducts:(NSArray *)products cbId:(nonnull NSNumber *)cbId)
16
- RCT_EXTERN_METHOD(updateProductViewConfig:(NSDictionary *)config cbId:(nonnull NSNumber *)cbId)
17
16
  RCT_EXTERN_METHOD(updateAddToCartStatus:(NSString *)res tips:(nullable NSString *)tips cbId:(nonnull NSNumber *)cbId)
18
17
  RCT_EXTERN_METHOD(jumpToCartPage:(nonnull NSNumber *)cbId props:(NSDictionary *)props)
19
18
  RCT_EXTERN_METHOD(setCustomClickCartIconEnabled:(BOOL)enabled resolver: (RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
19
+ RCT_EXTERN_METHOD(setProductInfoViewConfiguration:(NSDictionary *)config)
20
20
  RCT_EXTERN_METHOD(clearCallbackId:(nonnull NSNumber *)cbId eventName:(nonnull NSString *)name)
21
21
 
22
22
  @end