react-native-firework-sdk 2.7.1 → 2.8.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.
Files changed (73) hide show
  1. package/FireworkVideoUI.xcframework/Info.plist +5 -5
  2. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/FireworkVideoUI +0 -0
  3. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Info.plist +0 -0
  4. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/FireworkVideoUI +0 -0
  5. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Info.plist +0 -0
  6. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/_CodeSignature/CodeResources +1 -1
  7. package/ios/Components/StoryBlock.swift +86 -6
  8. package/ios/Components/StoryBlockConfiguration.swift +1 -0
  9. package/ios/Components/StoryBlockManager.m +4 -0
  10. package/ios/Components/VideoFeed.swift +90 -13
  11. package/ios/Components/VideoFeedManager.m +4 -0
  12. package/ios/Components/VideoPlayerConfiguration.swift +1 -0
  13. package/ios/Components/VideoPlayerLogoConfiguration.swift +18 -0
  14. package/ios/FireworkVideoUI/Podfile +1 -1
  15. package/ios/FireworkVideoUI/Podfile.lock +4 -4
  16. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +71 -8
  17. package/ios/Modules/FWNavigatorModule/FWRNPresentContainerViewController.swift +30 -0
  18. package/ios/Modules/FireworkSDKModule/FireworkSDKModule+CTA.swift +23 -2
  19. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.m +2 -0
  20. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +3 -0
  21. package/ios/Modules/Shopping/ProductInfoViewConfiguration.swift +41 -8
  22. package/ios/Modules/Shopping/ShoppingModule.m +2 -0
  23. package/ios/Modules/Shopping/ShoppingModule.swift +163 -2
  24. package/lib/commonjs/FireworkSDK.js +16 -0
  25. package/lib/commonjs/FireworkSDK.js.map +1 -1
  26. package/lib/commonjs/VideoShopping.js +21 -1
  27. package/lib/commonjs/VideoShopping.js.map +1 -1
  28. package/lib/commonjs/components/StoryBlock.js +71 -0
  29. package/lib/commonjs/components/StoryBlock.js.map +1 -1
  30. package/lib/commonjs/components/VideoFeed.js +76 -1
  31. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  32. package/lib/commonjs/index.js.map +1 -1
  33. package/lib/commonjs/models/VideoPlayerLogoConfiguration.js +2 -0
  34. package/lib/commonjs/models/VideoPlayerLogoConfiguration.js.map +1 -0
  35. package/lib/commonjs/modules/FireworkSDKModule.js.map +1 -1
  36. package/lib/commonjs/modules/ShoppingModule.js.map +1 -1
  37. package/lib/module/FireworkSDK.js +15 -0
  38. package/lib/module/FireworkSDK.js.map +1 -1
  39. package/lib/module/VideoShopping.js +22 -1
  40. package/lib/module/VideoShopping.js.map +1 -1
  41. package/lib/module/components/StoryBlock.js +69 -0
  42. package/lib/module/components/StoryBlock.js.map +1 -1
  43. package/lib/module/components/VideoFeed.js +74 -1
  44. package/lib/module/components/VideoFeed.js.map +1 -1
  45. package/lib/module/index.js.map +1 -1
  46. package/lib/module/models/VideoPlayerLogoConfiguration.js +2 -0
  47. package/lib/module/models/VideoPlayerLogoConfiguration.js.map +1 -0
  48. package/lib/module/modules/FireworkSDKModule.js.map +1 -1
  49. package/lib/module/modules/ShoppingModule.js.map +1 -1
  50. package/lib/typescript/components/StoryBlock.d.ts +12 -1
  51. package/lib/typescript/components/VideoFeed.d.ts +12 -1
  52. package/lib/typescript/index.d.ts +3 -2
  53. package/lib/typescript/models/FWEvents.d.ts +21 -0
  54. package/lib/typescript/models/ProductInfoViewConfiguration.d.ts +110 -5
  55. package/lib/typescript/models/StoryBlockConfiguration.d.ts +7 -0
  56. package/lib/typescript/models/VideoPlayerConfiguration.d.ts +7 -0
  57. package/lib/typescript/models/VideoPlayerLogoConfiguration.d.ts +15 -0
  58. package/lib/typescript/modules/FireworkSDKModule.d.ts +2 -0
  59. package/lib/typescript/modules/ShoppingModule.d.ts +2 -0
  60. package/package.json +1 -1
  61. package/react-native-firework-sdk.podspec +1 -1
  62. package/src/FireworkSDK.ts +16 -0
  63. package/src/VideoShopping.ts +18 -1
  64. package/src/components/StoryBlock.tsx +92 -3
  65. package/src/components/VideoFeed.tsx +93 -2
  66. package/src/index.ts +14 -0
  67. package/src/models/FWEvents.ts +24 -0
  68. package/src/models/ProductInfoViewConfiguration.ts +114 -5
  69. package/src/models/StoryBlockConfiguration.ts +7 -0
  70. package/src/models/VideoPlayerConfiguration.ts +7 -0
  71. package/src/models/VideoPlayerLogoConfiguration.ts +23 -0
  72. package/src/modules/FireworkSDKModule.ts +2 -0
  73. package/src/modules/ShoppingModule.ts +2 -0
@@ -6,30 +6,30 @@
6
6
  <array>
7
7
  <dict>
8
8
  <key>LibraryIdentifier</key>
9
- <string>ios-arm64_x86_64-simulator</string>
9
+ <string>ios-arm64</string>
10
10
  <key>LibraryPath</key>
11
11
  <string>FireworkVideoUI.framework</string>
12
12
  <key>SupportedArchitectures</key>
13
13
  <array>
14
14
  <string>arm64</string>
15
- <string>x86_64</string>
16
15
  </array>
17
16
  <key>SupportedPlatform</key>
18
17
  <string>ios</string>
19
- <key>SupportedPlatformVariant</key>
20
- <string>simulator</string>
21
18
  </dict>
22
19
  <dict>
23
20
  <key>LibraryIdentifier</key>
24
- <string>ios-arm64</string>
21
+ <string>ios-arm64_x86_64-simulator</string>
25
22
  <key>LibraryPath</key>
26
23
  <string>FireworkVideoUI.framework</string>
27
24
  <key>SupportedArchitectures</key>
28
25
  <array>
29
26
  <string>arm64</string>
27
+ <string>x86_64</string>
30
28
  </array>
31
29
  <key>SupportedPlatform</key>
32
30
  <string>ios</string>
31
+ <key>SupportedPlatformVariant</key>
32
+ <string>simulator</string>
33
33
  </dict>
34
34
  </array>
35
35
  <key>CFBundlePackageType</key>
@@ -14,7 +14,7 @@
14
14
  </data>
15
15
  <key>Info.plist</key>
16
16
  <data>
17
- p6/LLg4hl5dM7i1ps8S9Rzkge2s=
17
+ +sxLWZZaXLRZ4LE21UnZGJgO790=
18
18
  </data>
19
19
  <key>Modules/FireworkVideoUI.swiftmodule/arm64-apple-ios-simulator.abi.json</key>
20
20
  <data>
@@ -19,7 +19,8 @@ public protocol StoryBlockViewDelegate: AnyObject {
19
19
  }
20
20
 
21
21
  @objc
22
- public class StoryBlock: UIView, StoryBlockViewControllerDelegate {
22
+ // swiftlint:disable:next type_body_length
23
+ public class StoryBlock: UIView, StoryBlockViewControllerDelegate, PictureInPictureControllerDelegate {
23
24
  @objc public var sourceType: StoryBlockSourceType = .discover
24
25
  @objc public var channel: String = ""
25
26
  @objc public var playlist: String = ""
@@ -30,7 +31,20 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate {
30
31
  @objc public var adConfiguration: AdConfiguration?
31
32
  @objc public var storyBlockConfiguration: StoryBlockConfiguration? {
32
33
  didSet {
33
- updateStoryBlockVCConfiguration()
34
+ guard let storyBlockVC = storyBlockVC else {
35
+ return
36
+ }
37
+
38
+ if storyBlockConfiguration?.videoPlayerLogoConfiguration != oldValue?.videoPlayerLogoConfiguration {
39
+ storyBlockVC.isPictureInPictureEnabled = false
40
+ storyBlockVC.detachFromParent()
41
+ self.storyBlockVC = nil
42
+ DispatchQueue.main.async {
43
+ self.embed()
44
+ }
45
+ } else {
46
+ updateStoryBlockVCConfiguration()
47
+ }
34
48
  }
35
49
  }
36
50
 
@@ -38,6 +52,10 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate {
38
52
 
39
53
  @objc var onStoryBlockLoadFinished: RCTBubblingEventBlock?
40
54
 
55
+ @objc var onStoryBlockDidStartPictureInPicture: RCTBubblingEventBlock?
56
+
57
+ @objc var onStoryBlockDidStopPictureInPicture: RCTBubblingEventBlock?
58
+
41
59
  private var storyBlockVC: StoryBlockViewController?
42
60
 
43
61
  private var source: StoryBlockContentSource {
@@ -59,6 +77,7 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate {
59
77
  return .singleContent(videoOrLiveStreamID: contentId)
60
78
  }
61
79
  }
80
+ private var isInPip: Bool = false
62
81
 
63
82
  public override init(frame: CGRect) {
64
83
  super.init(frame: frame)
@@ -94,11 +113,13 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate {
94
113
  return
95
114
  }
96
115
 
97
- storyBlockVC.isPictureInPictureEnabled = storyBlockConfiguration?.enablePictureInPicture ?? true
98
-
99
- storyBlockVC.delegate = self
100
116
  self.storyBlockVC = storyBlockVC
101
117
  updateStoryBlockVCConfiguration()
118
+
119
+ storyBlockVC.isPictureInPictureEnabled = storyBlockConfiguration?.enablePictureInPicture ?? true
120
+ storyBlockVC.pictureInPictureDelegate = self
121
+ storyBlockVC.delegate = self
122
+
102
123
  parentVC.attachChild(storyBlockVC, to: self)
103
124
  }
104
125
 
@@ -108,7 +129,9 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate {
108
129
  guard let storyBlockVC = self.storyBlockVC else {
109
130
  return
110
131
  }
111
-
132
+ if !isInPip {
133
+ storyBlockVC.isPictureInPictureEnabled = false
134
+ }
112
135
  storyBlockVC.detachFromParent()
113
136
  self.storyBlockVC = nil
114
137
  }
@@ -282,6 +305,63 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate {
282
305
  resultConfig.adBadge = adBadge
283
306
  }
284
307
 
308
+ if let videoPlayerLogoConfiguration = config.videoPlayerLogoConfiguration {
309
+ switch videoPlayerLogoConfiguration.option {
310
+ case .disabled:
311
+ resultConfig.logoConfiguration.option = .disabled
312
+ resultConfig.fullScreenPlayerView.logoConfiguration.option = .disabled
313
+ case .creator:
314
+ if let encodedId = videoPlayerLogoConfiguration.encodedId {
315
+ resultConfig.logoConfiguration.option = .creator(encodedId)
316
+ resultConfig.fullScreenPlayerView.logoConfiguration.option = .creator(encodedId)
317
+ }
318
+ case .channelAggregator:
319
+ if let encodedId = videoPlayerLogoConfiguration.encodedId {
320
+ resultConfig.logoConfiguration.option = .channelAggregator(encodedId)
321
+ resultConfig.fullScreenPlayerView.logoConfiguration.option = .channelAggregator(encodedId)
322
+ }
323
+ }
324
+ }
325
+
285
326
  storyBlockVC.viewConfiguration = resultConfig
286
327
  }
328
+
329
+ // MARK: PictureInPictureDelegate
330
+
331
+ public func pictureInPictureControllerWillStartPictureInPicture(
332
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController
333
+ ) {
334
+ }
335
+
336
+ public func pictureInPictureControllerDidStartPictureInPicture(
337
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController
338
+ ) {
339
+ self.onStoryBlockDidStartPictureInPicture?(nil)
340
+ isInPip = true
341
+ }
342
+
343
+ public func pictureInPictureController(
344
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController,
345
+ failedToStartPictureInPictureWithError error: Error?
346
+ ) {
347
+ }
348
+
349
+ public func pictureInPictureControllerWillStopPictureInPicture(
350
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController
351
+ ) {
352
+ }
353
+
354
+ public func pictureInPictureControllerDidStopPictureInPicture(
355
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController
356
+ ) {
357
+ self.onStoryBlockDidStopPictureInPicture?(nil)
358
+ isInPip = false
359
+ }
360
+
361
+ public func pictureInPictureController(
362
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController,
363
+ restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void
364
+ ) {
365
+ completionHandler(true)
366
+ }
287
367
  }
@@ -23,4 +23,5 @@ public class StoryBlockConfiguration: NSObject, Codable {
23
23
  var enablePictureInPicture: Bool?
24
24
  var buttonConfiguration: VideoPlayerButtonConfiguration?
25
25
  var showVideoDetailTitle: Bool?
26
+ var videoPlayerLogoConfiguration: VideoPlayerLogoConfiguration?
26
27
  }
@@ -43,6 +43,10 @@ RCT_CUSTOM_VIEW_PROPERTY(storyBlockConfiguration, StoryBlockConfiguration, Story
43
43
 
44
44
  RCT_EXPORT_VIEW_PROPERTY(onStoryBlockLoadFinished, RCTBubblingEventBlock)
45
45
 
46
+ RCT_EXPORT_VIEW_PROPERTY(onStoryBlockDidStartPictureInPicture, RCTBubblingEventBlock)
47
+
48
+ RCT_EXPORT_VIEW_PROPERTY(onStoryBlockDidStopPictureInPicture, RCTBubblingEventBlock)
49
+
46
50
  RCT_EXPORT_METHOD(play:(nonnull NSNumber *)reactTag) {
47
51
  [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
48
52
  StoryBlock *view = (StoryBlock *)(viewRegistry[reactTag]);
@@ -33,7 +33,7 @@ public protocol VideoFeedDelegate: AnyObject {
33
33
  }
34
34
 
35
35
  @objc
36
- public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
36
+ public class VideoFeed: UIView, VideoFeedViewControllerDelegate, PictureInPictureControllerDelegate {
37
37
  @objc public var sourceType: VideFeedSourceType = .discover
38
38
  @objc public var channel: String = ""
39
39
  @objc public var playlist: String = ""
@@ -48,7 +48,8 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
48
48
  guard let feedVC = feedVC else {
49
49
  return
50
50
  }
51
- feedVC.viewConfiguration = convertToVideoFeedContentConfiguration()
51
+ let newVideoFeedContentConfiguration = convertToVideoFeedContentConfiguration()
52
+ feedVC.viewConfiguration = newVideoFeedContentConfiguration
52
53
  feedVC.layout = videoFeedLayout
53
54
  }
54
55
  }
@@ -57,7 +58,18 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
57
58
  guard let feedVC = feedVC else {
58
59
  return
59
60
  }
60
- feedVC.viewConfiguration = convertToVideoFeedContentConfiguration()
61
+
62
+ if playerViewConfig?.videoPlayerLogoConfiguration != oldValue?.videoPlayerLogoConfiguration {
63
+ feedVC.isPictureInPictureEnabled = false
64
+ feedVC.detachFromParent()
65
+ self.feedVC = nil
66
+ DispatchQueue.main.async {
67
+ self.embed()
68
+ }
69
+ } else {
70
+ let newVideoFeedContentConfiguration = convertToVideoFeedContentConfiguration()
71
+ feedVC.viewConfiguration = newVideoFeedContentConfiguration
72
+ }
61
73
  }
62
74
  }
63
75
  @objc public var adConfiguration: AdConfiguration?
@@ -65,6 +77,10 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
65
77
  @objc var onVideoFeedLoadFinished: RCTBubblingEventBlock?
66
78
  // @objc var onVideoFeedClick: RCTBubblingEventBlock?
67
79
 
80
+ @objc var onVideoFeedDidStartPictureInPicture: RCTBubblingEventBlock?
81
+
82
+ @objc var onVideoFeedDidStopPictureInPicture: RCTBubblingEventBlock?
83
+
68
84
  public weak var delegate: VideoFeedDelegate?
69
85
 
70
86
  private var feedVC: VideoFeedViewController?
@@ -141,6 +157,8 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
141
157
  return resultLayout ?? VideoFeedHorizontalLayout()
142
158
  }
143
159
 
160
+ private var isInPip: Bool = false
161
+
144
162
  public override func layoutSubviews() {
145
163
  super.layoutSubviews()
146
164
 
@@ -173,16 +191,6 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
173
191
  return
174
192
  }
175
193
 
176
- if let subView = feedVC.view.subviews.first {
177
- let constraints = feedVC.view.constraints
178
- for constraint in constraints {
179
- if (constraint.firstItem as? NSObject) == subView || (constraint.secondItem as? NSObject) == subView {
180
- constraint.isActive = false
181
- }
182
- }
183
- NSLayoutConstraint.activate(subView.constraints(equalTo: feedVC.view))
184
- }
185
-
186
194
  var viewConfiguration = convertToVideoFeedContentConfiguration()
187
195
  if viewConfiguration.itemView.autoplay.isEnabled {
188
196
  viewConfiguration.itemView.autoplay.isEnabled = false
@@ -198,7 +206,19 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
198
206
  feedVC.isPictureInPictureEnabled = playerViewConfig?.enablePictureInPicture ?? true
199
207
 
200
208
  feedVC.delegate = self
209
+ feedVC.pictureInPictureDelegate = self
201
210
  self.feedVC = feedVC
211
+
212
+ if self.mode != .row, let subView = feedVC.view.subviews.first {
213
+ let constraints = feedVC.view.constraints
214
+ for constraint in constraints {
215
+ if (constraint.firstItem as? NSObject) == subView || (constraint.secondItem as? NSObject) == subView {
216
+ constraint.isActive = false
217
+ }
218
+ }
219
+ NSLayoutConstraint.activate(subView.constraints(equalTo: feedVC.view))
220
+ }
221
+
202
222
  parentVC.attachChild(feedVC, to: self)
203
223
  }
204
224
 
@@ -209,6 +229,10 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
209
229
  return
210
230
  }
211
231
 
232
+ if !isInPip {
233
+ feedVC.isPictureInPictureEnabled = false
234
+ }
235
+
212
236
  feedVC.detachFromParent()
213
237
  self.feedVC = nil
214
238
  }
@@ -237,6 +261,45 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
237
261
  }
238
262
  delegate.videoFeed(self, didFailToLoadFeed: error)
239
263
  }
264
+
265
+ // MARK: PictureInPictureDelegate
266
+
267
+ public func pictureInPictureControllerWillStartPictureInPicture(
268
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController
269
+ ) {
270
+ }
271
+
272
+ public func pictureInPictureControllerDidStartPictureInPicture(
273
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController
274
+ ) {
275
+ self.onVideoFeedDidStartPictureInPicture?(nil)
276
+ isInPip = true
277
+ }
278
+
279
+ public func pictureInPictureController(
280
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController,
281
+ failedToStartPictureInPictureWithError error: Error?
282
+ ) {
283
+ }
284
+
285
+ public func pictureInPictureControllerWillStopPictureInPicture(
286
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController
287
+ ) {
288
+ }
289
+
290
+ public func pictureInPictureControllerDidStopPictureInPicture(
291
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController
292
+ ) {
293
+ self.onVideoFeedDidStopPictureInPicture?(nil)
294
+ isInPip = false
295
+ }
296
+
297
+ public func pictureInPictureController(
298
+ _ pictureInPictureController: FireworkVideo.PictureInPictureController,
299
+ restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void
300
+ ) {
301
+ completionHandler(true)
302
+ }
240
303
  }
241
304
 
242
305
  extension VideoFeed {
@@ -432,6 +495,20 @@ extension VideoFeed {
432
495
  vpcConfig.videoDetail.titleConfiguration.isHidden = !showVideoDetailTitle
433
496
  }
434
497
 
498
+ if let videoPlayerLogoConfiguration = config.videoPlayerLogoConfiguration {
499
+ switch videoPlayerLogoConfiguration.option {
500
+ case .disabled:
501
+ vpcConfig.logoConfiguration.option = .disabled
502
+ case .creator:
503
+ if let encodedId = videoPlayerLogoConfiguration.encodedId {
504
+ vpcConfig.logoConfiguration.option = .creator(encodedId)
505
+ }
506
+ case .channelAggregator:
507
+ if let encodedId = videoPlayerLogoConfiguration.encodedId {
508
+ vpcConfig.logoConfiguration.option = .channelAggregator(encodedId)
509
+ }
510
+ }
511
+ }
435
512
  return vpcConfig
436
513
  }
437
514
 
@@ -55,6 +55,10 @@ RCT_CUSTOM_VIEW_PROPERTY(adConfiguration, AdConfiguration, VideoFeed) {
55
55
  RCT_EXPORT_VIEW_PROPERTY(onVideoFeedLoadFinished, RCTBubblingEventBlock)
56
56
  //RCT_EXPORT_VIEW_PROPERTY(onVideoFeedClick, RCTBubblingEventBlock)
57
57
 
58
+ RCT_EXPORT_VIEW_PROPERTY(onVideoFeedDidStartPictureInPicture, RCTBubblingEventBlock)
59
+
60
+ RCT_EXPORT_VIEW_PROPERTY(onVideoFeedDidStopPictureInPicture, RCTBubblingEventBlock)
61
+
58
62
  RCT_EXPORT_METHOD(refresh:(nonnull NSNumber *)reactTag) {
59
63
  [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
60
64
  VideoFeed *view = (VideoFeed *)(viewRegistry[reactTag]);
@@ -72,4 +72,5 @@ public class VideoPlayerConfiguration: NSObject, Codable {
72
72
  var enablePictureInPicture: Bool?
73
73
  var buttonConfiguration: VideoPlayerButtonConfiguration?
74
74
  var showVideoDetailTitle: Bool?
75
+ var videoPlayerLogoConfiguration: VideoPlayerLogoConfiguration?
75
76
  }
@@ -0,0 +1,18 @@
1
+ //
2
+ // VideoPlayerLogoConfiguration.swift
3
+ // react-native-firework-sdk
4
+ //
5
+ // Created by Haitao Shangguan on 2023/9/19.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ public struct VideoPlayerLogoConfiguration: Codable, Equatable {
11
+ enum LogoOption: String, Codable {
12
+ case disabled
13
+ case creator
14
+ case channelAggregator
15
+ }
16
+ var option: LogoOption = .disabled
17
+ var encodedId: String?
18
+ }
@@ -6,7 +6,7 @@ target 'FireworkVideoUI' do
6
6
  use_frameworks!
7
7
 
8
8
  # Pods for FireworkVideoUI
9
- pod 'FireworkVideo', '1.14.0'
9
+ pod 'FireworkVideo', '1.15.0'
10
10
 
11
11
  target 'FireworkVideoUITests' do
12
12
  # Pods for testing
@@ -1,16 +1,16 @@
1
1
  PODS:
2
- - FireworkVideo (1.14.0)
2
+ - FireworkVideo (1.15.0)
3
3
 
4
4
  DEPENDENCIES:
5
- - FireworkVideo (= 1.14.0)
5
+ - FireworkVideo (= 1.15.0)
6
6
 
7
7
  SPEC REPOS:
8
8
  trunk:
9
9
  - FireworkVideo
10
10
 
11
11
  SPEC CHECKSUMS:
12
- FireworkVideo: c8af446a350e2486e86c0a789ecfd4a57ce6facc
12
+ FireworkVideo: fae657a5093efadbf7f4aa723466aee8dcf47824
13
13
 
14
- PODFILE CHECKSUM: 880bd5c72a5a81b620b803189a6ec208e8481116
14
+ PODFILE CHECKSUM: b8d50fd1ccf28eaa3033fe13c43ca09199e1e245
15
15
 
16
16
  COCOAPODS: 1.12.1
@@ -8,6 +8,20 @@
8
8
  import UIKit
9
9
  import FireworkVideo
10
10
 
11
+ class RCTRootViewPlaceholder: UIView {
12
+ weak var reactViewController: UIViewController?
13
+ }
14
+
15
+ private struct RCTRootViewResult {
16
+ weak var viewController: UIViewController?
17
+ weak var view: RCTRootView?
18
+ }
19
+
20
+ struct RCTRootViewPlaceholderResult {
21
+ weak var viewController: UIViewController?
22
+ weak var view: RCTRootViewPlaceholder?
23
+ }
24
+
11
25
  private struct PlayerExitButtonInfo {
12
26
  enum ExitButtonType: Int {
13
27
  case close, floating
@@ -162,8 +176,10 @@ class FWNavigatorModule: RCTEventEmitter {
162
176
  let containerViewController = FWRNPresentContainerViewController()
163
177
  containerViewController.modalPresentationStyle = .fullScreen
164
178
 
165
- guard let window = UIApplication.shared.delegate?.window as? UIWindow,
166
- let rootView = window.rootViewController?.view as? RCTRootView else {
179
+ guard let rootVC = RCTKeyWindow()?.rootViewController,
180
+ let rootViewResult = FWNavigatorModule.findRCTRootViewResult(rootVC),
181
+ let rootViewVC = rootViewResult.viewController,
182
+ let rootView = rootViewResult.view else {
167
183
  resolver(false)
168
184
  return
169
185
  }
@@ -176,10 +192,17 @@ class FWNavigatorModule: RCTEventEmitter {
176
192
  containerViewController.addChild(detachedController)
177
193
  detachedController.didMove(toParent: containerViewController)
178
194
  }
195
+
179
196
  rootView.removeFromSuperview()
180
- window.rootViewController?.view = UIView()
197
+ let placeholderView = RCTRootViewPlaceholder()
198
+ rootViewVC.view = placeholderView
181
199
  containerViewController.rootView = rootView
182
200
  presentedVC.present(containerViewController, animated: true) {
201
+ if rootView.reactViewController() != containerViewController {
202
+ // Save previous reactViewController
203
+ placeholderView.reactViewController = rootView.reactViewController()
204
+ rootView.setReactViewController(containerViewController)
205
+ }
183
206
  resolver(true)
184
207
  }
185
208
  }
@@ -191,22 +214,31 @@ class FWNavigatorModule: RCTEventEmitter {
191
214
  if let containerVC = RCTPresentedViewController() as? FWRNPresentContainerViewController,
192
215
  let rootView = containerVC.rootView,
193
216
  containerVC.presentingViewController != nil {
194
- guard let window = UIApplication.shared.delegate?.window as? UIWindow,
195
- let rootViewController = window.rootViewController else {
217
+ guard let rootVC = RCTKeyWindow()?.rootViewController,
218
+ let rootViewPlaceholderResult = FWNavigatorModule.findRCTRootViewPlaceholderResult(rootVC),
219
+ let rootViewPlaceholderVC = rootViewPlaceholderResult.viewController,
220
+ let rootViewPlaceholder = rootViewPlaceholderResult.view else {
196
221
  resolver(false)
197
222
  return
198
223
  }
224
+
199
225
  let childViewControllers = rootView.reactViewController()?.children
226
+ containerVC.rootView = nil
200
227
  containerVC.dismiss(animated: true) {
201
228
  childViewControllers?.forEach { (childViewController) in
202
229
  let detachedController = childViewController
203
230
  detachedController.willMove(toParent: nil)
204
231
  detachedController.removeFromParent()
205
- rootViewController.addChild(detachedController)
206
- detachedController.didMove(toParent: rootViewController)
232
+ rootViewPlaceholderVC.addChild(detachedController)
233
+ detachedController.didMove(toParent: rootViewPlaceholderVC)
207
234
  }
208
235
  rootView.removeFromSuperview()
209
- rootViewController.view = rootView
236
+ rootViewPlaceholderVC.view = rootView
237
+
238
+ if let reactViewController = rootViewPlaceholder.reactViewController {
239
+ // Restore previous reactViewController
240
+ rootView.setReactViewController(reactViewController)
241
+ }
210
242
  resolver(true)
211
243
  }
212
244
  } else {
@@ -272,6 +304,21 @@ extension FWNavigatorModule {
272
304
 
273
305
  return isIOSSDKViewController(controller.parent)
274
306
  }
307
+
308
+ private static func findRCTRootViewResult(_ viewController: UIViewController) -> RCTRootViewResult? {
309
+ if let rootView = viewController.view as? RCTRootView {
310
+ return RCTRootViewResult(viewController: viewController, view: rootView)
311
+ }
312
+
313
+ for childVC in viewController.children {
314
+ if let result = findRCTRootViewResult(childVC) {
315
+ return result
316
+ }
317
+ }
318
+
319
+ return nil
320
+ }
321
+
275
322
  }
276
323
 
277
324
  extension FWNavigatorModule {
@@ -283,4 +330,20 @@ extension FWNavigatorModule {
283
330
  return false
284
331
  }
285
332
  }
333
+
334
+ static func findRCTRootViewPlaceholderResult(
335
+ _ viewController: UIViewController
336
+ ) -> RCTRootViewPlaceholderResult? {
337
+ if let rootViewPlaceholder = viewController.view as? RCTRootViewPlaceholder {
338
+ return RCTRootViewPlaceholderResult(viewController: viewController, view: rootViewPlaceholder)
339
+ }
340
+
341
+ for childVC in viewController.children {
342
+ if let result = findRCTRootViewPlaceholderResult(childVC) {
343
+ return result
344
+ }
345
+ }
346
+
347
+ return nil
348
+ }
286
349
  }
@@ -15,6 +15,36 @@ class FWRNPresentContainerViewController: UIViewController {
15
15
  loadContent()
16
16
  }
17
17
 
18
+ override func viewDidDisappear(_ animated: Bool) {
19
+ super.viewDidDisappear(animated)
20
+ if let rootView = rootView {
21
+ guard let rootVC = RCTKeyWindow()?.rootViewController,
22
+ let rootViewPlaceholderResult = FWNavigatorModule.findRCTRootViewPlaceholderResult(rootVC),
23
+ let rootViewPlaceholderVC = rootViewPlaceholderResult.viewController,
24
+ let rootViewPlaceholder = rootViewPlaceholderResult.view else {
25
+ return
26
+ }
27
+
28
+ let childViewControllers = rootView.reactViewController()?.children
29
+ childViewControllers?.forEach { (childViewController) in
30
+ let detachedController = childViewController
31
+ detachedController.willMove(toParent: nil)
32
+ detachedController.removeFromParent()
33
+ rootViewPlaceholderVC.addChild(detachedController)
34
+ detachedController.didMove(toParent: rootViewPlaceholderVC)
35
+ }
36
+ rootView.removeFromSuperview()
37
+ rootViewPlaceholderVC.view = rootView
38
+
39
+ if let reactViewController = rootViewPlaceholder.reactViewController {
40
+ // Restore previous reactViewController
41
+ rootView.setReactViewController(reactViewController)
42
+ }
43
+
44
+ self.rootView = nil
45
+ }
46
+ }
47
+
18
48
  private func loadContent() {
19
49
  guard let rootView = rootView else {
20
50
  return
@@ -20,9 +20,30 @@ extension FireworkSDKModule: FireworkVideoCTADelegate {
20
20
  "[iOS] Receive CustomCTAClick event \(formatter.string(from: Date()))"
21
21
  ])
22
22
  #endif
23
-
24
- sendEvent(withName: FWEventName.customCTAClick.rawValue, body: ["url": url.absoluteString])
23
+ let callbackId = UUID().uuidString
24
+ playerMap.setObject(viewController, forKey: callbackId as NSString)
25
+ sendEvent(withName: FWEventName.customCTAClick.rawValue,
26
+ body: [
27
+ "url": url.absoluteString,
28
+ "callbackId": callbackId
29
+ ])
25
30
 
26
31
  return customCTAClickEnabled
27
32
  }
33
+
34
+ @objc(pausePlayer:)
35
+ func pausePlayer(_ callbackId: String) {
36
+ if let playerViewController = playerMap.object(forKey: callbackId as NSString),
37
+ let playerViewController = playerViewController as? PlayerViewController {
38
+ playerViewController.pause()
39
+ }
40
+ }
41
+
42
+ @objc(resumePlayer:)
43
+ func resumePlayer(_ callbackId: String) {
44
+ if let playerViewController = playerMap.object(forKey: callbackId as NSString),
45
+ let playerViewController = playerViewController as? PlayerViewController {
46
+ playerViewController.resume()
47
+ }
48
+ }
28
49
  }
@@ -19,5 +19,7 @@ RCT_EXTERN_METHOD(setVideoPlaybackEventEnabled:(BOOL)enabled)
19
19
  RCT_EXTERN_METHOD(setAdBadgeConfiguration:(NSDictionary *)config resolver: (RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
20
20
  RCT_EXTERN_METHOD(trackPurchase:(NSDictionary *)parameters)
21
21
  RCT_EXTERN_METHOD(changeAppLanguage:(NSString * __nullable)language resolver: (RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
22
+ RCT_EXTERN_METHOD(pausePlayer:(NSString *)callbackId)
23
+ RCT_EXTERN_METHOD(resumePlayer:(NSString *)callbackId)
22
24
 
23
25
  @end