react-native-firework-sdk 1.6.1 → 1.7.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 (55) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWStoryBlockManager.kt +39 -42
  3. package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FireworkSDKInterface.kt +2 -0
  4. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWNavigatorModule.kt +35 -0
  5. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +55 -0
  6. package/android/src/main/java/com/fireworksdk/bridge/utils/FWLanguageUtil.kt +72 -0
  7. package/ios/Components/StoryBlock.swift +5 -4
  8. package/ios/Components/VideoFeed.swift +27 -35
  9. package/ios/Components/VideoPlayerConfiguration.swift +11 -0
  10. package/ios/FireworkSdk.xcodeproj/project.pbxproj +26 -16
  11. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +2 -11
  12. package/ios/Modules/FireworkSDKModule/FireworkSDKModule+EventTracking.swift +2 -0
  13. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +1 -1
  14. package/ios/Utils/DispatchQueue+FWOnce.swift +32 -0
  15. package/ios/Utils/FWPiPManager.swift +24 -0
  16. package/ios/Utils/FWSwizzleLoader.h +15 -0
  17. package/ios/Utils/FWSwizzleLoader.m +17 -0
  18. package/ios/Utils/FWSwizzleUtil.swift +29 -0
  19. package/ios/Utils/UIButton+FWSwizzle.swift +33 -0
  20. package/ios/Utils/UINavigationController+FWSwizzle.swift +30 -0
  21. package/ios/react_native_firework_sdk.h +1 -2
  22. package/lib/commonjs/FireworkSDK.js +21 -1
  23. package/lib/commonjs/FireworkSDK.js.map +1 -1
  24. package/lib/commonjs/VideoShopping.js +7 -7
  25. package/lib/commonjs/VideoShopping.js.map +1 -1
  26. package/lib/commonjs/components/VideoFeed.js +3 -1
  27. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  28. package/lib/commonjs/index.js.map +1 -1
  29. package/lib/commonjs/modules/FireworkSDKModule.js.map +1 -1
  30. package/lib/module/FireworkSDK.js +21 -1
  31. package/lib/module/FireworkSDK.js.map +1 -1
  32. package/lib/module/VideoShopping.js +7 -7
  33. package/lib/module/VideoShopping.js.map +1 -1
  34. package/lib/module/components/VideoFeed.js +3 -1
  35. package/lib/module/components/VideoFeed.js.map +1 -1
  36. package/lib/module/index.js.map +1 -1
  37. package/lib/module/modules/FireworkSDKModule.js.map +1 -1
  38. package/lib/typescript/FireworkSDK.d.ts +7 -3
  39. package/lib/typescript/VideoShopping.d.ts +7 -7
  40. package/lib/typescript/index.d.ts +3 -3
  41. package/lib/typescript/models/VideoPlayerConfiguration.d.ts +19 -0
  42. package/lib/typescript/modules/FireworkSDKModule.d.ts +2 -0
  43. package/package.json +1 -1
  44. package/react-native-firework-sdk.podspec +2 -4
  45. package/src/FireworkSDK.ts +18 -4
  46. package/src/VideoShopping.ts +7 -7
  47. package/src/components/VideoFeed.tsx +2 -0
  48. package/src/index.tsx +4 -2
  49. package/src/models/VideoPlayerConfiguration.ts +20 -0
  50. package/src/modules/FireworkSDKModule.ts +2 -0
  51. package/ios/Utils/AVPlayer+FWSwizzle.h +0 -17
  52. package/ios/Utils/AVPlayer+FWSwizzle.m +0 -50
  53. package/ios/Utils/FWNavigatorUtils.swift +0 -26
  54. package/ios/Utils/UINavigationController+FWSwizzle.h +0 -16
  55. package/ios/Utils/UINavigationController+FWSwizzle.m +0 -49
@@ -167,7 +167,7 @@ def kotlin_version = getExtOrDefault('kotlinVersion')
167
167
 
168
168
  dependencies {
169
169
 
170
- def firework_sdk_version = 'v5.14.11'
170
+ def firework_sdk_version = 'v5.14.14'
171
171
  implementation "com.github.loopsocial:firework_sdk:$firework_sdk_version"
172
172
 
173
173
  // noinspection GradleDynamicVersion
@@ -53,10 +53,14 @@ class FWStoryBlockManager(
53
53
  val filter = IntentFilter()
54
54
  filter.addAction(FW_STORY_BLOCK_INIT_ACTION)
55
55
  LocalBroadcastManager.getInstance(reactContext).registerReceiver(broadcastReceiver, filter)
56
-
57
56
  return FrameLayout(reactContext)
58
57
  }
59
58
 
59
+ override fun onAfterUpdateTransaction(view: FrameLayout) {
60
+ super.onAfterUpdateTransaction(view)
61
+ FWLogUtils.d { "FWStoryBlockManager onAfterUpdateTransaction" }
62
+ }
63
+
60
64
  @Nullable
61
65
  override fun getCommandsMap(): Map<String, Int>? {
62
66
  return MapBuilder.of("create", COMMAND_CREATE)
@@ -107,9 +111,11 @@ class FWStoryBlockManager(
107
111
  private fun setupLayout(view: View) {
108
112
  Choreographer.getInstance().postFrameCallback(object : Choreographer.FrameCallback {
109
113
  override fun doFrame(frameTimeNanos: Long) {
110
- manuallyLayoutChildren(view)
111
- view.viewTreeObserver.dispatchOnGlobalLayout()
112
- Choreographer.getInstance().postFrameCallback(this)
114
+ if (view.isAttachedToWindow) {
115
+ manuallyLayoutChildren(view)
116
+ view.viewTreeObserver.dispatchOnGlobalLayout()
117
+ Choreographer.getInstance().postFrameCallback(this)
118
+ }
113
119
  }
114
120
  })
115
121
  }
@@ -118,10 +124,6 @@ class FWStoryBlockManager(
118
124
  * Layout all children properly
119
125
  */
120
126
  private fun manuallyLayoutChildren(view: View) {
121
- // propWidth and propHeight coming from react-native props
122
- // val width = requireNotNull(propWidth)
123
- // val height = requireNotNull(propHeight)
124
-
125
127
  view.measure(
126
128
  View.MeasureSpec.makeMeasureSpec(view.measuredWidth, View.MeasureSpec.EXACTLY),
127
129
  View.MeasureSpec.makeMeasureSpec(view.measuredHeight, View.MeasureSpec.EXACTLY)
@@ -132,6 +134,7 @@ class FWStoryBlockManager(
132
134
 
133
135
 
134
136
  private fun createFragment(root: FrameLayout, reactNativeViewId: Int?) {
137
+ FWLogUtils.d { "FWStoryBlockManager createFragment, reactNativeViewId = $reactNativeViewId" }
135
138
  reactNativeViewId ?: return
136
139
  val activity = (reactContext.currentActivity as AppCompatActivity?) ?: return
137
140
 
@@ -146,43 +149,37 @@ class FWStoryBlockManager(
146
149
  val fireworkPlayerFragment = FireworkPlayerFragment()
147
150
  this.fireworkPlayerFragment = fireworkPlayerFragment
148
151
 
149
- FWLogUtils.d { "FWStoryBlockManager createFragment doOnAttach before" }
150
- parentView.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
151
- override fun onViewAttachedToWindow(v: View?) {
152
- FWLogUtils.d { "FWStoryBlockManager createFragment doOnAttach" }
153
- // Log.e("isAttachedToWindow", parentView.isAttachedToWindow.toString())
154
- activity.supportFragmentManager
155
- .beginTransaction()
156
- .replace(reactNativeViewId, fireworkPlayerFragment, reactNativeViewId.toString())
157
- .commitNow()
158
- parentView.requestLayout()
159
- // Log.e("isAttachedToWindow", fireworkPlayerFragment.isAdded.toString())
160
- setStoryBlockParameters()
161
- }
162
-
163
- override fun onViewDetachedFromWindow(v: View?) {
152
+ FWLogUtils.d { "FWStoryBlockManager createFragment doOnAttach before, fireworkPlayerFragment.isAdded = ${fireworkPlayerFragment.isAdded}, parentView.isAttachedToWindow = ${parentView.isAttachedToWindow}" }
153
+ if (parentView.isAttachedToWindow) {
154
+ if (fireworkPlayerFragment.isAdded) {
155
+ return
164
156
  }
157
+ activity.supportFragmentManager
158
+ .beginTransaction()
159
+ .replace(reactNativeViewId, fireworkPlayerFragment, reactNativeViewId.toString())
160
+ .commitNow()
161
+ parentView.requestLayout()
162
+ setStoryBlockParameters()
163
+ } else {
164
+ parentView.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
165
+ override fun onViewAttachedToWindow(v: View?) {
166
+ FWLogUtils.d { "FWStoryBlockManager createFragment doOnAttach" }
167
+ if (fireworkPlayerFragment.isAdded) {
168
+ return
169
+ }
170
+ activity.supportFragmentManager
171
+ .beginTransaction()
172
+ .replace(reactNativeViewId, fireworkPlayerFragment, reactNativeViewId.toString())
173
+ .commitNow()
174
+ parentView.requestLayout()
175
+ setStoryBlockParameters()
176
+ }
165
177
 
166
- })
167
-
168
- // activity.lifecycleScope.launch {
169
- //// withContext(Dispatchers.Default) {
170
- //// while (!FwSDK.initialized) {
171
- //// delay(2000)
172
- //// }
173
- //// }
174
- //
175
- // withContext(Dispatchers.Main) {
176
- // if(FwSDK.initialized) {
177
- // delay(2000)
178
- // Log.e("isAttachedToWindow", parentView.isAttachedToWindow.toString())
179
- //// FeedFactory.getVideoFeed(13, FeedType.DISCOVER, null, null)
180
- // fireworkPlayerFragment.setStoryBlockParameters(FeedType.DISCOVER)
181
- //// fireworkPlayerFragment.setParameters(13, null)
182
- // }
183
- // }
184
- // }
178
+ override fun onViewDetachedFromWindow(v: View?) {
179
+ }
185
180
 
181
+ })
182
+ }
186
183
  }
187
184
 
188
185
  private fun addStoryBlockListener(reactContext: ReactApplicationContext) {
@@ -13,4 +13,6 @@ interface FireworkSDKInterface {
13
13
  fun setCustomCTALinkContentPageRouteName(name: String?, promise: Promise)
14
14
  fun setAppComponentName(name: String?, promise: Promise)
15
15
  fun setVideoPlaybackEventEnabled(value: Boolean?)
16
+ fun changeAppLanguage(language: String?, promise: Promise)
17
+ fun restart(promise: Promise)
16
18
  }
@@ -1,11 +1,15 @@
1
1
  package com.fireworksdk.bridge.reactnative.module
2
2
 
3
3
  import android.app.Activity
4
+ import androidx.appcompat.app.AppCompatActivity
4
5
  import com.facebook.react.bridge.*
5
6
  import com.fireworksdk.bridge.FWInitializationProvider
6
7
  import com.fireworksdk.bridge.reactnative.models.FWNavigatorInterface
7
8
  import com.fireworksdk.bridge.reactnative.utils.FWEventUtils
8
9
  import com.fireworksdk.bridge.utils.FWLogUtils
10
+ import com.loopnow.fireworklibrary.baya.ProductListFragment
11
+ import com.loopnow.fireworklibrary.views.BaseVideoViewFragment
12
+ import com.loopnow.fireworklibrary.views.FireworkPlayerFragment
9
13
 
10
14
 
11
15
  class FWNavigatorModule(
@@ -28,6 +32,7 @@ class FWNavigatorModule(
28
32
  }
29
33
 
30
34
  if (isTaskRoot(activity)) {
35
+ closeDialog(activity)
31
36
  promise.resolve(false)
32
37
  return
33
38
  }
@@ -69,6 +74,36 @@ class FWNavigatorModule(
69
74
  return false
70
75
  }
71
76
 
77
+ private fun closeDialog(activity: Activity) {
78
+ // close ProductListFragment
79
+ if (activity is AppCompatActivity) {
80
+ val fragmentList = activity.supportFragmentManager.fragments
81
+ if (fragmentList.isEmpty()) {
82
+ return
83
+ }
84
+ for (fragment in fragmentList) {
85
+ if (fragment !is FireworkPlayerFragment) {
86
+ continue
87
+ }
88
+ val childFragmentList = fragment.childFragmentManager.fragments
89
+ for (childFragment in childFragmentList) {
90
+ if (childFragment !is BaseVideoViewFragment<*>) {
91
+ continue
92
+ }
93
+ val list = childFragment.childFragmentManager.fragments
94
+ for (f in list) {
95
+ if (f !is ProductListFragment) {
96
+ continue
97
+ }
98
+ if (f.isAdded) {
99
+ f.dismiss()
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+
72
107
  override fun getName(): String {
73
108
  return "FWNavigatorModule"
74
109
  }
@@ -1,8 +1,13 @@
1
1
  package com.fireworksdk.bridge.reactnative.module
2
2
 
3
3
  import android.annotation.SuppressLint
4
+ import android.app.Activity
5
+ import android.app.Application
4
6
  import android.content.Intent
5
7
  import android.content.pm.PackageManager
8
+ import android.os.Handler
9
+ import android.os.Looper
10
+ import android.os.Process
6
11
  import android.provider.Settings
7
12
  import androidx.localbroadcastmanager.content.LocalBroadcastManager
8
13
  import com.facebook.react.bridge.*
@@ -20,6 +25,7 @@ import com.fireworksdk.bridge.reactnative.pages.FWContainerActivity
20
25
  import com.fireworksdk.bridge.reactnative.utils.FWEventUtils
21
26
  import com.loopnow.fireworklibrary.*
22
27
  import java.util.*
28
+ import kotlin.system.exitProcess
23
29
 
24
30
 
25
31
  class FireworkSDKModule(
@@ -269,6 +275,55 @@ class FireworkSDKModule(
269
275
  promise.resolve(Arguments.createMap())
270
276
  }
271
277
 
278
+ @ReactMethod
279
+ override fun changeAppLanguage(language: String?, promise: Promise) {
280
+ val activity = FWInitializationProvider.INSTANCE.resumedActivity
281
+ if (activity == null) {
282
+ promise.resolve(false)
283
+ return
284
+ }
285
+ UiThreadUtil.runOnUiThread {
286
+ FWLanguageUtil.changeLanguage(activity, language)
287
+ promise.resolve(true)
288
+ }
289
+ }
290
+
291
+ @ReactMethod
292
+ override fun restart(promise: Promise) {
293
+ val activity: Activity? = FWInitializationProvider.INSTANCE.resumedActivity
294
+ if (activity == null) {
295
+ promise.resolve(false)
296
+ return
297
+ }
298
+ restartApplication(activity.application)
299
+ }
300
+
301
+ private fun recreateActivity(activity: Activity) {
302
+ UiThreadUtil.runOnUiThread {
303
+ activity.recreate()
304
+ }
305
+ }
306
+
307
+ // why delay:
308
+ // 1. must ensure that the data of SharedPreferences has been saved
309
+ // 2. if the restart method is called after the I18nManager.forceRTL(false);, sometimes the forceRTL(false) does not work.
310
+ private fun restartApplication(application: Application) {
311
+ Handler(Looper.getMainLooper()).postDelayed({
312
+ UiThreadUtil.runOnUiThread {
313
+ val intent = application.packageManager
314
+ .getLaunchIntentForPackage(application.packageName)
315
+ intent?.addFlags(
316
+ Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
317
+ or Intent.FLAG_ACTIVITY_CLEAR_TASK
318
+ )
319
+ application.startActivity(intent)
320
+ Process.killProcess(Process.myPid())
321
+ exitProcess(0)
322
+ }
323
+ }, 300)
324
+ }
325
+
326
+
272
327
  @ReactMethod
273
328
  fun addListener(eventName: String?, promise: Promise) {
274
329
  // Set up any upstream listeners or background tasks as necessary
@@ -0,0 +1,72 @@
1
+ package com.fireworksdk.bridge.utils
2
+
3
+ import android.content.Context
4
+ import com.loopnow.fireworklibrary.FwSDK
5
+ import java.util.*
6
+
7
+ object FWLanguageUtil {
8
+
9
+ private var locale: String? = null
10
+ private const val LOCALE_SP = "fw_locale_sp"
11
+ private const val LOCALE_KEY = "fw_locale_key"
12
+
13
+ private fun init(context: Context) {
14
+ locale = context.getSharedPreferences(LOCALE_SP, Context.MODE_PRIVATE)
15
+ .getString(LOCALE_KEY, null)
16
+ }
17
+
18
+ fun changeLanguage(context: Context, l: String?) {
19
+ if (l.isNullOrBlank() || !isValidLocale(l)) {
20
+ return
21
+ }
22
+
23
+ locale = l
24
+ FwSDK.changeAppLocale(context, l)
25
+
26
+ // save to sp
27
+ val sharedPreferences =
28
+ context.getSharedPreferences(LOCALE_SP, Context.MODE_PRIVATE)
29
+ sharedPreferences.edit().apply {
30
+ putString(LOCALE_KEY, l)
31
+ }.apply()
32
+ }
33
+
34
+ fun updateBaseContextLocale(context: Context): Context {
35
+ if (locale.isNullOrBlank()) {
36
+ init(context)
37
+ }
38
+ locale?.let {
39
+ val localeStrings = it.split("-")
40
+ val locale = if (localeStrings.size > 1) {
41
+ Locale(localeStrings[0], localeStrings[1])
42
+ } else {
43
+ Locale(it)
44
+ }
45
+ Locale.setDefault(locale)
46
+
47
+ return updateResourcesLocale(context, locale)
48
+ }
49
+ return updateResourcesLocale(context, Locale.getDefault())
50
+ }
51
+
52
+ private fun updateResourcesLocale(context: Context, locale: Locale): Context {
53
+ val resources = context.resources
54
+ val configuration = resources.configuration
55
+ configuration.setLocale(locale)
56
+ configuration.setLayoutDirection(locale)
57
+ return context.createConfigurationContext(configuration)
58
+ }
59
+
60
+ private fun isValidLocale(locale: String?) : Boolean {
61
+ locale ?: return false
62
+ val list = Locale.getAvailableLocales()
63
+ if (locale.contains("-")) {
64
+ val locales = locale.split("-")
65
+ if (locales.size > 1) {
66
+ return list.contains(Locale(locales[0], locales[1]))
67
+ }
68
+ }
69
+ return list.contains(Locale(locale))
70
+ }
71
+
72
+ }
@@ -73,8 +73,6 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate {
73
73
  let storyBlockVC = StoryBlockViewController(source: source)
74
74
  if self.enablePictureInPicture {
75
75
  self.pipController = PictureInPictureController(storyBlock: storyBlockVC)
76
- } else {
77
- self.pipController = nil
78
76
  }
79
77
 
80
78
  storyBlockVC.delegate = self
@@ -84,13 +82,16 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate {
84
82
 
85
83
  public override func removeFromSuperview() {
86
84
  super.removeFromSuperview()
87
- self.pipController = nil
85
+
86
+ if let pipController = pipController {
87
+ FWPiPManager.shared.addPiPController(pipController)
88
+ self.pipController = nil
89
+ }
88
90
 
89
91
  guard let storyBlockVC = self.storyBlockVC else {
90
92
  return
91
93
  }
92
94
 
93
- storyBlockVC.pause()
94
95
  storyBlockVC.detachFromParent()
95
96
  self.storyBlockVC = nil
96
97
  }
@@ -8,9 +8,6 @@
8
8
  import FireworkVideo
9
9
  import UIKit
10
10
 
11
- let gOnVideoTemporarilyReleasePipController = Notification.Name("gOnVideoTemporarilyReleasePipController")
12
- let gOnVideoRestorePipController = Notification.Name("gOnVideoRestorePipController")
13
-
14
11
  @objc
15
12
  public enum VideoFeedMode: Int {
16
13
  case row, column, grid
@@ -160,7 +157,6 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
160
157
  embed()
161
158
  }
162
159
 
163
- // swiftlint:disable:next function_body_length
164
160
  private func embed() {
165
161
  guard let parentVC = parentViewController else {
166
162
  return
@@ -213,19 +209,6 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
213
209
  NotificationCenter.default.removeObserver(self)
214
210
  if feedViewConfig?.enablePictureInPicture == true {
215
211
  self.pipController = PictureInPictureController(videoFeed: feedVC)
216
- NotificationCenter.default.addObserver(
217
- self,
218
- selector: #selector(onVideoTemporarilyReleasePipController(_:)),
219
- name: gOnVideoTemporarilyReleasePipController,
220
- object: nil
221
- )
222
- NotificationCenter.default.addObserver(
223
- self,
224
- selector: #selector(onVideoRestorePipController(_:)),
225
- name: gOnVideoRestorePipController,
226
- object: nil)
227
- } else {
228
- self.pipController = nil
229
212
  }
230
213
 
231
214
  feedVC.delegate = self
@@ -237,7 +220,10 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate {
237
220
  super.removeFromSuperview()
238
221
  // swiftlint:disable:next notification_center_detachment
239
222
  NotificationCenter.default.removeObserver(self)
240
- self.pipController = nil
223
+ if let pipController = pipController {
224
+ FWPiPManager.shared.addPiPController(pipController)
225
+ self.pipController = nil
226
+ }
241
227
 
242
228
  guard let feedVC = self.feedVC else {
243
229
  return
@@ -331,7 +317,7 @@ extension VideoFeed {
331
317
  return vfcConfig
332
318
  }
333
319
 
334
- // swiftlint:disable:next cyclomatic_complexity
320
+ // swiftlint:disable:next cyclomatic_complexity function_body_length
335
321
  static func convertToVideoPlayerContentConfiguration(
336
322
  _ config: VideoPlayerConfiguration?
337
323
  ) -> VideoPlayerContentConfiguration? {
@@ -388,6 +374,28 @@ extension VideoFeed {
388
374
  vpcConfig.shareButton.behavior.baseURL = URL(string: shareBaseUrl)
389
375
  }
390
376
 
377
+ if let ctaDelay = config.ctaDelay,
378
+ let type = ctaDelay.type,
379
+ let value = ctaDelay.value {
380
+ switch type {
381
+ case .constant:
382
+ vpcConfig.ctaButton.behavior.delay = .constant(value)
383
+ case .percentage:
384
+ vpcConfig.ctaButton.behavior.delay = .percentage(Float(value))
385
+ }
386
+ }
387
+
388
+ if let ctaHighlightDelay = config.ctaHighlightDelay,
389
+ let type = ctaHighlightDelay.type,
390
+ let value = ctaHighlightDelay.value {
391
+ switch type {
392
+ case .constant:
393
+ vpcConfig.ctaButton.behavior.highlightDelay = .constant(value)
394
+ case .percentage:
395
+ vpcConfig.ctaButton.behavior.highlightDelay = .percentage(Float(value))
396
+ }
397
+ }
398
+
391
399
  return vpcConfig
392
400
  }
393
401
 
@@ -420,22 +428,6 @@ extension VideoFeed {
420
428
 
421
429
  return videoConfig
422
430
  }
423
-
424
- @objc private func onVideoTemporarilyReleasePipController(_ notification: NSNotification) {
425
- self.pipController = nil
426
- }
427
-
428
- @objc private func onVideoRestorePipController(_ notification: NSNotification) {
429
- guard let feedVC = feedVC else {
430
- return
431
- }
432
-
433
- guard feedViewConfig?.enablePictureInPicture == true else {
434
- return
435
- }
436
-
437
- self.pipController = PictureInPictureController(videoFeed: feedVC)
438
- }
439
431
  }
440
432
 
441
433
  // swiftlint:disable file_length
@@ -17,6 +17,8 @@ public class VideoPlayerConfiguration: NSObject, Codable {
17
17
  var showMuteButton: Bool?
18
18
  var launchBehavior: VideoLaunchBehavior?
19
19
  var showBranding: Bool?
20
+ var ctaDelay: VideoPlayerCTADelay?
21
+ var ctaHighlightDelay: VideoPlayerCTADelay?
20
22
 
21
23
  public enum VideoPlayerStyle: String, Codable {
22
24
  case full, fit
@@ -35,4 +37,13 @@ public class VideoPlayerConfiguration: NSObject, Codable {
35
37
  public enum VideoLaunchBehavior: String, Codable {
36
38
  case `default`, muteOnFirstLaunch
37
39
  }
40
+
41
+ public enum VideoPlayerCTADelayType: String, Codable {
42
+ case constant, percentage
43
+ }
44
+
45
+ public class VideoPlayerCTADelay: NSObject, Codable {
46
+ var type: VideoPlayerCTADelayType?
47
+ var value: Double?
48
+ }
38
49
  }
@@ -8,6 +8,12 @@
8
8
 
9
9
  /* Begin PBXBuildFile section */
10
10
  89335CA628E29D3A00B84BC7 /* TrackPurchaseParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89335CA528E29D3A00B84BC7 /* TrackPurchaseParameters.swift */; };
11
+ 8953CF5E2993E0D200F7413E /* UINavigationController+FWSwizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8953CF5D2993E0D200F7413E /* UINavigationController+FWSwizzle.swift */; };
12
+ 8953CF602993E3B200F7413E /* FWSwizzleUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8953CF5F2993E3B200F7413E /* FWSwizzleUtil.swift */; };
13
+ 8953CF622993E44E00F7413E /* DispatchQueue+FWOnce.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8953CF612993E44E00F7413E /* DispatchQueue+FWOnce.swift */; };
14
+ 8953CF642993EF8200F7413E /* UIButton+FWSwizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8953CF632993EF8200F7413E /* UIButton+FWSwizzle.swift */; };
15
+ 8953CF662993F13800F7413E /* FWPiPManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8953CF652993F13800F7413E /* FWPiPManager.swift */; };
16
+ 8953CF6C2993FAAB00F7413E /* FWSwizzleLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8953CF6B2993FAAB00F7413E /* FWSwizzleLoader.m */; };
11
17
  896A8EB928E3DCCA007E51F8 /* AdConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896A8EB828E3DCCA007E51F8 /* AdConfiguration.swift */; };
12
18
  8975235E2817DEEE0070EBB6 /* VideoFeedManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897523592817DEEE0070EBB6 /* VideoFeedManager.swift */; };
13
19
  8975235F2817DEEE0070EBB6 /* VideoFeedConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8975235A2817DEEE0070EBB6 /* VideoFeedConfiguration.swift */; };
@@ -39,9 +45,6 @@
39
45
  8975239E2817DEF80070EBB6 /* FireworkSDKModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 897523832817DEF80070EBB6 /* FireworkSDKModule.m */; };
40
46
  8975239F2817DEF80070EBB6 /* LiveStreamModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897523852817DEF80070EBB6 /* LiveStreamModule.swift */; };
41
47
  897523A02817DEF80070EBB6 /* LiveStreamModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 897523862817DEF80070EBB6 /* LiveStreamModule.m */; };
42
- 8977F48528C99340008CC888 /* UINavigationController+FWSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 8977F48428C99340008CC888 /* UINavigationController+FWSwizzle.m */; };
43
- 899703B5296D89B600571B4F /* FWNavigatorUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 899703B4296D89B600571B4F /* FWNavigatorUtils.swift */; };
44
- 899703B8296D9C5C00571B4F /* AVPlayer+FWSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 899703B7296D9C5C00571B4F /* AVPlayer+FWSwizzle.m */; };
45
48
  89DF27DD28A53A77003F3CCB /* StoryBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89DF27DA28A53A77003F3CCB /* StoryBlock.swift */; };
46
49
  89DF27DE28A53A77003F3CCB /* StoryBlockManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89DF27DB28A53A77003F3CCB /* StoryBlockManager.swift */; };
47
50
  89DF27DF28A53A77003F3CCB /* StoryBlockManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 89DF27DC28A53A77003F3CCB /* StoryBlockManager.m */; };
@@ -64,6 +67,13 @@
64
67
  134814201AA4EA6300B7C361 /* libFireworkSdk.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFireworkSdk.a; sourceTree = BUILT_PRODUCTS_DIR; };
65
68
  1F6F718A2771B48100224AF3 /* FireworkSdk-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FireworkSdk-Bridging-Header.h"; sourceTree = "<group>"; };
66
69
  89335CA528E29D3A00B84BC7 /* TrackPurchaseParameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackPurchaseParameters.swift; sourceTree = "<group>"; };
70
+ 8953CF5D2993E0D200F7413E /* UINavigationController+FWSwizzle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+FWSwizzle.swift"; sourceTree = "<group>"; };
71
+ 8953CF5F2993E3B200F7413E /* FWSwizzleUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FWSwizzleUtil.swift; sourceTree = "<group>"; };
72
+ 8953CF612993E44E00F7413E /* DispatchQueue+FWOnce.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+FWOnce.swift"; sourceTree = "<group>"; };
73
+ 8953CF632993EF8200F7413E /* UIButton+FWSwizzle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+FWSwizzle.swift"; sourceTree = "<group>"; };
74
+ 8953CF652993F13800F7413E /* FWPiPManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FWPiPManager.swift; sourceTree = "<group>"; };
75
+ 8953CF6A2993FAAB00F7413E /* FWSwizzleLoader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FWSwizzleLoader.h; sourceTree = "<group>"; };
76
+ 8953CF6B2993FAAB00F7413E /* FWSwizzleLoader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FWSwizzleLoader.m; sourceTree = "<group>"; };
67
77
  896A8EB828E3DCCA007E51F8 /* AdConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdConfiguration.swift; sourceTree = "<group>"; };
68
78
  897523592817DEEE0070EBB6 /* VideoFeedManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoFeedManager.swift; sourceTree = "<group>"; };
69
79
  8975235A2817DEEE0070EBB6 /* VideoFeedConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoFeedConfiguration.swift; sourceTree = "<group>"; };
@@ -96,11 +106,6 @@
96
106
  897523832817DEF80070EBB6 /* FireworkSDKModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FireworkSDKModule.m; sourceTree = "<group>"; };
97
107
  897523852817DEF80070EBB6 /* LiveStreamModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LiveStreamModule.swift; sourceTree = "<group>"; };
98
108
  897523862817DEF80070EBB6 /* LiveStreamModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LiveStreamModule.m; sourceTree = "<group>"; };
99
- 8977F48328C99340008CC888 /* UINavigationController+FWSwizzle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UINavigationController+FWSwizzle.h"; sourceTree = "<group>"; };
100
- 8977F48428C99340008CC888 /* UINavigationController+FWSwizzle.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UINavigationController+FWSwizzle.m"; sourceTree = "<group>"; };
101
- 899703B4296D89B600571B4F /* FWNavigatorUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FWNavigatorUtils.swift; sourceTree = "<group>"; };
102
- 899703B6296D9C5C00571B4F /* AVPlayer+FWSwizzle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AVPlayer+FWSwizzle.h"; sourceTree = "<group>"; };
103
- 899703B7296D9C5C00571B4F /* AVPlayer+FWSwizzle.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "AVPlayer+FWSwizzle.m"; sourceTree = "<group>"; };
104
109
  89DF27DA28A53A77003F3CCB /* StoryBlock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryBlock.swift; sourceTree = "<group>"; };
105
110
  89DF27DB28A53A77003F3CCB /* StoryBlockManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryBlockManager.swift; sourceTree = "<group>"; };
106
111
  89DF27DC28A53A77003F3CCB /* StoryBlockManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StoryBlockManager.m; sourceTree = "<group>"; };
@@ -158,15 +163,17 @@
158
163
  897523642817DEF80070EBB6 /* Utils */ = {
159
164
  isa = PBXGroup;
160
165
  children = (
166
+ 8953CF612993E44E00F7413E /* DispatchQueue+FWOnce.swift */,
167
+ 8953CF5F2993E3B200F7413E /* FWSwizzleUtil.swift */,
161
168
  897523652817DEF80070EBB6 /* UIViewController+AttachChild.swift */,
162
169
  897523662817DEF80070EBB6 /* UIView+Constraints.swift */,
163
170
  897523672817DEF80070EBB6 /* String+Color.swift */,
164
171
  897523682817DEF80070EBB6 /* UIView+ParentViewController.swift */,
165
- 8977F48328C99340008CC888 /* UINavigationController+FWSwizzle.h */,
166
- 8977F48428C99340008CC888 /* UINavigationController+FWSwizzle.m */,
167
- 899703B4296D89B600571B4F /* FWNavigatorUtils.swift */,
168
- 899703B6296D9C5C00571B4F /* AVPlayer+FWSwizzle.h */,
169
- 899703B7296D9C5C00571B4F /* AVPlayer+FWSwizzle.m */,
172
+ 8953CF5D2993E0D200F7413E /* UINavigationController+FWSwizzle.swift */,
173
+ 8953CF632993EF8200F7413E /* UIButton+FWSwizzle.swift */,
174
+ 8953CF652993F13800F7413E /* FWPiPManager.swift */,
175
+ 8953CF6A2993FAAB00F7413E /* FWSwizzleLoader.h */,
176
+ 8953CF6B2993FAAB00F7413E /* FWSwizzleLoader.m */,
170
177
  );
171
178
  path = Utils;
172
179
  sourceTree = "<group>";
@@ -314,23 +321,24 @@
314
321
  buildActionMask = 2147483647;
315
322
  files = (
316
323
  8975238A2817DEF80070EBB6 /* UIView+ParentViewController.swift in Sources */,
317
- 8977F48528C99340008CC888 /* UINavigationController+FWSwizzle.m in Sources */,
318
- 899703B8296D9C5C00571B4F /* AVPlayer+FWSwizzle.m in Sources */,
319
324
  8975239B2817DEF80070EBB6 /* FireworkSDKModule.swift in Sources */,
320
325
  897523952817DEF80070EBB6 /* ShoppingModule.m in Sources */,
321
326
  89335CA628E29D3A00B84BC7 /* TrackPurchaseParameters.swift in Sources */,
322
- 899703B5296D89B600571B4F /* FWNavigatorUtils.swift in Sources */,
323
327
  897523A02817DEF80070EBB6 /* LiveStreamModule.m in Sources */,
324
328
  8975238E2817DEF80070EBB6 /* FireworkSDK+Json.swift in Sources */,
329
+ 8953CF5E2993E0D200F7413E /* UINavigationController+FWSwizzle.swift in Sources */,
325
330
  89DF27E128A53A89003F3CCB /* RCTConvert+StoryBlock.swift in Sources */,
331
+ 8953CF6C2993FAAB00F7413E /* FWSwizzleLoader.m in Sources */,
326
332
  8975235F2817DEEE0070EBB6 /* VideoFeedConfiguration.swift in Sources */,
327
333
  897523612817DEEE0070EBB6 /* VideoPlayerConfiguration.swift in Sources */,
328
334
  897523972817DEF80070EBB6 /* Product.swift in Sources */,
329
335
  89DF27DD28A53A77003F3CCB /* StoryBlock.swift in Sources */,
330
336
  89DF27DF28A53A77003F3CCB /* StoryBlockManager.m in Sources */,
337
+ 8953CF642993EF8200F7413E /* UIButton+FWSwizzle.swift in Sources */,
331
338
  897523932817DEF80070EBB6 /* FWNavigatorModule.m in Sources */,
332
339
  897523922817DEF80070EBB6 /* FWNavigatorModule.swift in Sources */,
333
340
  897523872817DEF80070EBB6 /* UIViewController+AttachChild.swift in Sources */,
341
+ 8953CF662993F13800F7413E /* FWPiPManager.swift in Sources */,
334
342
  897523902817DEF80070EBB6 /* FWNavigatorProtocol.swift in Sources */,
335
343
  897523882817DEF80070EBB6 /* UIView+Constraints.swift in Sources */,
336
344
  897523982817DEF80070EBB6 /* ShoppingModule.swift in Sources */,
@@ -346,7 +354,9 @@
346
354
  8975235E2817DEEE0070EBB6 /* VideoFeedManager.swift in Sources */,
347
355
  8975239D2817DEF80070EBB6 /* FireworkSDKModule+CTA.swift in Sources */,
348
356
  89DF27DE28A53A77003F3CCB /* StoryBlockManager.swift in Sources */,
357
+ 8953CF622993E44E00F7413E /* DispatchQueue+FWOnce.swift in Sources */,
349
358
  897523892817DEF80070EBB6 /* String+Color.swift in Sources */,
359
+ 8953CF602993E3B200F7413E /* FWSwizzleUtil.swift in Sources */,
350
360
  897523622817DEEE0070EBB6 /* VideoFeedManager.m in Sources */,
351
361
  897523912817DEF80070EBB6 /* FWNavigatorContainerViewController.swift in Sources */,
352
362
  8975238F2817DEF80070EBB6 /* FireworkEventName.swift in Sources */,
@@ -142,20 +142,13 @@ class FWNavigatorModule: RCTEventEmitter, FWNavigator {
142
142
  } else if let presentedVC = RCTPresentedViewController(),
143
143
  let presentingVC = presentedVC.presentingViewController,
144
144
  presentingVC.presentingViewController == RCTKeyWindow()?.rootViewController {
145
- let closeButton = self.getCloseButton(view: presentingVC.view)
146
- if closeButton == nil {
147
- FWNavigatorUtils.shared.shouldDisablePlay = true
148
- }
149
145
  presentedVC.dismiss(animated: false) {
150
146
  DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.1) {
151
- FWNavigatorUtils.shared.shouldDisablePlay = false
152
- if closeButton != nil {
153
- closeButton!.sendActions(for: .touchUpInside)
147
+ if let closeButton = self.getCloseButton(view: presentingVC.view) {
148
+ closeButton.sendActions(for: .touchUpInside)
154
149
  resolver(true)
155
150
  } else {
156
- NotificationCenter.default.post(name: gOnVideoTemporarilyReleasePipController, object: nil)
157
151
  presentingVC.dismiss(animated: true) {
158
- NotificationCenter.default.post(name: gOnVideoRestorePipController, object: nil)
159
152
  resolver(true)
160
153
  }
161
154
  }
@@ -167,9 +160,7 @@ class FWNavigatorModule: RCTEventEmitter, FWNavigator {
167
160
  closeButton.sendActions(for: .touchUpInside)
168
161
  resolver(true)
169
162
  } else {
170
- NotificationCenter.default.post(name: gOnVideoTemporarilyReleasePipController, object: nil)
171
163
  presentedVC.dismiss(animated: true) {
172
- NotificationCenter.default.post(name: gOnVideoRestorePipController, object: nil)
173
164
  resolver(true)
174
165
  }
175
166
  }
@@ -127,5 +127,7 @@ extension FireworkSDKModule: FireworkVideoFeedDelegate {
127
127
 
128
128
  sendEvent(
129
129
  withName: FWEventName.videoFeedClick.rawValue, body: ["info": eventDetails.jsObject])
130
+
131
+ FWPiPManager.shared.removeAllPiPControllers()
130
132
  }
131
133
  }