react-native-firework-sdk 1.6.2 → 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 (53) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FireworkSDKInterface.kt +2 -0
  3. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +55 -0
  4. package/android/src/main/java/com/fireworksdk/bridge/utils/FWLanguageUtil.kt +72 -0
  5. package/ios/Components/StoryBlock.swift +5 -4
  6. package/ios/Components/VideoFeed.swift +27 -35
  7. package/ios/Components/VideoPlayerConfiguration.swift +11 -0
  8. package/ios/FireworkSdk.xcodeproj/project.pbxproj +26 -16
  9. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +2 -11
  10. package/ios/Modules/FireworkSDKModule/FireworkSDKModule+EventTracking.swift +2 -0
  11. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +1 -1
  12. package/ios/Utils/DispatchQueue+FWOnce.swift +32 -0
  13. package/ios/Utils/FWPiPManager.swift +24 -0
  14. package/ios/Utils/FWSwizzleLoader.h +15 -0
  15. package/ios/Utils/FWSwizzleLoader.m +17 -0
  16. package/ios/Utils/FWSwizzleUtil.swift +29 -0
  17. package/ios/Utils/UIButton+FWSwizzle.swift +33 -0
  18. package/ios/Utils/UINavigationController+FWSwizzle.swift +30 -0
  19. package/ios/react_native_firework_sdk.h +1 -2
  20. package/lib/commonjs/FireworkSDK.js +21 -1
  21. package/lib/commonjs/FireworkSDK.js.map +1 -1
  22. package/lib/commonjs/VideoShopping.js +7 -7
  23. package/lib/commonjs/VideoShopping.js.map +1 -1
  24. package/lib/commonjs/components/VideoFeed.js +3 -1
  25. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  26. package/lib/commonjs/index.js.map +1 -1
  27. package/lib/commonjs/modules/FireworkSDKModule.js.map +1 -1
  28. package/lib/module/FireworkSDK.js +21 -1
  29. package/lib/module/FireworkSDK.js.map +1 -1
  30. package/lib/module/VideoShopping.js +7 -7
  31. package/lib/module/VideoShopping.js.map +1 -1
  32. package/lib/module/components/VideoFeed.js +3 -1
  33. package/lib/module/components/VideoFeed.js.map +1 -1
  34. package/lib/module/index.js.map +1 -1
  35. package/lib/module/modules/FireworkSDKModule.js.map +1 -1
  36. package/lib/typescript/FireworkSDK.d.ts +7 -3
  37. package/lib/typescript/VideoShopping.d.ts +7 -7
  38. package/lib/typescript/index.d.ts +3 -3
  39. package/lib/typescript/models/VideoPlayerConfiguration.d.ts +19 -0
  40. package/lib/typescript/modules/FireworkSDKModule.d.ts +2 -0
  41. package/package.json +1 -1
  42. package/react-native-firework-sdk.podspec +2 -4
  43. package/src/FireworkSDK.ts +18 -4
  44. package/src/VideoShopping.ts +7 -7
  45. package/src/components/VideoFeed.tsx +2 -0
  46. package/src/index.tsx +4 -2
  47. package/src/models/VideoPlayerConfiguration.ts +20 -0
  48. package/src/modules/FireworkSDKModule.ts +2 -0
  49. package/ios/Utils/AVPlayer+FWSwizzle.h +0 -17
  50. package/ios/Utils/AVPlayer+FWSwizzle.m +0 -50
  51. package/ios/Utils/FWNavigatorUtils.swift +0 -26
  52. package/ios/Utils/UINavigationController+FWSwizzle.h +0 -16
  53. 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
@@ -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,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
  }
@@ -56,7 +56,7 @@ class FireworkSDKModule: RCTEventEmitter, FireworkVideoSDKDelegate {
56
56
  return
57
57
  }
58
58
 
59
- var vpcConfig = RCTConvert.videoPlayerContentConfiguration(config)
59
+ let vpcConfig = RCTConvert.videoPlayerContentConfiguration(config)
60
60
 
61
61
  var feedContentConfig = VideoFeedContentConfiguration()
62
62
  if let vpcConfig = vpcConfig {
@@ -0,0 +1,32 @@
1
+ //
2
+ // DispatchQueue+FWOnce.swift
3
+ //
4
+ // Created by Jeff Zheng on 2022/3/1.
5
+ //
6
+
7
+ import Foundation
8
+
9
+ extension DispatchQueue {
10
+ private static var _onceContainer = [String]()
11
+
12
+ /// Execute a block only once.
13
+ public class func fw_once(
14
+ file: String = #file, function: String = #function, line: Int = #line, block: () -> Void
15
+ ) {
16
+ let token = file + ":" + function + ":" + String(line)
17
+ fw_once(token: token, block: block)
18
+ }
19
+
20
+ /// Execute a block only once.
21
+ public class func fw_once(token: String, block: () -> Void) {
22
+ objc_sync_enter(self)
23
+ defer { objc_sync_exit(self) }
24
+
25
+ guard !_onceContainer.contains(token) else {
26
+ return
27
+ }
28
+
29
+ _onceContainer.append(token)
30
+ block()
31
+ }
32
+ }
@@ -0,0 +1,24 @@
1
+ //
2
+ // FWPiPManager.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/8.
5
+ //
6
+
7
+ import Foundation
8
+ import FireworkVideo
9
+
10
+ class FWPiPManager {
11
+ static let shared = FWPiPManager()
12
+ // store the pipController corresponding to Video Feed or Story block being removed
13
+ var pipControllerList: [PictureInPictureController] = []
14
+
15
+ private init() {}
16
+
17
+ func addPiPController(_ pipController: PictureInPictureController) {
18
+ pipControllerList.append(pipController)
19
+ }
20
+
21
+ func removeAllPiPControllers() {
22
+ pipControllerList.removeAll()
23
+ }
24
+ }
@@ -0,0 +1,15 @@
1
+ //
2
+ // FWSwizzleLoader.h
3
+ //
4
+ // Created by linjie jiang on 2023/2/8.
5
+ //
6
+
7
+ #import <UIKit/UIKit.h>
8
+
9
+ NS_ASSUME_NONNULL_BEGIN
10
+
11
+ @interface FWSwizzleLoader : NSObject
12
+
13
+ @end
14
+
15
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,17 @@
1
+ //
2
+ // FWSwizzleLoader.m
3
+ //
4
+ // Created by linjie jiang on 2023/2/8.
5
+ //
6
+
7
+ #import "FWSwizzleLoader.h"
8
+ #import "react_native_firework_sdk-Swift.h"
9
+
10
+ @implementation FWSwizzleLoader
11
+
12
+ + (void)load {
13
+ [UINavigationController fw_swizzleMethods];
14
+ [UIButton fw_swizzleMethods];
15
+ }
16
+
17
+ @end
@@ -0,0 +1,29 @@
1
+ //
2
+ // FWSwizzleUtil.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/7.
5
+ //
6
+
7
+ import Foundation
8
+
9
+ class FWSwizzleUtil {
10
+ static func swizzleSelector(cls: AnyClass, orginalSelector: Selector, customSelector: Selector) {
11
+ guard let orginalMethod = class_getInstanceMethod(cls, orginalSelector) else { return }
12
+ guard let customMethod = class_getInstanceMethod(cls, customSelector) else { return }
13
+
14
+ if class_addMethod(
15
+ cls,
16
+ orginalSelector,
17
+ method_getImplementation(customMethod),
18
+ method_getTypeEncoding(customMethod)) {
19
+ class_replaceMethod(
20
+ cls,
21
+ customSelector,
22
+ method_getImplementation(orginalMethod),
23
+ method_getTypeEncoding(orginalMethod)
24
+ )
25
+ } else {
26
+ method_exchangeImplementations(orginalMethod, customMethod)
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,33 @@
1
+ //
2
+ // UIButton+FWSwizzle.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/8.
5
+ //
6
+
7
+ import UIKit
8
+ import FireworkVideo
9
+
10
+ extension UIButton {
11
+ @objc public static func fw_swizzleMethods() {
12
+ DispatchQueue.fw_once {
13
+ FWSwizzleUtil.swizzleSelector(
14
+ cls: self,
15
+ orginalSelector: #selector(sendAction(_:to:for:)),
16
+ customSelector: #selector(fw_sendAction(_:to:for:))
17
+ )
18
+ }
19
+ }
20
+
21
+ @objc func fw_sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
22
+ if let targetImage = self.image(for: .normal) {
23
+ let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
24
+ let closeImage = UIImage(named: "closeX", in: iOSSDKBundle, compatibleWith: nil)
25
+ if targetImage.isEqual(closeImage) {
26
+ DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.1) {
27
+ FWPiPManager.shared.removeAllPiPControllers()
28
+ }
29
+ }
30
+ }
31
+ self.fw_sendAction(action, to: target, for: event)
32
+ }
33
+ }