react-native-firework-sdk 2.12.0 → 2.13.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 (39) hide show
  1. package/android/build.gradle +3 -2
  2. package/android/gradle.properties +4 -3
  3. package/android/src/main/AndroidManifest.xml +14 -0
  4. package/android/src/main/java/com/fireworksdk/bridge/FWInitializationProvider.kt +4 -0
  5. package/android/src/main/java/com/fireworksdk/bridge/components/storyblock/StoryBlockFragment.kt +1 -2
  6. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerLogoConfigurationModel.kt +1 -0
  7. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerLogoConfigurationModelDeserializer.kt +3 -0
  8. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerLogoConfigurationModelSerializer.kt +2 -0
  9. package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FWNavigatorInterface.kt +2 -0
  10. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWNavigatorModule.kt +26 -0
  11. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +2 -2
  12. package/android/src/main/java/com/fireworksdk/bridge/utils/FWConfigUtil.kt +21 -2
  13. package/android/src/main/java/com/fireworksdk/bridge/utils/FWModelUtils.kt +9 -9
  14. package/ios/Components/StoryBlock.swift +5 -8
  15. package/ios/Components/VideoFeed.swift +1 -5
  16. package/ios/FireworkSdk.xcodeproj/project.pbxproj +4 -0
  17. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +2 -0
  18. package/ios/Utils/Extensions/UIWindowScene+Swizzle.swift +33 -0
  19. package/lib/commonjs/components/VideoFeed.js +15 -6
  20. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  21. package/lib/commonjs/index.js.map +1 -1
  22. package/lib/commonjs/models/VideoPlayerLivestreamCountdownTimerTheme.js +2 -0
  23. package/lib/commonjs/models/VideoPlayerLivestreamCountdownTimerTheme.js.map +1 -0
  24. package/lib/module/components/VideoFeed.js +15 -5
  25. package/lib/module/components/VideoFeed.js.map +1 -1
  26. package/lib/module/index.js.map +1 -1
  27. package/lib/module/models/VideoPlayerLivestreamCountdownTimerTheme.js +2 -0
  28. package/lib/module/models/VideoPlayerLivestreamCountdownTimerTheme.js.map +1 -0
  29. package/lib/typescript/index.d.ts +2 -1
  30. package/lib/typescript/models/ReplayBadgeConfiguration.d.ts +1 -1
  31. package/lib/typescript/models/StoryBlockConfiguration.d.ts +0 -2
  32. package/lib/typescript/models/VideoPlayerLivestreamCountdownTimerTheme.d.ts +1 -0
  33. package/package.json +1 -1
  34. package/react-native-firework-sdk.podspec +1 -1
  35. package/src/components/VideoFeed.tsx +13 -6
  36. package/src/index.ts +2 -0
  37. package/src/models/ReplayBadgeConfiguration.ts +1 -1
  38. package/src/models/StoryBlockConfiguration.ts +0 -2
  39. package/src/models/VideoPlayerLivestreamCountdownTimerTheme.ts +1 -0
@@ -5,7 +5,6 @@ buildscript {
5
5
  repositories {
6
6
  google()
7
7
  mavenCentral()
8
- mavenLocal()
9
8
  }
10
9
 
11
10
  dependencies {
@@ -35,6 +34,7 @@ android {
35
34
  defaultConfig {
36
35
  minSdkVersion getExtOrIntegerDefault('minSdkVersion')
37
36
  targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
37
+ manifestPlaceholders["fw_player_launch_mode"] = getExtOrDefault('fwPlayerLaunchMode')
38
38
  }
39
39
 
40
40
  // LOG_LEVEL: VERBOSE(2), DEBUG(3), INFO(4), WARN(5), ERROR(6), ASSERT(7)
@@ -61,9 +61,9 @@ android {
61
61
  }
62
62
 
63
63
  repositories {
64
+ mavenLocal()
64
65
  mavenCentral()
65
66
  google()
66
- mavenLocal()
67
67
 
68
68
  maven {
69
69
  setUrl("https://s01.oss.sonatype.org/content/repositories/snapshots/")
@@ -144,5 +144,6 @@ dependencies {
144
144
  def fireworkSdkVersion = getExtOrDefault('fwNativeVersion')
145
145
  implementation "com.firework:sdk:$fireworkSdkVersion"
146
146
  implementation "com.firework.feature:uiKit:$fireworkSdkVersion"
147
+ implementation "com.firework.feature.player:pager:$fireworkSdkVersion"
147
148
  }
148
149
 
@@ -1,8 +1,9 @@
1
- android.useAndroidX=true
2
1
  android.enableJetifier=true
2
+ android.useAndroidX=true
3
3
  org.gradle.jvmargs=-Xmx1536M
4
- FireworkSDK_kotlinVersion=1.6.10
4
+ FireworkSDK_kotlinVersion=1.8.22
5
5
  FireworkSDK_minSdkVersion=21
6
6
  FireworkSDK_compileSdkVersion=33
7
7
  FireworkSDK_targetSdkVersion=33
8
- FireworkSDK_fwNativeVersion=6.9.3
8
+ FireworkSDK_fwPlayerLaunchMode=singleTask
9
+ FireworkSDK_fwNativeVersion=6.10.2
@@ -1,4 +1,5 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ xmlns:tools="http://schemas.android.com/tools"
2
3
  package="com.fireworksdk.bridge">
3
4
 
4
5
  <uses-permission android:name="android.permission.INTERNET" />
@@ -23,6 +24,19 @@
23
24
  android:name="Firework:RecyclerViewRequestLayoutEnable"
24
25
  android:value="true" />
25
26
 
27
+ <activity
28
+ android:name="com.firework.player.pager.PlayerActivity"
29
+ android:autoRemoveFromRecents="true"
30
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
31
+ android:exported="true"
32
+ android:launchMode="${fw_player_launch_mode}"
33
+ android:screenOrientation="portrait"
34
+ android:supportsPictureInPicture="true"
35
+ android:theme="@style/FwPlayerPagerPlayerActivity"
36
+ android:windowSoftInputMode="adjustPan"
37
+ tools:replace="android:launchMode"
38
+ tools:targetApi="n" />
39
+
26
40
  </application>
27
41
 
28
42
  </manifest>
@@ -14,6 +14,7 @@ class FWInitializationProvider: ContentProvider() {
14
14
 
15
15
  var application: Application? = null
16
16
  var resumedActivity by weakProperty<Activity?>()
17
+ var mainActivity by weakProperty<Activity?>()
17
18
 
18
19
  override fun onCreate(): Boolean {
19
20
  sInstance = this
@@ -36,6 +37,9 @@ class FWInitializationProvider: ContentProvider() {
36
37
 
37
38
  override fun onActivityResumed(activity: Activity) {
38
39
  resumedActivity = activity
40
+ if (mainActivity == null) { // only set once
41
+ mainActivity = activity
42
+ }
39
43
  }
40
44
 
41
45
  override fun onActivityPaused(activity: Activity) {
@@ -119,8 +119,7 @@ class StoryBlockFragment : FWBaseFragment() {
119
119
  childFragmentManager,
120
120
  viewLifecycleOwner,
121
121
  viewOptionsBuilder.build(),
122
- FWGlobalDataUtil.pauseWhenNotVisible,
123
- videoFeedPropsModel?.videoPlayerConfiguration?.countdownTimerConfiguration?.isHidden == false
122
+ FWGlobalDataUtil.pauseWhenNotVisible
124
123
  )
125
124
  isStoryBlockInitializer = true
126
125
 
@@ -5,4 +5,5 @@ import com.fireworksdk.bridge.models.enums.FWVideoPlayerLogoOption
5
5
  data class FWVideoPlayerLogoConfigurationModel(
6
6
  val option: FWVideoPlayerLogoOption?,
7
7
  val encodedId: String?,
8
+ val isClickable: Boolean?
8
9
  )
@@ -7,16 +7,19 @@ object FWVideoPlayerLogoConfigurationModelDeserializer {
7
7
 
8
8
  private const val OPTION_KEY = "option"
9
9
  private const val ENCODED_ID_KEY = "encodedId"
10
+ private const val IS_CLICKABLE = "isClickable"
10
11
 
11
12
  fun deserialize(responseJson: JSONObject?): FWVideoPlayerLogoConfigurationModel? {
12
13
  responseJson ?: return null
13
14
 
14
15
  val option = if (responseJson.has(OPTION_KEY)) responseJson.optString(OPTION_KEY) else null
15
16
  val encodedId = if (responseJson.has(ENCODED_ID_KEY)) responseJson.optString(ENCODED_ID_KEY) else null
17
+ val isClickable = if (responseJson.has(IS_CLICKABLE)) responseJson.optBoolean(IS_CLICKABLE) else null
16
18
 
17
19
  return FWVideoPlayerLogoConfigurationModel(
18
20
  option = if (!option.isNullOrBlank()) FWVideoPlayerLogoOption.deserialize(option) else null,
19
21
  encodedId = encodedId,
22
+ isClickable = isClickable
20
23
  )
21
24
  }
22
25
 
@@ -7,12 +7,14 @@ object FWVideoPlayerLogoConfigurationModelSerializer {
7
7
 
8
8
  private const val OPTION_KEY = "option"
9
9
  private const val ENCODED_ID_KEY = "encodedId"
10
+ private const val IS_CLICKABLE = "isClickable"
10
11
 
11
12
  fun serialize(model: FWVideoPlayerLogoConfigurationModel?): JSONObject? {
12
13
  model ?: return null
13
14
  val jsonObject = JSONObject()
14
15
  jsonObject.put(OPTION_KEY, FWVideoPlayerLogoOption.serialize(model.option))
15
16
  jsonObject.put(ENCODED_ID_KEY, model.encodedId)
17
+ jsonObject.put(IS_CLICKABLE, model.isClickable)
16
18
  return jsonObject
17
19
  }
18
20
  }
@@ -11,4 +11,6 @@ interface FWNavigatorInterface {
11
11
  fun canPopNativeContainer(promise: Promise)
12
12
  fun startFloatingPlayer(promise: Promise)
13
13
  fun stopFloatingPlayer(promise: Promise)
14
+ fun bringRNContainerToTop(promise: Promise)
15
+ fun bringRNContainerToBottom(promise: Promise)
14
16
  }
@@ -1,7 +1,9 @@
1
1
  package com.fireworksdk.bridge.reactnative.module
2
2
 
3
3
  import android.app.Activity
4
+ import android.content.Intent
4
5
  import com.facebook.react.bridge.*
6
+ import com.firework.player.pager.PlayerActivity
5
7
  import com.firework.sdk.FireworkSdk
6
8
  import com.fireworksdk.bridge.FWInitializationProvider
7
9
  import com.fireworksdk.bridge.reactnative.models.FWNavigatorInterface
@@ -85,6 +87,30 @@ class FWNavigatorModule(
85
87
  promise.resolve(true)
86
88
  }
87
89
 
90
+ @ReactMethod
91
+ override fun bringRNContainerToTop(promise: Promise) {
92
+ // reorder MainActivity to front
93
+ val mainActivity = FWInitializationProvider.INSTANCE.mainActivity
94
+ mainActivity?.let { mActivity ->
95
+ val resumedActivity = FWInitializationProvider.INSTANCE.resumedActivity
96
+ resumedActivity?.let { rActivity ->
97
+ rActivity.startActivity(
98
+ Intent(rActivity, mActivity::class.java)
99
+ .addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
100
+ )
101
+ }
102
+ }
103
+ }
104
+
105
+ @ReactMethod
106
+ override fun bringRNContainerToBottom(promise: Promise) {
107
+ // reorder PlayerActivity to front
108
+ val mainActivity = FWInitializationProvider.INSTANCE.mainActivity
109
+ mainActivity?.let {
110
+ it.startActivity(PlayerActivity.getIntentForReorderToFront(it))
111
+ }
112
+ }
113
+
88
114
  @ReactMethod
89
115
  fun addListener(eventName: String?, promise: Promise) {
90
116
  // Set up any upstream listeners or background tasks as necessary
@@ -186,7 +186,7 @@ class FireworkSDKModule(
186
186
  val videoPlaybackDetails = FWModelUtils.convertPlayerEvent2PlaybackDetails(event)
187
187
  when (event) {
188
188
  is PlayerLifecycleAnalyticsEvent.OnStarted -> {
189
- if (event.videoInfo.isAd) {
189
+ if (event.videoInfo?.isAd == true) {
190
190
  FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.AdStart.rawValue, videoPlaybackDetails)
191
191
  } else {
192
192
  FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.Start.rawValue, videoPlaybackDetails)
@@ -199,7 +199,7 @@ class FireworkSDKModule(
199
199
  is PlayerLifecycleAnalyticsEvent.OnIdle -> {}
200
200
  is PlayerLifecycleAnalyticsEvent.OnRepeat -> {}
201
201
  is PlayerLifecycleAnalyticsEvent.OnEnded -> {
202
- if (event.videoInfo.isAd) {
202
+ if (event.videoInfo?.isAd == true) {
203
203
  FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.AdEnd.rawValue, videoPlaybackDetails)
204
204
  } else {
205
205
  FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.Complete.rawValue, videoPlaybackDetails)
@@ -5,6 +5,7 @@ import android.content.Context
5
5
  import android.graphics.Typeface
6
6
  import android.graphics.drawable.GradientDrawable
7
7
  import com.firework.common.PlayerMode
8
+ import com.firework.common.Theme
8
9
  import com.firework.common.ad.AdBadgeOption
9
10
  import com.firework.common.ad.AdBadgeTextType
10
11
  import com.firework.common.ad.AdOption
@@ -14,6 +15,7 @@ import com.firework.common.feed.FeedLayout
14
15
  import com.firework.common.feed.FeedResource
15
16
  import com.firework.common.feed.FeedTitlePosition
16
17
  import com.firework.common.player.CloseButtonOption
18
+ import com.firework.common.player.LivestreamCountDownOption
17
19
  import com.firework.common.player.MuteButtonOption
18
20
  import com.firework.common.player.PlaybackButtonOption
19
21
  import com.firework.common.player.PlayerUiOption
@@ -22,6 +24,7 @@ import com.firework.common.widget.WidgetImage
22
24
  import com.firework.viewoptions.*
23
25
  import com.fireworksdk.bridge.FWInitializationProvider
24
26
  import com.fireworksdk.bridge.models.*
27
+ import com.fireworksdk.bridge.models.enums.FWAppearanceMode
25
28
  import com.fireworksdk.bridge.models.enums.FWBadgeTextType
26
29
  import com.fireworksdk.bridge.models.enums.FWCtaDelayType
27
30
  import com.fireworksdk.bridge.models.enums.FWGradientDrawableOrientation
@@ -52,6 +55,7 @@ object FWConfigUtil {
52
55
  val adBadgeOptionBuilder = getDefaultAdBadgeOptionBuilder()
53
56
  val ctaOptionBuilder = getDefaultCtaOptionBuilder()
54
57
  val adOptionBuilder = getDefaultAdOptionBuilder()
58
+ val countDownOptionBuilder = getDefaultPlayerCountdownTimerOptionBuilder()
55
59
 
56
60
  when (videoFeedPropsModel.source) {
57
61
  FWVideoFeedSource.Discover -> {
@@ -397,16 +401,27 @@ object FWConfigUtil {
397
401
 
398
402
  val logoConfigOption = videoFeedPropsModel.videoPlayerConfiguration?.videoPlayerLogoConfiguration?.option
399
403
  val logoConfigChannelId = videoFeedPropsModel.videoPlayerConfiguration?.videoPlayerLogoConfiguration?.encodedId
404
+ val isLogoClickable = videoFeedPropsModel.videoPlayerConfiguration?.videoPlayerLogoConfiguration?.isClickable ?: true
400
405
  when {
401
406
  logoConfigOption == FWVideoPlayerLogoOption.Creator && !logoConfigChannelId.isNullOrBlank() -> {
402
- playerOptionBuilder.logoConfig(LogoConfig.Logo.CreatorLogo(logoConfigChannelId))
407
+ playerOptionBuilder.logoConfig(LogoConfig.Logo.CreatorLogo(logoConfigChannelId, isLogoClickable))
403
408
  }
404
409
  logoConfigOption == FWVideoPlayerLogoOption.ChannelAggregator && !logoConfigChannelId.isNullOrBlank() -> {
405
- playerOptionBuilder.logoConfig(LogoConfig.Logo.AggregatorLogo(logoConfigChannelId))
410
+ playerOptionBuilder.logoConfig(LogoConfig.Logo.AggregatorLogo(logoConfigChannelId, isLogoClickable))
406
411
  }
407
412
  else -> {}
408
413
  }
409
414
 
415
+ val countdownTimerAppearance = videoFeedPropsModel.videoPlayerConfiguration?.countdownTimerConfiguration?.appearance
416
+ val isCountdownTimerHidden = videoFeedPropsModel.videoPlayerConfiguration?.countdownTimerConfiguration?.isHidden ?: true
417
+ countDownOptionBuilder.isHidden(isCountdownTimerHidden)
418
+ when (countdownTimerAppearance) {
419
+ FWAppearanceMode.Light -> countDownOptionBuilder.theme(Theme.LIGHT)
420
+ FWAppearanceMode.Dark -> countDownOptionBuilder.theme(Theme.DARK)
421
+ else -> {}
422
+ }
423
+ playerOptionBuilder.livestreamCountDownOption(countDownOptionBuilder.build())
424
+
410
425
  return ViewOptions.Builder()
411
426
  .layoutOption(layoutOptionBuilder.build())
412
427
  .titleOption(titleOptionBuilder.build())
@@ -437,6 +452,10 @@ object FWConfigUtil {
437
452
  return PlayerUiOption.Builder()
438
453
  }
439
454
 
455
+ private fun getDefaultPlayerCountdownTimerOptionBuilder(): LivestreamCountDownOption.Builder {
456
+ return LivestreamCountDownOption.Builder()
457
+ }
458
+
440
459
  private fun getDefaultVideoDetailsOptionBuilder(): VideoDetailsOption.Builder {
441
460
  return VideoDetailsOption.Builder()
442
461
  }
@@ -36,15 +36,15 @@ object FWModelUtils {
36
36
 
37
37
  fun convertPlayerEvent2PlaybackDetails(event: PlayerLifecycleAnalyticsEvent): FWVideoPlaybackDetails {
38
38
  return FWVideoPlaybackDetails(
39
- badge = event.videoInfo.badge,
40
- caption = event.videoInfo.caption,
41
- duration = event.videoInfo.duration,
42
- hasCta = event.videoInfo.hasCta,
43
- playerHeight = event.videoInfo.playerHeight,
44
- playerWidth = event.videoInfo.playerWidth,
45
- id = event.videoInfo.id,
39
+ badge = event.videoInfo?.badge,
40
+ caption = event.videoInfo?.caption,
41
+ duration = event.videoInfo?.duration,
42
+ hasCta = event.videoInfo?.hasCta,
43
+ playerHeight = event.videoInfo?.playerHeight,
44
+ playerWidth = event.videoInfo?.playerWidth,
45
+ id = event.videoInfo?.id,
46
46
  progress = event.progress,
47
- feedId = event.videoInfo.feedId,
47
+ feedId = event.videoInfo?.feedId,
48
48
  )
49
49
  }
50
50
 
@@ -61,4 +61,4 @@ object FWModelUtils {
61
61
  )
62
62
  }
63
63
 
64
- }
64
+ }
@@ -123,7 +123,7 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate, PictureInPict
123
123
  self.storyBlockVC = storyBlockVC
124
124
  updateStoryBlockVCConfiguration()
125
125
 
126
- storyBlockVC.isPictureInPictureEnabled = storyBlockConfiguration?.enablePictureInPicture ?? true
126
+ storyBlockVC.isPictureInPictureEnabled = storyBlockConfiguration?.enablePictureInPicture ?? false
127
127
  storyBlockVC.pictureInPictureDelegate = self
128
128
  storyBlockVC.delegate = self
129
129
 
@@ -243,10 +243,10 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate, PictureInPict
243
243
  }
244
244
  }
245
245
 
246
- // if let showPlaybackButton = config.showPlaybackButton {
247
- // resultConfig.fullScreenPlayerView.playbackButton.isHidden = !showPlaybackButton
248
- // }
249
- //
246
+ if let showPlaybackButton = config.showPlaybackButton {
247
+ resultConfig.fullScreenPlayerView.playbackButton.isHidden = !showPlaybackButton
248
+ }
249
+
250
250
  // if let showMuteButton = config.showMuteButton {
251
251
  // resultConfig.fullScreenPlayerView.muteButton.isHidden = !showMuteButton
252
252
  // }
@@ -356,9 +356,6 @@ public class StoryBlock: UIView, StoryBlockViewControllerDelegate, PictureInPict
356
356
  if let replayBadgeConfiguration = config.replayBadgeConfiguration {
357
357
  resultConfig.replayBadge.isHidden = replayBadgeConfiguration.isHidden
358
358
  resultConfig.fullScreenPlayerView.replayBadge.isHidden = replayBadgeConfiguration.isHidden
359
- } else {
360
- resultConfig.replayBadge.isHidden = false
361
- resultConfig.fullScreenPlayerView.replayBadge.isHidden = false
362
359
  }
363
360
 
364
361
  if let countdownTimerConfiguration = config.countdownTimerConfiguration {
@@ -208,7 +208,7 @@ public class VideoFeed: UIView, VideoFeedViewControllerDelegate, PictureInPictur
208
208
  feedVC.viewConfiguration = viewConfiguration
209
209
  }
210
210
 
211
- feedVC.isPictureInPictureEnabled = playerViewConfig?.enablePictureInPicture ?? true
211
+ feedVC.isPictureInPictureEnabled = playerViewConfig?.enablePictureInPicture ?? false
212
212
 
213
213
  feedVC.delegate = self
214
214
  feedVC.pictureInPictureDelegate = self
@@ -537,8 +537,6 @@ extension VideoFeed {
537
537
 
538
538
  if let replayBadgeConfiguration = config.replayBadgeConfiguration {
539
539
  vpcConfig.replayBadge.isHidden = replayBadgeConfiguration.isHidden
540
- } else {
541
- vpcConfig.replayBadge.isHidden = false
542
540
  }
543
541
 
544
542
  if let countdownTimerConfiguration = config.countdownTimerConfiguration {
@@ -570,8 +568,6 @@ extension VideoFeed {
570
568
 
571
569
  if let replayBadge = feedViewConfig?.replayBadge {
572
570
  videoConfig.replayBadge.isHidden = replayBadge.isHidden
573
- } else {
574
- videoConfig.replayBadge.isHidden = false
575
571
  }
576
572
 
577
573
  return videoConfig
@@ -74,6 +74,7 @@
74
74
  8988736B2A0A8E7E0089CD1C /* VideoFeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898873432A0A8E7E0089CD1C /* VideoFeed.swift */; };
75
75
  8988736C2A0A8E7E0089CD1C /* VideoPlayerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898873442A0A8E7E0089CD1C /* VideoPlayerConfiguration.swift */; };
76
76
  8988736D2A0A8E7E0089CD1C /* VideoFeedManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 898873452A0A8E7E0089CD1C /* VideoFeedManager.m */; };
77
+ 89C105652BAD2C1D00E47CDD /* UIWindowScene+Swizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C105642BAD2C1D00E47CDD /* UIWindowScene+Swizzle.swift */; };
77
78
  89C4D6A62A494EB800EFB74A /* StoryBlockConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C4D6A52A494EB800EFB74A /* StoryBlockConfiguration.swift */; };
78
79
  89C6791A2A736C80000C1A71 /* ButtonInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C679192A736C80000C1A71 /* ButtonInfo.swift */; };
79
80
  89D6BBF929ACE2DC00C8AA2A /* (null) in Sources */ = {isa = PBXBuildFile; };
@@ -141,6 +142,7 @@
141
142
  898873432A0A8E7E0089CD1C /* VideoFeed.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoFeed.swift; sourceTree = "<group>"; };
142
143
  898873442A0A8E7E0089CD1C /* VideoPlayerConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VideoPlayerConfiguration.swift; sourceTree = "<group>"; };
143
144
  898873452A0A8E7E0089CD1C /* VideoFeedManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VideoFeedManager.m; sourceTree = "<group>"; };
145
+ 89C105642BAD2C1D00E47CDD /* UIWindowScene+Swizzle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIWindowScene+Swizzle.swift"; sourceTree = "<group>"; };
144
146
  89C4D6A52A494EB800EFB74A /* StoryBlockConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryBlockConfiguration.swift; sourceTree = "<group>"; };
145
147
  89C679192A736C80000C1A71 /* ButtonInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonInfo.swift; sourceTree = "<group>"; };
146
148
  /* End PBXFileReference section */
@@ -181,6 +183,7 @@
181
183
  898873122A0A8E7E0089CD1C /* Extensions */ = {
182
184
  isa = PBXGroup;
183
185
  children = (
186
+ 89C105642BAD2C1D00E47CDD /* UIWindowScene+Swizzle.swift */,
184
187
  898873132A0A8E7E0089CD1C /* UIViewController+AttachChild.swift */,
185
188
  898873142A0A8E7E0089CD1C /* UIView+Constraints.swift */,
186
189
  898873172A0A8E7E0089CD1C /* String+Color.swift */,
@@ -425,6 +428,7 @@
425
428
  8988736B2A0A8E7E0089CD1C /* VideoFeed.swift in Sources */,
426
429
  891F4AF62A67E12800A9E8DA /* FWRNContainerViewController.swift in Sources */,
427
430
  898873522A0A8E7E0089CD1C /* ShoppingCTAResult.swift in Sources */,
431
+ 89C105652BAD2C1D00E47CDD /* UIWindowScene+Swizzle.swift in Sources */,
428
432
  89C6791A2A736C80000C1A71 /* ButtonInfo.swift in Sources */,
429
433
  8975239D2817DEF80070EBB6 /* (null) in Sources */,
430
434
  898873562A0A8E7E0089CD1C /* SDKInitOptions.swift in Sources */,
@@ -39,6 +39,8 @@ class FireworkSDKModule: RCTEventEmitter, FireworkVideoSDKDelegate {
39
39
  self.initializeSDK(Self.cachedSDKInitOptions, true)
40
40
  }
41
41
 
42
+ UIWindowScene.swizzleMethods()
43
+
42
44
  _ = AppLanguageManager.shared
43
45
  NotificationCenter.default.addObserver(
44
46
  self, selector: #selector(Self.onAppLanguageChanged),
@@ -0,0 +1,33 @@
1
+ //
2
+ // UIWindowScene+Swizzle.swift
3
+ // react-native-firework-sdk
4
+ //
5
+ // Created by linjie jiang on 3/22/24.
6
+ //
7
+
8
+ import UIKit
9
+ import FireworkVideoUI
10
+
11
+ extension UIWindowScene {
12
+ static func swizzleMethods() {
13
+ #if DEBUG
14
+ Swizzle.swizzleSelector(
15
+ cls: self,
16
+ originalSelector: #selector(getter: UIWindowScene.windows),
17
+ customSelector: #selector(UIWindowScene.fw_windows)
18
+ )
19
+ #endif
20
+ }
21
+
22
+ @objc func fw_windows() -> [UIWindow] {
23
+ let windowList = self.fw_windows().filter { window in
24
+ let typeName = String(describing: type(of: window))
25
+ if typeName == "SKHiddenWindow" {
26
+ return false
27
+ }
28
+ return true
29
+ }
30
+
31
+ return windowList
32
+ }
33
+ }
@@ -62,7 +62,7 @@ class VideoFeed extends _react.default.Component {
62
62
 
63
63
  let reactTag = (0, _reactNative.findNodeHandle)(nativeNodeHandle);
64
64
 
65
- _FWLoggerUtil.default.log(`StoryBlock refresh commandId: ${commandId} nativeNodeHandle: ${nativeNodeHandle} reactTag: ${reactTag}`);
65
+ _FWLoggerUtil.default.log(`VideoFeed refresh commandId: ${commandId} nativeNodeHandle: ${nativeNodeHandle} reactTag: ${reactTag}`);
66
66
 
67
67
  if (!nativeNodeHandle || !reactTag) {
68
68
  return;
@@ -72,8 +72,6 @@ class VideoFeed extends _react.default.Component {
72
72
  });
73
73
 
74
74
  _defineProperty(this, "_onVideoFeedLoadFinished", event => {
75
- _FWLoggerUtil.default.log(`VideoFeed _onVideoFeedLoadFinished ${JSON.stringify(event.nativeEvent)}`);
76
-
77
75
  const {
78
76
  onVideoFeedLoadFinished,
79
77
  onVideoFeedEmpty
@@ -94,19 +92,30 @@ class VideoFeed extends _react.default.Component {
94
92
  error.reason = reason;
95
93
  }
96
94
 
97
- onVideoFeedLoadFinished(error);
98
-
99
95
  if (_reactNative.Platform.OS === 'android') {
96
+ if (!this._loaded) {
97
+ onVideoFeedLoadFinished(error);
98
+ }
99
+
100
100
  if (action === _FWNativeErrorAction.FWNativeErrorAction.loadingFirstPage || !this._loaded) {
101
101
  onVideoFeedEmpty === null || onVideoFeedEmpty === void 0 ? void 0 : onVideoFeedEmpty(error);
102
102
  }
103
103
  } else {
104
+ onVideoFeedLoadFinished(error);
105
+
104
106
  if (!this._loaded) {
105
107
  onVideoFeedEmpty === null || onVideoFeedEmpty === void 0 ? void 0 : onVideoFeedEmpty(error);
106
108
  }
107
109
  }
108
110
  } else {
109
- onVideoFeedLoadFinished();
111
+ if (_reactNative.Platform.OS === 'android') {
112
+ if (!this._loaded) {
113
+ onVideoFeedLoadFinished();
114
+ }
115
+ } else {
116
+ onVideoFeedLoadFinished();
117
+ }
118
+
110
119
  this._loaded = true;
111
120
  }
112
121
  }