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.
- package/FireworkVideoUI.xcframework/Info.plist +5 -5
- package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/FireworkVideoUI +0 -0
- package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Info.plist +0 -0
- package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/FireworkVideoUI +0 -0
- package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Info.plist +0 -0
- package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/_CodeSignature/CodeResources +1 -1
- package/ios/Components/StoryBlock.swift +86 -6
- package/ios/Components/StoryBlockConfiguration.swift +1 -0
- package/ios/Components/StoryBlockManager.m +4 -0
- package/ios/Components/VideoFeed.swift +90 -13
- package/ios/Components/VideoFeedManager.m +4 -0
- package/ios/Components/VideoPlayerConfiguration.swift +1 -0
- package/ios/Components/VideoPlayerLogoConfiguration.swift +18 -0
- package/ios/FireworkVideoUI/Podfile +1 -1
- package/ios/FireworkVideoUI/Podfile.lock +4 -4
- package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +71 -8
- package/ios/Modules/FWNavigatorModule/FWRNPresentContainerViewController.swift +30 -0
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule+CTA.swift +23 -2
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule.m +2 -0
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +3 -0
- package/ios/Modules/Shopping/ProductInfoViewConfiguration.swift +41 -8
- package/ios/Modules/Shopping/ShoppingModule.m +2 -0
- package/ios/Modules/Shopping/ShoppingModule.swift +163 -2
- package/lib/commonjs/FireworkSDK.js +16 -0
- package/lib/commonjs/FireworkSDK.js.map +1 -1
- package/lib/commonjs/VideoShopping.js +21 -1
- package/lib/commonjs/VideoShopping.js.map +1 -1
- package/lib/commonjs/components/StoryBlock.js +71 -0
- package/lib/commonjs/components/StoryBlock.js.map +1 -1
- package/lib/commonjs/components/VideoFeed.js +76 -1
- package/lib/commonjs/components/VideoFeed.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/VideoPlayerLogoConfiguration.js +2 -0
- package/lib/commonjs/models/VideoPlayerLogoConfiguration.js.map +1 -0
- package/lib/commonjs/modules/FireworkSDKModule.js.map +1 -1
- package/lib/commonjs/modules/ShoppingModule.js.map +1 -1
- package/lib/module/FireworkSDK.js +15 -0
- package/lib/module/FireworkSDK.js.map +1 -1
- package/lib/module/VideoShopping.js +22 -1
- package/lib/module/VideoShopping.js.map +1 -1
- package/lib/module/components/StoryBlock.js +69 -0
- package/lib/module/components/StoryBlock.js.map +1 -1
- package/lib/module/components/VideoFeed.js +74 -1
- package/lib/module/components/VideoFeed.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/VideoPlayerLogoConfiguration.js +2 -0
- package/lib/module/models/VideoPlayerLogoConfiguration.js.map +1 -0
- package/lib/module/modules/FireworkSDKModule.js.map +1 -1
- package/lib/module/modules/ShoppingModule.js.map +1 -1
- package/lib/typescript/components/StoryBlock.d.ts +12 -1
- package/lib/typescript/components/VideoFeed.d.ts +12 -1
- package/lib/typescript/index.d.ts +3 -2
- package/lib/typescript/models/FWEvents.d.ts +21 -0
- package/lib/typescript/models/ProductInfoViewConfiguration.d.ts +110 -5
- package/lib/typescript/models/StoryBlockConfiguration.d.ts +7 -0
- package/lib/typescript/models/VideoPlayerConfiguration.d.ts +7 -0
- package/lib/typescript/models/VideoPlayerLogoConfiguration.d.ts +15 -0
- package/lib/typescript/modules/FireworkSDKModule.d.ts +2 -0
- package/lib/typescript/modules/ShoppingModule.d.ts +2 -0
- package/package.json +1 -1
- package/react-native-firework-sdk.podspec +1 -1
- package/src/FireworkSDK.ts +16 -0
- package/src/VideoShopping.ts +18 -1
- package/src/components/StoryBlock.tsx +92 -3
- package/src/components/VideoFeed.tsx +93 -2
- package/src/index.ts +14 -0
- package/src/models/FWEvents.ts +24 -0
- package/src/models/ProductInfoViewConfiguration.ts +114 -5
- package/src/models/StoryBlockConfiguration.ts +7 -0
- package/src/models/VideoPlayerConfiguration.ts +7 -0
- package/src/models/VideoPlayerLogoConfiguration.ts +23 -0
- package/src/modules/FireworkSDKModule.ts +2 -0
- 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-
|
|
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-
|
|
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>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Info.plist
CHANGED
|
Binary file
|
|
@@ -19,7 +19,8 @@ public protocol StoryBlockViewDelegate: AnyObject {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
@objc
|
|
22
|
-
|
|
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
|
-
|
|
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
|
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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]);
|
|
@@ -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
|
+
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
PODS:
|
|
2
|
-
- FireworkVideo (1.
|
|
2
|
+
- FireworkVideo (1.15.0)
|
|
3
3
|
|
|
4
4
|
DEPENDENCIES:
|
|
5
|
-
- FireworkVideo (= 1.
|
|
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:
|
|
12
|
+
FireworkVideo: fae657a5093efadbf7f4aa723466aee8dcf47824
|
|
13
13
|
|
|
14
|
-
PODFILE CHECKSUM:
|
|
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
|
|
166
|
-
let
|
|
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
|
-
|
|
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
|
|
195
|
-
let
|
|
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
|
-
|
|
206
|
-
detachedController.didMove(toParent:
|
|
232
|
+
rootViewPlaceholderVC.addChild(detachedController)
|
|
233
|
+
detachedController.didMove(toParent: rootViewPlaceholderVC)
|
|
207
234
|
}
|
|
208
235
|
rootView.removeFromSuperview()
|
|
209
|
-
|
|
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
|
-
|
|
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
|