react-native-firework-sdk 2.8.6 → 2.9.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 (88) hide show
  1. package/FireworkVideoUI.xcframework/Info.plist +5 -5
  2. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/FireworkVideoUI +0 -0
  3. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Info.plist +0 -0
  4. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/FireworkVideoUI +0 -0
  5. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Info.plist +0 -0
  6. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/_CodeSignature/CodeResources +1 -1
  7. package/android/build.gradle +2 -1
  8. package/android/gradle.properties +1 -1
  9. package/android/src/main/java/com/fireworksdk/bridge/components/base/FWLoading.kt +22 -0
  10. package/android/src/main/java/com/fireworksdk/bridge/components/storyblock/StoryBlockFragment.kt +240 -18
  11. package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/FWVideoFeed.kt +19 -9
  12. package/android/src/main/java/com/fireworksdk/bridge/models/FWAdConfigurationDeserializer.kt +49 -0
  13. package/android/src/main/java/com/fireworksdk/bridge/models/FWAdConfigurationModel.kt +13 -0
  14. package/android/src/main/java/com/fireworksdk/bridge/models/FWAdConfigurationSerializer.kt +42 -0
  15. package/android/src/main/java/com/fireworksdk/bridge/models/FWButtonInfoDeserializer.kt +21 -0
  16. package/android/src/main/java/com/fireworksdk/bridge/models/FWButtonInfoModel.kt +6 -0
  17. package/android/src/main/java/com/fireworksdk/bridge/models/FWButtonInfoSerializer.kt +17 -0
  18. package/android/src/main/java/com/fireworksdk/bridge/models/FWPlayerButtonConfigurationDeserializer.kt +33 -0
  19. package/android/src/main/java/com/fireworksdk/bridge/models/FWPlayerButtonConfigurationModel.kt +10 -0
  20. package/android/src/main/java/com/fireworksdk/bridge/models/FWPlayerButtonConfigurationSerializer.kt +25 -0
  21. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfiguration.kt +7 -0
  22. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfigurationDeserializer.kt +17 -0
  23. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfigurationSerializer.kt +13 -0
  24. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedPropsModel.kt +1 -0
  25. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedPropsModelDeserializer.kt +3 -0
  26. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedPropsModelSerializer.kt +2 -0
  27. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModel.kt +3 -1
  28. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelDeserializer.kt +7 -1
  29. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelSerializer.kt +4 -0
  30. package/android/src/main/java/com/fireworksdk/bridge/models/enums/FWErrorAction.kt +18 -0
  31. package/android/src/main/java/com/fireworksdk/bridge/models/enums/FWEventName.kt +3 -0
  32. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWStoryBlockManager.kt +50 -26
  33. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWVideoFeedManager.kt +47 -8
  34. package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FWVideoShoppingInterface.kt +1 -0
  35. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWNavigatorModule.kt +0 -10
  36. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt +42 -0
  37. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +5 -3
  38. package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +24 -6
  39. package/android/src/main/java/com/fireworksdk/bridge/utils/FWConfigUtil.kt +95 -0
  40. package/android/src/main/res/layout/fw_bridge_story_block.xml +6 -0
  41. package/android/src/main/res/layout/fw_loading.xml +14 -0
  42. package/ios/Components/VideoFeed.swift +1 -1
  43. package/ios/FireworkVideoUI/Podfile.lock +1 -1
  44. package/ios/Modules/FWNavigatorModule/RNSScreenStackView+Window.h +20 -0
  45. package/ios/Modules/FWNavigatorModule/RNSScreenStackView+Window.m +84 -0
  46. package/lib/commonjs/VideoShopping.js +1 -4
  47. package/lib/commonjs/VideoShopping.js.map +1 -1
  48. package/lib/commonjs/components/StoryBlock.js +32 -42
  49. package/lib/commonjs/components/StoryBlock.js.map +1 -1
  50. package/lib/commonjs/components/VideoFeed.js +29 -11
  51. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  52. package/lib/commonjs/index.js +8 -0
  53. package/lib/commonjs/index.js.map +1 -1
  54. package/lib/commonjs/utils/VideoFeedUtil.js +73 -0
  55. package/lib/commonjs/utils/VideoFeedUtil.js.map +1 -0
  56. package/lib/module/VideoShopping.js +1 -5
  57. package/lib/module/VideoShopping.js.map +1 -1
  58. package/lib/module/components/StoryBlock.js +32 -40
  59. package/lib/module/components/StoryBlock.js.map +1 -1
  60. package/lib/module/components/VideoFeed.js +28 -11
  61. package/lib/module/components/VideoFeed.js.map +1 -1
  62. package/lib/module/index.js +2 -1
  63. package/lib/module/index.js.map +1 -1
  64. package/lib/module/utils/VideoFeedUtil.js +65 -0
  65. package/lib/module/utils/VideoFeedUtil.js.map +1 -0
  66. package/lib/typescript/VideoShopping.d.ts +0 -1
  67. package/lib/typescript/components/StoryBlock.d.ts +15 -4
  68. package/lib/typescript/components/VideoFeed.d.ts +12 -1
  69. package/lib/typescript/index.d.ts +2 -1
  70. package/lib/typescript/models/ButtonInfo.d.ts +0 -1
  71. package/lib/typescript/models/ProductInfoViewConfiguration.d.ts +3 -3
  72. package/lib/typescript/models/StoryBlockConfiguration.d.ts +0 -2
  73. package/lib/typescript/models/VideoPlayerButtonConfiguration.d.ts +0 -6
  74. package/lib/typescript/models/VideoPlayerConfiguration.d.ts +0 -2
  75. package/lib/typescript/utils/VideoFeedUtil.d.ts +10 -0
  76. package/package.json +1 -1
  77. package/src/VideoShopping.ts +1 -4
  78. package/src/components/StoryBlock.tsx +40 -44
  79. package/src/components/VideoFeed.tsx +32 -11
  80. package/src/index.ts +2 -0
  81. package/src/models/ButtonInfo.ts +0 -1
  82. package/src/models/ProductInfoViewConfiguration.ts +3 -3
  83. package/src/models/StoryBlockConfiguration.ts +0 -2
  84. package/src/models/VideoPlayerButtonConfiguration.ts +0 -6
  85. package/src/models/VideoPlayerConfiguration.ts +0 -2
  86. package/src/utils/VideoFeedUtil.ts +74 -0
  87. package/android/src/main/java/com/fireworksdk/bridge/utils/FWStatusBarUtil.kt +0 -28
  88. package/android/src/main/java/com/fireworksdk/bridge/utils/FWStoryBlockUtil.kt +0 -30
@@ -164,10 +164,15 @@ object FWEventUtils {
164
164
  receiveEvent(reactContext, targetTag, FWFeedViewEventName.VideoFeedLoadFinished.rawValue, null)
165
165
  }
166
166
 
167
- fun receiveVideoFeedLoadFinishedFailedEvent(reactContext: ReactContext, targetTag: Int, name: String, reason: String?) {
167
+ fun receiveVideoFeedEmptyEvent(reactContext: ReactContext, targetTag: Int) {
168
+ receiveEvent(reactContext, targetTag, FWFeedViewEventName.VideoFeedEmpty.rawValue, null)
169
+ }
170
+
171
+ fun receiveVideoFeedLoadFinishedFailedEvent(reactContext: ReactContext, targetTag: Int, name: String?, reason: String?, action: String) {
168
172
  val eventMap = Arguments.createMap()
169
- eventMap.putString("name", name)
170
- eventMap.putString("reason", reason)
173
+ eventMap.putString("name", name ?: "VideoFeedLoadFailed")
174
+ eventMap.putString("reason", reason ?: "VideoFeedLoadFailed")
175
+ eventMap.putString("action", action)
171
176
  receiveEvent(reactContext, targetTag, FWFeedViewEventName.VideoFeedLoadFinished.rawValue, eventMap)
172
177
  }
173
178
 
@@ -175,10 +180,14 @@ object FWEventUtils {
175
180
  receiveEvent(reactContext, targetTag, FWStoryBlockEventName.StoryBlockLoadFinished.rawValue, null)
176
181
  }
177
182
 
178
- fun receiveStoryBlockLoadFinishedFailedEvent(reactContext: ReactContext, targetTag: Int, name: String, reason: String?) {
183
+ fun receiveStoryBlockEmptyEvent(reactContext: ReactContext, targetTag: Int) {
184
+ receiveEvent(reactContext, targetTag, FWStoryBlockEventName.StoryBlockEmpty.rawValue, null)
185
+ }
186
+
187
+ fun receiveStoryBlockLoadFinishedFailedEvent(reactContext: ReactContext, targetTag: Int, name: String?, reason: String?) {
179
188
  val eventMap = Arguments.createMap()
180
- eventMap.putString("name", name)
181
- eventMap.putString("reason", reason)
189
+ eventMap.putString("name", name ?: "StoryBlockLoadFailed")
190
+ eventMap.putString("reason", reason ?: "StoryBlockLoadFailed")
182
191
  receiveEvent(reactContext, targetTag, FWStoryBlockEventName.StoryBlockLoadFinished.rawValue, eventMap)
183
192
  }
184
193
 
@@ -247,6 +256,15 @@ object FWEventUtils {
247
256
  sendEvent(reactContext, FWEventName.LiveStreamChat.rawValue, eventMap)
248
257
  }
249
258
 
259
+ fun sendProductCardClickEvent(reactContext: ReactContext, url: String?, productId: String?, unitId: String?, callbackId: Int?) {
260
+ val eventMap = Arguments.createMap()
261
+ eventMap.putString("url", url ?: "")
262
+ eventMap.putString("productId", productId)
263
+ eventMap.putString("unitId", unitId)
264
+ eventMap.putInt("callbackId", callbackId?:0)
265
+ sendEvent(reactContext, FWVideoShoppingEventName.CustomProductCardTap.rawValue, eventMap)
266
+ }
267
+
250
268
  fun sendCustomLinkButtonClickEvent(reactContext: ReactContext, url: String?, productId: String?, unitId: String?, callbackId: Int?) {
251
269
  val eventMap = Arguments.createMap()
252
270
  eventMap.putString("url", url ?: "")
@@ -1,5 +1,6 @@
1
1
  package com.fireworksdk.bridge.utils
2
2
 
3
+ import android.annotation.SuppressLint
3
4
  import android.content.Context
4
5
  import android.graphics.Typeface
5
6
  import android.graphics.drawable.GradientDrawable
@@ -12,6 +13,12 @@ import com.firework.common.cta.CtaDelayUnit
12
13
  import com.firework.common.feed.FeedLayout
13
14
  import com.firework.common.feed.FeedResource
14
15
  import com.firework.common.feed.FeedTitlePosition
16
+ import com.firework.common.player.CloseButtonOption
17
+ import com.firework.common.player.MuteButtonOption
18
+ import com.firework.common.player.PlaybackButtonOption
19
+ import com.firework.common.player.PlayerUiOption
20
+ import com.firework.common.player.VideoDetailsOption
21
+ import com.firework.common.widget.WidgetImage
15
22
  import com.firework.viewoptions.*
16
23
  import com.fireworksdk.bridge.FWInitializationProvider
17
24
  import com.fireworksdk.bridge.models.*
@@ -35,6 +42,11 @@ object FWConfigUtil {
35
42
  val layoutOptionBuilder = getDefaultLayoutOptionBuilder()
36
43
  val titleOptionBuilder = getDefaultTitleOptionBuilder()
37
44
  val playerOptionBuilder = getDefaultPlayerOptionBuilder()
45
+ val playerUiOptionBuilder = getDefaultPlayerUiOptionBuilder()
46
+ val videoDetailsOptionBuilder = getDefaultVideoDetailsOptionBuilder()
47
+ val closeButtonOptionBuilder = getDefaultCloseButtonOptionBuilder()
48
+ val muteButtonOptionBuilder = getDefaultMuteButtonOptionBuilder()
49
+ val playbackButtonOptionBuilder = getDefaultPlaybackButtonOptionBuilder()
38
50
  val baseOptionBuilder = getDefaultBaseOptionBuilder()
39
51
  val adBadgeOptionBuilder = getDefaultAdBadgeOptionBuilder()
40
52
  val ctaOptionBuilder = getDefaultCtaOptionBuilder()
@@ -355,6 +367,33 @@ object FWConfigUtil {
355
367
  playerOptionBuilder.showFireworkLogo(it)
356
368
  }
357
369
 
370
+ val showVideoDetailTitle = videoFeedPropsModel.videoPlayerConfiguration?.showVideoDetailTitle
371
+ showVideoDetailTitle?.let {
372
+ videoDetailsOptionBuilder.showCaption(showVideoDetailTitle)
373
+ }
374
+
375
+ val buttonConfiguration = videoFeedPropsModel.videoPlayerConfiguration?.buttonConfiguration
376
+ videoDetailsOptionBuilder.buttonIcon(getWidgetImage(context, buttonConfiguration?.videoDetailButton))
377
+ closeButtonOptionBuilder.icon(getWidgetImage(context, buttonConfiguration?.closeButton))
378
+ muteButtonOptionBuilder.muteIcon(getWidgetImage(context, buttonConfiguration?.muteButton))
379
+ .unmuteIcon(getWidgetImage(context, buttonConfiguration?.unmuteButton))
380
+ playbackButtonOptionBuilder.playIcon(getWidgetImage(context, buttonConfiguration?.playButton))
381
+ .pauseIcon(getWidgetImage(context, buttonConfiguration?.pauseButton))
382
+
383
+ playerUiOptionBuilder.videoDetailsOption(videoDetailsOptionBuilder.build())
384
+ .closeButtonOption(closeButtonOptionBuilder.build())
385
+ .muteButtonOption(muteButtonOptionBuilder.build())
386
+ .playbackButtonOption(playbackButtonOptionBuilder.build())
387
+ playerOptionBuilder.playerUiOption(playerUiOptionBuilder.build())
388
+
389
+ val adConfiguration = videoFeedPropsModel.adConfiguration
390
+ if (adConfiguration != null) {
391
+ adOptionBuilder.vastAttributes(listVastAttributes2Map(adConfiguration.vastAttributes))
392
+ if (adConfiguration.adsFetchTimeout != null) {
393
+ adOptionBuilder.adsFetchTimeoutInSeconds(adConfiguration.adsFetchTimeout)
394
+ }
395
+ }
396
+
358
397
  return ViewOptions.Builder()
359
398
  .layoutOption(layoutOptionBuilder.build())
360
399
  .titleOption(titleOptionBuilder.build())
@@ -369,6 +408,7 @@ object FWConfigUtil {
369
408
  val context = FWInitializationProvider.INSTANCE.resumedActivity ?: return LayoutOption.Builder()
370
409
  return LayoutOption.Builder()
371
410
  .playIconWidth(FWCommonUtil.dpToPx("36".toFloat(), context))
411
+ .itemSpacing(FWCommonUtil.dpToPx(4.0f, context))
372
412
  }
373
413
 
374
414
  private fun getDefaultTitleOptionBuilder(): TitleOption.Builder {
@@ -380,6 +420,26 @@ object FWConfigUtil {
380
420
  .enablePipMode(false)
381
421
  }
382
422
 
423
+ private fun getDefaultPlayerUiOptionBuilder(): PlayerUiOption.Builder {
424
+ return PlayerUiOption.Builder()
425
+ }
426
+
427
+ private fun getDefaultVideoDetailsOptionBuilder(): VideoDetailsOption.Builder {
428
+ return VideoDetailsOption.Builder()
429
+ }
430
+
431
+ private fun getDefaultCloseButtonOptionBuilder(): CloseButtonOption.Builder {
432
+ return CloseButtonOption.Builder()
433
+ }
434
+
435
+ private fun getDefaultMuteButtonOptionBuilder(): MuteButtonOption.Builder {
436
+ return MuteButtonOption.Builder()
437
+ }
438
+
439
+ private fun getDefaultPlaybackButtonOptionBuilder(): PlaybackButtonOption.Builder {
440
+ return PlaybackButtonOption.Builder()
441
+ }
442
+
383
443
  private fun getDefaultBaseOptionBuilder(): BaseOption.Builder {
384
444
  return BaseOption.Builder()
385
445
  }
@@ -423,4 +483,39 @@ object FWConfigUtil {
423
483
  return typeface
424
484
  }
425
485
 
486
+ private fun listVastAttributes2Map(list: List<FWAdConfigurationModel.FWVastAttributeModel>?): Map<String, String>? {
487
+ list ?: return null
488
+ val map = mutableMapOf<String, String>()
489
+ for (item in list) {
490
+ if (!item.name.isNullOrBlank() && !item.value.isNullOrBlank()) {
491
+ map[item.name] = item.value
492
+ }
493
+ }
494
+
495
+ return map
496
+ }
497
+
498
+ private fun getWidgetImage(context: Context, buttonInfo: FWButtonInfoModel?): WidgetImage? {
499
+ if (buttonInfo == null) {
500
+ return null
501
+ }
502
+ val drawableRes = getDrawableByImageName(context, buttonInfo.imageName) ?: return null
503
+ return WidgetImage(
504
+ drawableRes = drawableRes,
505
+ tintColor = if (buttonInfo.tintColor.isNullOrBlank()) null else FWColorUtil.parseColor(buttonInfo.tintColor)
506
+ )
507
+ }
508
+
509
+ @SuppressLint("DiscouragedApi")
510
+ private fun getDrawableByImageName(context: Context, imageName: String?): Int? {
511
+ if (imageName.isNullOrBlank()) {
512
+ return null
513
+ }
514
+ return try {
515
+ context.resources.getIdentifier(imageName, "drawable", context.packageName)
516
+ } catch (e: Exception) {
517
+ null
518
+ }
519
+ }
520
+
426
521
  }
@@ -14,4 +14,10 @@
14
14
  android:layout_height="match_parent" />
15
15
 
16
16
  </FrameLayout>
17
+
18
+ <include
19
+ android:id="@+id/fw_loading_wrapper"
20
+ layout="@layout/fw_loading"
21
+ />
22
+
17
23
  </FrameLayout>
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
+ android:id="@+id/loader_container"
4
+ android:layout_width="match_parent"
5
+ android:layout_height="match_parent">
6
+
7
+ <com.firework.uikit.widget.FwProgressBar
8
+ android:id="@+id/loader"
9
+ android:layout_width="@dimen/fw__progress_size"
10
+ android:layout_height="@dimen/fw__progress_size"
11
+ android:layout_gravity="center"
12
+ android:visibility="visible" />
13
+
14
+ </FrameLayout>
@@ -543,7 +543,7 @@ extension VideoFeedLayout {
543
543
  if type(of: self) != type(of: other) {
544
544
  return false
545
545
  }
546
-
546
+
547
547
  if self.ignoresSafeAreaLayoutGuide == other.ignoresSafeAreaLayoutGuide,
548
548
  self.itemSpacing == other.itemSpacing,
549
549
  self.contentInsets == other.contentInsets {
@@ -13,4 +13,4 @@ SPEC CHECKSUMS:
13
13
 
14
14
  PODFILE CHECKSUM: b8d50fd1ccf28eaa3033fe13c43ca09199e1e245
15
15
 
16
- COCOAPODS: 1.14.2
16
+ COCOAPODS: 1.12.1
@@ -0,0 +1,20 @@
1
+ //
2
+ // RNSScreenStackView+Window.h
3
+ // react-native-firework-sdk
4
+ //
5
+ // Created by Haitao Shangguan on 2023/10/26.
6
+ //
7
+
8
+ #if __has_include(<RNScreens/RNSScreenStack.h>)
9
+
10
+ #import <RNScreens/RNSScreenStack.h>
11
+
12
+ NS_ASSUME_NONNULL_BEGIN
13
+
14
+ @interface RNSScreenStackView (Window)
15
+
16
+ @end
17
+
18
+ NS_ASSUME_NONNULL_END
19
+
20
+ #endif
@@ -0,0 +1,84 @@
1
+ //
2
+ // RNSScreenStackView+Window.m
3
+ // react-native-firework-sdk
4
+ //
5
+ // Created by Haitao Shangguan on 2023/10/26.
6
+ //
7
+
8
+ #if __has_include(<RNScreens/RNSScreenStack.h>)
9
+
10
+ #import "RNSScreenStackView+Window.h"
11
+ #import <objc/runtime.h>
12
+
13
+ @implementation RNSScreenStackView (Window)
14
+
15
+ #pragma clang diagnostic push
16
+ #pragma clang diagnostic ignored "-Wundeclared-selector"
17
+
18
+ static bool fw_setPushViewControllers = false;
19
+
20
+ __attribute__((constructor)) static void fw_screen_stack_view_inject_entry(void) {
21
+ [RNSScreenStackView swizzleScreenStackView];
22
+ }
23
+
24
+ + (void)swizzleSelector:(Class)originalClass
25
+ originalSelector:(SEL)originalSelector
26
+ swizzledClass:(Class)swizzledClass
27
+ swizzledSelector:(SEL)swizzledSelector {
28
+ Method originalMethod = class_getInstanceMethod(originalClass, originalSelector);
29
+ Method swizzledMethod = class_getInstanceMethod(swizzledClass, swizzledSelector);
30
+
31
+ BOOL didAddMethod = class_addMethod(originalClass,
32
+ originalSelector,
33
+ method_getImplementation(swizzledMethod),
34
+ method_getTypeEncoding(swizzledMethod));
35
+
36
+ if (didAddMethod) {
37
+ class_replaceMethod(originalClass,
38
+ swizzledSelector,
39
+ method_getImplementation(originalMethod),
40
+ method_getTypeEncoding(originalMethod));
41
+ } else {
42
+ method_exchangeImplementations(originalMethod, swizzledMethod);
43
+ }
44
+ }
45
+
46
+ + (void)swizzleScreenStackView {
47
+ SEL originalSelector1 = @selector(setPushViewControllers:);
48
+ SEL swizzledSelector1 = @selector(fw_setPushViewControllers:);
49
+
50
+ [self swizzleSelector:[self class]
51
+ originalSelector:originalSelector1
52
+ swizzledClass:[self class]
53
+ swizzledSelector:swizzledSelector1];
54
+
55
+ SEL originalSelector2 = @selector(window);
56
+ SEL swizzledSelector2 = @selector(fw_window);
57
+
58
+ [self swizzleSelector:[self class]
59
+ originalSelector:originalSelector2
60
+ swizzledClass:[self class]
61
+ swizzledSelector:swizzledSelector2];
62
+ }
63
+
64
+ - (void)fw_setPushViewControllers:(NSArray *)viewControllers {
65
+ fw_setPushViewControllers = true;
66
+ [self fw_setPushViewControllers:viewControllers];
67
+ fw_setPushViewControllers = false;
68
+ }
69
+
70
+ - (UIWindow *)fw_window {
71
+ UIWindow *window = [self fw_window];
72
+ if (fw_setPushViewControllers) {
73
+ if (window == nil) {
74
+ return [[UIWindow alloc] init];
75
+ }
76
+ }
77
+ return window;
78
+ }
79
+
80
+ #pragma clang diagnostic pop
81
+
82
+ @end
83
+
84
+ #endif
@@ -64,7 +64,6 @@ class VideoShopping {
64
64
 
65
65
  /**
66
66
  * This callback is triggered when the user clicks product card.
67
- * Only supported on iOS.
68
67
  *
69
68
  * The host app can customize the tap event processing logic of
70
69
  * the product card by setting the callback.
@@ -76,9 +75,7 @@ class VideoShopping {
76
75
  set onCustomTapProductCard(value) {
77
76
  this._onCustomTapProductCard = value;
78
77
 
79
- if (_reactNative.Platform.OS === 'ios') {
80
- _ShoppingModule.default.setCustomTapProductCardEnabled(!!value);
81
- }
78
+ _ShoppingModule.default.setCustomTapProductCardEnabled(!!value);
82
79
  }
83
80
 
84
81
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["VideoShopping.ts"],"names":["VideoShopping","onCustomClickLinkButton","_onCustomClickLinkButton","value","ShoppingModule","setCustomClickLinkButtonEnabled","onCustomTapProductCard","_onCustomTapProductCard","Platform","OS","setCustomTapProductCardEnabled","cartIconVisible","_cartIconVisible","FWGlobalState","getInstance","sdkInitCalled","setCartIconVisible","sdkInitCalledPromise","then","productInfoViewConfiguration","_productInfoViewConfiguration","valueHasChanged","updateNativeProductInfoViewConfiguration","setProductInfoViewConfiguration","eventEmitter","emit","FWEventName","ProductInfoViewConfigurationUpdated","FWLoggerUtil","log","ShoppingModuleEventEmitter","_instance","constructor","addListener","ShoppingCTAButtonClick","event","productId","unitId","url","handleShoppingCTAEvent","ClickCartIcon","handleClickCartIconEvent","UpdateProductDetails","productIds","handleUpdateProductDetailsEvent","LogMessage","CustomLinkButtonClick","handleCustomLinkButtonClickEvent","CustomProductCardTap","video","videoId","callbackId","playerHandler","pause","pausePlayer","resume","resumePlayer","handleCustomProductCardTapEvent","setCartItemCount","count","onShoppingCTA","result","updateShoppingCTAResult","clearCallbackId","onCustomClickCartIcon","onUpdateProductDetails","productList","map","product","length","updateVideoProducts"],"mappings":";;;;;;;AAAA;;AAEA;;AASA;;AAGA;;AAEA;;;;;;;;;;AAuBA;AACA;AACA;AACA,MAAMA,aAAN,CAAoB;AAGlB;AACF;AACA;AACA;;AAGE;AACF;AACA;AACA;AACA;AACA;;AAGE;AACF;AACA;AACA;AACA;;AAGE;AACF;AACA;AACA;AACA;AACA;AACA;AACoC,MAAvBC,uBAAuB,GAEpB;AACZ,WAAO,KAAKC,wBAAZ;AACD;;AACiC,MAAvBD,uBAAuB,CAChCE,KADgC,EAEhC;AACA,SAAKD,wBAAL,GAAgCC,KAAhC;;AACAC,4BAAeC,+BAAf,CAA+C,CAAC,CAACF,KAAjD;AACD;;AAGD;AACF;AACA;AACA;AACA;AACA;AACA;AACmC,MAAtBG,sBAAsB,GAEnB;AACZ,WAAO,KAAKC,uBAAZ;AACD;;AACgC,MAAtBD,sBAAsB,CAC/BH,KAD+B,EAE/B;AACA,SAAKI,uBAAL,GAA+BJ,KAA/B;;AACA,QAAIK,sBAASC,EAAT,KAAgB,KAApB,EAA2B;AACzBL,8BAAeM,8BAAf,CAA8C,CAAC,CAACP,KAAhD;AACD;AACF;;AAGD;AACF;AACA;AACA;AAC4B,MAAfQ,eAAe,GAAY;AACpC,WAAO,KAAKC,gBAAZ;AACD;;AACyB,MAAfD,eAAe,CAACR,KAAD,EAAiB;AACzC,SAAKS,gBAAL,GAAwBT,KAAxB;;AACA,QAAIU,uBAAcC,WAAd,GAA4BC,aAAhC,EAA+C;AAC7CX,8BAAeY,kBAAf,CAAkCb,KAAlC;AACD,KAFD,MAEO;AACLU,6BAAcC,WAAd,GAA4BG,oBAA5B,CAAiDC,IAAjD,CAAsD,MAAM;AAC1Dd,gCAAeY,kBAAf,CAAkCb,KAAlC;AACD,OAFD;AAGD;AACF;;AAGD;AACF;AACA;AACA;AACyC,MAA5BgB,4BAA4B,GAEzB;AACZ,WAAO,KAAKC,6BAAZ;AACD;;AAEsC,MAA5BD,4BAA4B,CACrChB,KADqC,EAErC;AACA,UAAMkB,eAAe,GAAG,KAAKD,6BAAL,KAAuCjB,KAA/D;AACA,SAAKiB,6BAAL,GAAqCjB,KAArC;;AACA,QAAIU,uBAAcC,WAAd,GAA4BC,aAAhC,EAA+C;AAC7C,WAAKO,wCAAL,CAA8CnB,KAA9C,EAAqDkB,eAArD;AACD,KAFD,MAEO;AACLR,6BAAcC,WAAd,GAA4BG,oBAA5B,CAAiDC,IAAjD,CAAsD,MAAM;AAC1D,aAAKI,wCAAL,CAA8CnB,KAA9C,EAAqDkB,eAArD;AACD,OAFD;AAGD;AACF;;AAEOC,EAAAA,wCAAwC,CAC9CnB,KAD8C,EAE9CkB,eAF8C,EAG9C;AACAjB,4BAAemB,+BAAf,CAA+CpB,KAA/C,aAA+CA,KAA/C,cAA+CA,KAA/C,GAAwD,EAAxD,EAA4De,IAA5D,CAAiE,MAAM;AACrE,UAAIG,eAAJ,EAAqB;AACnB,aAAKG,YAAL,CAAkBC,IAAlB,CAAuBC,yBAAYC,mCAAnC;;AACAC,8BAAaC,GAAb,CAAiB,kDAAjB;AACD;AACF,KALD;AAMD;;AAMuB,MAAZL,YAAY,GAAuB;AAC7C,WAAOM,0CAAP;AACD;;AAEwB,SAAXhB,WAAW,GAAG;AAC1Bc,0BAAaC,GAAb,CAAiB,2BAAjB;;AACA,QAAI,CAAC7B,aAAa,CAAC+B,SAAnB,EAA8B;AAC5B/B,MAAAA,aAAa,CAAC+B,SAAd,GAA0B,IAAI/B,aAAJ,EAA1B;AACD;;AAED,WAAOA,aAAa,CAAC+B,SAArB;AACD;;AAEOC,EAAAA,WAAW,GAAG;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,8CAvDc,IAuDd;;AAAA;;AACpB,SAAKR,YAAL,CAAkBS,WAAlB,CACEP,yBAAYQ,sBADd,EAEGC,KAAD,IAAW;AACTP,4BAAaC,GAAb,CACG,wCAAuCM,KAAxC,aAAwCA,KAAxC,uBAAwCA,KAAK,CAAEC,SAAU,YAAWD,KAApE,aAAoEA,KAApE,uBAAoEA,KAAK,CAAEE,MAAO,SAAQF,KAA1F,aAA0FA,KAA1F,uBAA0FA,KAAK,CAAEG,GAAI,EADvG;;AAGA,WAAKC,sBAAL,CAA4BJ,KAA5B;AACD,KAPH;AAUA,SAAKX,YAAL,CAAkBS,WAAlB,CAA8BP,yBAAYc,aAA1C,EAAyD,MAAM;AAC7DZ,4BAAaC,GAAb,CAAiB,6BAAjB;;AACA,WAAKY,wBAAL;AACD,KAHD;AAKA,SAAKjB,YAAL,CAAkBS,WAAlB,CAA8BP,yBAAYgB,oBAA1C,EAAiEP,KAAD,IAAW;AACzEP,4BAAaC,GAAb,CACG,kDAAiDM,KAAlD,aAAkDA,KAAlD,uBAAkDA,KAAK,CAAEQ,UAAW,EADtE;;AAGA,WAAKC,+BAAL,CAAqCT,KAArC;AACD,KALD;AAOA,SAAKX,YAAL,CAAkBS,WAAlB,CAA8BP,yBAAYmB,UAA1C,EAAsD,MAAM,CAAE,CAA9D;AAEA,SAAKrB,YAAL,CAAkBS,WAAlB,CACEP,yBAAYoB,qBADd,EAEGX,KAAD,IAAW;AACTP,4BAAaC,GAAb,CACG,4CAA2CM,KAA5C,aAA4CA,KAA5C,uBAA4CA,KAAK,CAAEG,GAAI,EADzD;;AAGA,WAAKS,gCAAL,CAAsCZ,KAAtC;AACD,KAPH;AAUA,SAAKX,YAAL,CAAkBS,WAAlB,CAA8BP,yBAAYsB,oBAA1C,EAAiEb,KAAD,IAAW;AACzEP,4BAAaC,GAAb,CAAkB,2CAA0CM,KAA3C,aAA2CA,KAA3C,uBAA2CA,KAAK,CAAEG,GAAI,EAAvE;;AACA,UAAIH,KAAJ,EAAW;AACT,YAAI,CAACA,KAAK,CAACc,KAAX,EAAkB;AAChBd,UAAAA,KAAK,CAACc,KAAN,GAAc;AAAEC,YAAAA,OAAO,EAAE;AAAX,WAAd;AACD;;AAED,YAAIf,KAAK,CAACgB,UAAV,EAAsB;AACpB,gBAAMA,UAAU,GAAGhB,KAAK,CAACgB,UAAzB;AACA,iBAAOhB,KAAK,CAACgB,UAAb;;AACA,cAAI3C,sBAASC,EAAT,KAAgB,KAApB,EAA2B;AACzB0B,YAAAA,KAAK,CAACiB,aAAN,GAAsB;AACpBC,cAAAA,KAAK,EAAE,MAAMjD,wBAAekD,WAAf,CAA2BH,UAA3B,CADO;AAEpBI,cAAAA,MAAM,EAAE,MAAMnD,wBAAeoD,YAAf,CAA4BL,UAA5B;AAFM,aAAtB;AAID;AACF;AACF;;AAED,WAAKM,+BAAL,CAAqCtB,KAArC,aAAqCA,KAArC,cAAqCA,KAArC,GAA8C,EAA9C;AACD,KApBD;AAqBD;AAED;AACF;AACA;AACA;AACA;AACA;AACA;AACA;;;AAC+B,QAAhBuB,gBAAgB,CAACC,KAAD,EAA+B;AAC1D,QAAI,CAAC9C,uBAAcC,WAAd,GAA4BC,aAAjC,EAAgD;AAC9C,YAAMF,uBAAcC,WAAd,GAA4BG,oBAAlC;AACD;;AACDb,4BAAesD,gBAAf,CAAgCC,KAAhC;AACD;;AAEmC,QAAtBpB,sBAAsB,CAACJ,KAAD,EAAa;AAC/C,UAAMgB,UAAU,GAAGhB,KAAK,CAACgB,UAAzB;AACA,WAAOhB,KAAK,CAACgB,UAAb;;AAEA,QAAI,KAAKS,aAAT,EAAwB;AACtB,YAAMC,MAAM,GAAG,MAAM,KAAKD,aAAL,CAAmBzB,KAAnB,CAArB;;AACA,UAAIgB,UAAJ,EAAgB;AACd/C,gCAAe0D,uBAAf,CAAuCD,MAAvC,EAA+CV,UAA/C;AACD;AACF,KALD,MAKO;AACL,UAAIA,UAAJ,EAAgB;AACd,YAAI3C,sBAASC,EAAT,KAAgB,KAApB,EAA2B;AACzBL,kCAAe2D,eAAf,CACEZ,UADF,EAEEzB,yBAAYQ,sBAFd;AAID;AACF;AACF;AACF;;AAEqC,QAAxBO,wBAAwB,GAAG;AACvC,QAAI,KAAKuB,qBAAT,EAAgC;AAC9B,WAAKA,qBAAL;AACD;AACF;;AAE4C,QAA/BpB,+BAA+B,CAACT,KAAD,EAAa;AACxD,UAAMgB,UAAU,GAAGhB,KAAK,CAACgB,UAAzB;AACA,WAAOhB,KAAK,CAACgB,UAAb;;AACA,QAAI,KAAKc,sBAAT,EAAiC;AAC/BrC,4BAAaC,GAAb,CACG,oDAAmDM,KAAK,CAACQ,UAAW,gBAAeQ,UAAW,EADjG;;AAGA,YAAMe,WAAW,GAAG,MAAM,KAAKD,sBAAL,CACxB9B,KADwB,CAA1B;AAIA,YAAMQ,UAAU,GAAG,CAACuB,WAAW,IAAI,EAAhB,EAAoBC,GAApB,CAChBC,OAAD;AAAA;;AAAA,qCAAaA,OAAO,CAAChC,SAArB,mEAAkC,EAAlC;AAAA,OADiB,CAAnB;;AAIAR,4BAAaC,GAAb,CACG,+DAA8Dc,UAAW,uBACxE,CAACuB,WAAW,IAAI,EAAhB,EAAoBG,MACrB,EAHH;;AAMA,UAAIH,WAAJ,EAAiB;AACf,YAAIf,UAAJ,EAAgB;AACd/C,kCAAekE,mBAAf,CAAmCJ,WAAnC,EAAgDf,UAAhD;AACD;AACF,OAJD,MAIO;AACL,YAAIA,UAAJ,EAAgB;AACd,cAAI3C,sBAASC,EAAT,KAAgB,KAApB,EAA2B;AACzBL,oCAAe2D,eAAf,CACEZ,UADF,EAEEzB,yBAAYgB,oBAFd;AAID;AACF;AACF;AACF,KAhCD,MAgCO;AACLd,4BAAaC,GAAb,CAAiB,6CAAjB;;AACA,UAAIsB,UAAJ,EAAgB;AACd,YAAI3C,sBAASC,EAAT,KAAgB,KAApB,EAA2B;AACzBL,kCAAe2D,eAAf,CACEZ,UADF,EAEEzB,yBAAYgB,oBAFd;AAID;AACF;AACF;AACF;;AAE6C,QAAhCK,gCAAgC,CAC5CZ,KAD4C,EAE5C;AACA,QAAI,KAAKlC,uBAAT,EAAkC;AAChC,WAAKA,uBAAL,CAA6BkC,KAA7B;AACD;AACF;;AAE4C,QAA/BsB,+BAA+B,CAC3CtB,KAD2C,EAE3C;AACA,QAAI,KAAK7B,sBAAT,EAAiC;AAC/B,WAAKA,sBAAL,CAA4B6B,KAA5B;AACD;AACF;;AA5SiB;;gBAAdnC,a;;eA+SSA,a","sourcesContent":["import { NativeEventEmitter, Platform } from 'react-native';\n\nimport { FWEventName } from './models/FWEventName';\nimport type {\n CustomClickLinkButtonEvent,\n CustomTapProductCardEvent,\n ShoppingCTAEvent,\n UpdateProductDetailsEvent,\n} from './models/FWEvents';\nimport type Product from './models/Product';\nimport type ProductInfoViewConfiguration from './models/ProductInfoViewConfiguration';\nimport ShoppingModule, {\n ShoppingModuleEventEmitter,\n} from './modules/ShoppingModule';\nimport FWLoggerUtil from './utils/FWLoggerUtil';\nimport type ShoppingCTAResult from './models/ShoppingCTAResult';\nimport FWGlobalState from './utils/FWGlobalState';\n\nexport type ShoppingCTACallback = (\n event: ShoppingCTAEvent\n) => Promise<ShoppingCTAResult> | ShoppingCTAResult;\n\nexport type CustomClickCartIconCallback = () => Promise<void> | void;\n\nexport type UpdateProductDetailsCallbackResult = Product[] | undefined | null;\nexport type UpdateProductDetailsCallback = (\n event: UpdateProductDetailsEvent\n) =>\n | Promise<UpdateProductDetailsCallbackResult>\n | UpdateProductDetailsCallbackResult;\n\nexport type CustomClickLinkButtonCallback = (\n event: CustomClickLinkButtonEvent\n) => Promise<void> | void;\n\nexport type CustomTapProductCardCallback = (\n event: CustomTapProductCardEvent\n) => Promise<void> | void;\n\n/**\n * The entry class of video shopping.\n */\nclass VideoShopping {\n private static _instance?: VideoShopping;\n\n /**\n * This callback is triggered when the user clicks the \"Add to cart\" or \"Shop now\" button.\n * The host app can return a ShoppingCTAResult object to tell SDK how to handle the result.\n */\n public onShoppingCTA?: ShoppingCTACallback;\n\n /**\n * This callback is triggered when the user clicks the shopping cart icon.\n *\n * The host app can customize the click event processing logic of\n * the shopping cart icon by setting the callback.\n */\n public onCustomClickCartIcon?: CustomClickCartIconCallback | undefined;\n\n /**\n * This callback is triggered when the video will be shown.\n *\n * The host app can return a Product list to update the latest product information.\n */\n public onUpdateProductDetails?: UpdateProductDetailsCallback;\n\n /**\n * This callback is triggered when the user clicks\n * the link button next to Add to cart button.\n *\n * The host app can customize the click event processing logic of\n * the link button by setting the callback.\n */\n public get onCustomClickLinkButton():\n | CustomClickLinkButtonCallback\n | undefined {\n return this._onCustomClickLinkButton;\n }\n public set onCustomClickLinkButton(\n value: CustomClickLinkButtonCallback | undefined\n ) {\n this._onCustomClickLinkButton = value;\n ShoppingModule.setCustomClickLinkButtonEnabled(!!value);\n }\n private _onCustomClickLinkButton?: CustomClickLinkButtonCallback | undefined;\n\n /**\n * This callback is triggered when the user clicks product card.\n * Only supported on iOS.\n *\n * The host app can customize the tap event processing logic of\n * the product card by setting the callback.\n */\n public get onCustomTapProductCard():\n | CustomTapProductCardCallback\n | undefined {\n return this._onCustomTapProductCard;\n }\n public set onCustomTapProductCard(\n value: CustomTapProductCardCallback | undefined\n ) {\n this._onCustomTapProductCard = value;\n if (Platform.OS === 'ios') {\n ShoppingModule.setCustomTapProductCardEnabled(!!value);\n }\n }\n private _onCustomTapProductCard?: CustomTapProductCardCallback | undefined;\n\n /**\n * Defaults to true.\n * You can hide the cart icon by setting this property to false.\n */\n public get cartIconVisible(): boolean {\n return this._cartIconVisible;\n }\n public set cartIconVisible(value: boolean) {\n this._cartIconVisible = value;\n if (FWGlobalState.getInstance().sdkInitCalled) {\n ShoppingModule.setCartIconVisible(value);\n } else {\n FWGlobalState.getInstance().sdkInitCalledPromise.then(() => {\n ShoppingModule.setCartIconVisible(value);\n });\n }\n }\n private _cartIconVisible: boolean = true;\n\n /**\n * The configuration of product info view.\n * Please refer to {@link ProductInfoViewConfiguration} for more details.\n */\n public get productInfoViewConfiguration():\n | ProductInfoViewConfiguration\n | undefined {\n return this._productInfoViewConfiguration;\n }\n\n public set productInfoViewConfiguration(\n value: ProductInfoViewConfiguration | undefined\n ) {\n const valueHasChanged = this._productInfoViewConfiguration !== value;\n this._productInfoViewConfiguration = value;\n if (FWGlobalState.getInstance().sdkInitCalled) {\n this.updateNativeProductInfoViewConfiguration(value, valueHasChanged);\n } else {\n FWGlobalState.getInstance().sdkInitCalledPromise.then(() => {\n this.updateNativeProductInfoViewConfiguration(value, valueHasChanged);\n });\n }\n }\n\n private updateNativeProductInfoViewConfiguration(\n value: ProductInfoViewConfiguration | undefined,\n valueHasChanged: Boolean\n ) {\n ShoppingModule.setProductInfoViewConfiguration(value ?? {}).then(() => {\n if (valueHasChanged) {\n this.eventEmitter.emit(FWEventName.ProductInfoViewConfigurationUpdated);\n FWLoggerUtil.log('eventEmitter ProductInfoViewConfigurationUpdated');\n }\n });\n }\n\n private _productInfoViewConfiguration?:\n | ProductInfoViewConfiguration\n | undefined;\n\n private get eventEmitter(): NativeEventEmitter {\n return ShoppingModuleEventEmitter;\n }\n\n public static getInstance() {\n FWLoggerUtil.log('VideoShopping constructor');\n if (!VideoShopping._instance) {\n VideoShopping._instance = new VideoShopping();\n }\n\n return VideoShopping._instance!;\n }\n\n private constructor() {\n this.eventEmitter.addListener(\n FWEventName.ShoppingCTAButtonClick,\n (event) => {\n FWLoggerUtil.log(\n `Receive ShoppingCTA event productId: ${event?.productId} unitId: ${event?.unitId} url: ${event?.url}`\n );\n this.handleShoppingCTAEvent(event);\n }\n );\n\n this.eventEmitter.addListener(FWEventName.ClickCartIcon, () => {\n FWLoggerUtil.log('Receive ClickCartIcon event');\n this.handleClickCartIconEvent();\n });\n\n this.eventEmitter.addListener(FWEventName.UpdateProductDetails, (event) => {\n FWLoggerUtil.log(\n `Receive UpdateProductDetails event productIds: ${event?.productIds}`\n );\n this.handleUpdateProductDetailsEvent(event);\n });\n\n this.eventEmitter.addListener(FWEventName.LogMessage, () => {});\n\n this.eventEmitter.addListener(\n FWEventName.CustomLinkButtonClick,\n (event) => {\n FWLoggerUtil.log(\n `Receive CustomLinkButtonClick event url: ${event?.url}`\n );\n this.handleCustomLinkButtonClickEvent(event);\n }\n );\n\n this.eventEmitter.addListener(FWEventName.CustomProductCardTap, (event) => {\n FWLoggerUtil.log(`Receive CustomProductCardTap event url: ${event?.url}`);\n if (event) {\n if (!event.video) {\n event.video = { videoId: '' };\n }\n\n if (event.callbackId) {\n const callbackId = event.callbackId;\n delete event.callbackId;\n if (Platform.OS === 'ios') {\n event.playerHandler = {\n pause: () => ShoppingModule.pausePlayer(callbackId),\n resume: () => ShoppingModule.resumePlayer(callbackId),\n };\n }\n }\n }\n\n this.handleCustomProductCardTapEvent(event ?? {});\n });\n }\n\n /**\n *\n * @param {number} count The number of items in the host app cart.\n * The count should be greater than or equal to 0.\n * We just use count to show or hide red indicator on the cart icon.\n * If cound > 0, we will show the red indicator on the cart icon.\n * Otherwise, we will hide the red indicator on the cart icon.\n */\n public async setCartItemCount(count: number): Promise<void> {\n if (!FWGlobalState.getInstance().sdkInitCalled) {\n await FWGlobalState.getInstance().sdkInitCalledPromise;\n }\n ShoppingModule.setCartItemCount(count);\n }\n\n private async handleShoppingCTAEvent(event: any) {\n const callbackId = event.callbackId;\n delete event.callbackId;\n\n if (this.onShoppingCTA) {\n const result = await this.onShoppingCTA(event as ShoppingCTAEvent);\n if (callbackId) {\n ShoppingModule.updateShoppingCTAResult(result, callbackId);\n }\n } else {\n if (callbackId) {\n if (Platform.OS === 'ios') {\n ShoppingModule.clearCallbackId(\n callbackId,\n FWEventName.ShoppingCTAButtonClick\n );\n }\n }\n }\n }\n\n private async handleClickCartIconEvent() {\n if (this.onCustomClickCartIcon) {\n this.onCustomClickCartIcon();\n }\n }\n\n private async handleUpdateProductDetailsEvent(event: any) {\n const callbackId = event.callbackId;\n delete event.callbackId;\n if (this.onUpdateProductDetails) {\n FWLoggerUtil.log(\n `Call onUpdateProductDetails callback productIds: ${event.productIds} callbackId: ${callbackId}`\n );\n const productList = await this.onUpdateProductDetails(\n event as UpdateProductDetailsEvent\n );\n\n const productIds = (productList || []).map(\n (product) => product.productId ?? ''\n );\n\n FWLoggerUtil.log(\n `Get result from onUpdateProductDetails callback productIds: ${productIds} productListLength: ${\n (productList || []).length\n }`\n );\n\n if (productList) {\n if (callbackId) {\n ShoppingModule.updateVideoProducts(productList, callbackId);\n }\n } else {\n if (callbackId) {\n if (Platform.OS === 'ios') {\n ShoppingModule.clearCallbackId(\n callbackId,\n FWEventName.UpdateProductDetails\n );\n }\n }\n }\n } else {\n FWLoggerUtil.log('onUpdateProductDetails callback is not set.');\n if (callbackId) {\n if (Platform.OS === 'ios') {\n ShoppingModule.clearCallbackId(\n callbackId,\n FWEventName.UpdateProductDetails\n );\n }\n }\n }\n }\n\n private async handleCustomLinkButtonClickEvent(\n event: CustomClickLinkButtonEvent\n ) {\n if (this.onCustomClickLinkButton) {\n this.onCustomClickLinkButton(event);\n }\n }\n\n private async handleCustomProductCardTapEvent(\n event: CustomTapProductCardEvent\n ) {\n if (this.onCustomTapProductCard) {\n this.onCustomTapProductCard(event);\n }\n }\n}\n\nexport default VideoShopping;\n"]}
1
+ {"version":3,"sources":["VideoShopping.ts"],"names":["VideoShopping","onCustomClickLinkButton","_onCustomClickLinkButton","value","ShoppingModule","setCustomClickLinkButtonEnabled","onCustomTapProductCard","_onCustomTapProductCard","setCustomTapProductCardEnabled","cartIconVisible","_cartIconVisible","FWGlobalState","getInstance","sdkInitCalled","setCartIconVisible","sdkInitCalledPromise","then","productInfoViewConfiguration","_productInfoViewConfiguration","valueHasChanged","updateNativeProductInfoViewConfiguration","setProductInfoViewConfiguration","eventEmitter","emit","FWEventName","ProductInfoViewConfigurationUpdated","FWLoggerUtil","log","ShoppingModuleEventEmitter","_instance","constructor","addListener","ShoppingCTAButtonClick","event","productId","unitId","url","handleShoppingCTAEvent","ClickCartIcon","handleClickCartIconEvent","UpdateProductDetails","productIds","handleUpdateProductDetailsEvent","LogMessage","CustomLinkButtonClick","handleCustomLinkButtonClickEvent","CustomProductCardTap","video","videoId","callbackId","Platform","OS","playerHandler","pause","pausePlayer","resume","resumePlayer","handleCustomProductCardTapEvent","setCartItemCount","count","onShoppingCTA","result","updateShoppingCTAResult","clearCallbackId","onCustomClickCartIcon","onUpdateProductDetails","productList","map","product","length","updateVideoProducts"],"mappings":"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","sourcesContent":["import { NativeEventEmitter, Platform } from 'react-native';\n\nimport { FWEventName } from './models/FWEventName';\nimport type {\n CustomClickLinkButtonEvent,\n CustomTapProductCardEvent,\n ShoppingCTAEvent,\n UpdateProductDetailsEvent,\n} from './models/FWEvents';\nimport type Product from './models/Product';\nimport type ProductInfoViewConfiguration from './models/ProductInfoViewConfiguration';\nimport ShoppingModule, {\n ShoppingModuleEventEmitter,\n} from './modules/ShoppingModule';\nimport FWLoggerUtil from './utils/FWLoggerUtil';\nimport type ShoppingCTAResult from './models/ShoppingCTAResult';\nimport FWGlobalState from './utils/FWGlobalState';\n\nexport type ShoppingCTACallback = (\n event: ShoppingCTAEvent\n) => Promise<ShoppingCTAResult> | ShoppingCTAResult;\n\nexport type CustomClickCartIconCallback = () => Promise<void> | void;\n\nexport type UpdateProductDetailsCallbackResult = Product[] | undefined | null;\nexport type UpdateProductDetailsCallback = (\n event: UpdateProductDetailsEvent\n) =>\n | Promise<UpdateProductDetailsCallbackResult>\n | UpdateProductDetailsCallbackResult;\n\nexport type CustomClickLinkButtonCallback = (\n event: CustomClickLinkButtonEvent\n) => Promise<void> | void;\n\nexport type CustomTapProductCardCallback = (\n event: CustomTapProductCardEvent\n) => Promise<void> | void;\n\n/**\n * The entry class of video shopping.\n */\nclass VideoShopping {\n private static _instance?: VideoShopping;\n\n /**\n * This callback is triggered when the user clicks the \"Add to cart\" or \"Shop now\" button.\n * The host app can return a ShoppingCTAResult object to tell SDK how to handle the result.\n */\n public onShoppingCTA?: ShoppingCTACallback;\n\n /**\n * This callback is triggered when the user clicks the shopping cart icon.\n *\n * The host app can customize the click event processing logic of\n * the shopping cart icon by setting the callback.\n */\n public onCustomClickCartIcon?: CustomClickCartIconCallback | undefined;\n\n /**\n * This callback is triggered when the video will be shown.\n *\n * The host app can return a Product list to update the latest product information.\n */\n public onUpdateProductDetails?: UpdateProductDetailsCallback;\n\n /**\n * This callback is triggered when the user clicks\n * the link button next to Add to cart button.\n *\n * The host app can customize the click event processing logic of\n * the link button by setting the callback.\n */\n public get onCustomClickLinkButton():\n | CustomClickLinkButtonCallback\n | undefined {\n return this._onCustomClickLinkButton;\n }\n public set onCustomClickLinkButton(\n value: CustomClickLinkButtonCallback | undefined\n ) {\n this._onCustomClickLinkButton = value;\n ShoppingModule.setCustomClickLinkButtonEnabled(!!value);\n }\n private _onCustomClickLinkButton?: CustomClickLinkButtonCallback | undefined;\n\n /**\n * This callback is triggered when the user clicks product card.\n *\n * The host app can customize the tap event processing logic of\n * the product card by setting the callback.\n */\n public get onCustomTapProductCard():\n | CustomTapProductCardCallback\n | undefined {\n return this._onCustomTapProductCard;\n }\n public set onCustomTapProductCard(\n value: CustomTapProductCardCallback | undefined\n ) {\n this._onCustomTapProductCard = value;\n ShoppingModule.setCustomTapProductCardEnabled(!!value);\n }\n private _onCustomTapProductCard?: CustomTapProductCardCallback | undefined;\n\n /**\n * Defaults to true.\n * You can hide the cart icon by setting this property to false.\n */\n public get cartIconVisible(): boolean {\n return this._cartIconVisible;\n }\n public set cartIconVisible(value: boolean) {\n this._cartIconVisible = value;\n if (FWGlobalState.getInstance().sdkInitCalled) {\n ShoppingModule.setCartIconVisible(value);\n } else {\n FWGlobalState.getInstance().sdkInitCalledPromise.then(() => {\n ShoppingModule.setCartIconVisible(value);\n });\n }\n }\n private _cartIconVisible: boolean = true;\n\n /**\n * The configuration of product info view.\n * Please refer to {@link ProductInfoViewConfiguration} for more details.\n */\n public get productInfoViewConfiguration():\n | ProductInfoViewConfiguration\n | undefined {\n return this._productInfoViewConfiguration;\n }\n\n public set productInfoViewConfiguration(\n value: ProductInfoViewConfiguration | undefined\n ) {\n const valueHasChanged = this._productInfoViewConfiguration !== value;\n this._productInfoViewConfiguration = value;\n if (FWGlobalState.getInstance().sdkInitCalled) {\n this.updateNativeProductInfoViewConfiguration(value, valueHasChanged);\n } else {\n FWGlobalState.getInstance().sdkInitCalledPromise.then(() => {\n this.updateNativeProductInfoViewConfiguration(value, valueHasChanged);\n });\n }\n }\n\n private updateNativeProductInfoViewConfiguration(\n value: ProductInfoViewConfiguration | undefined,\n valueHasChanged: Boolean\n ) {\n ShoppingModule.setProductInfoViewConfiguration(value ?? {}).then(() => {\n if (valueHasChanged) {\n this.eventEmitter.emit(FWEventName.ProductInfoViewConfigurationUpdated);\n FWLoggerUtil.log('eventEmitter ProductInfoViewConfigurationUpdated');\n }\n });\n }\n\n private _productInfoViewConfiguration?:\n | ProductInfoViewConfiguration\n | undefined;\n\n private get eventEmitter(): NativeEventEmitter {\n return ShoppingModuleEventEmitter;\n }\n\n public static getInstance() {\n FWLoggerUtil.log('VideoShopping constructor');\n if (!VideoShopping._instance) {\n VideoShopping._instance = new VideoShopping();\n }\n\n return VideoShopping._instance!;\n }\n\n private constructor() {\n this.eventEmitter.addListener(\n FWEventName.ShoppingCTAButtonClick,\n (event) => {\n FWLoggerUtil.log(\n `Receive ShoppingCTA event productId: ${event?.productId} unitId: ${event?.unitId} url: ${event?.url}`\n );\n this.handleShoppingCTAEvent(event);\n }\n );\n\n this.eventEmitter.addListener(FWEventName.ClickCartIcon, () => {\n FWLoggerUtil.log('Receive ClickCartIcon event');\n this.handleClickCartIconEvent();\n });\n\n this.eventEmitter.addListener(FWEventName.UpdateProductDetails, (event) => {\n FWLoggerUtil.log(\n `Receive UpdateProductDetails event productIds: ${event?.productIds}`\n );\n this.handleUpdateProductDetailsEvent(event);\n });\n\n this.eventEmitter.addListener(FWEventName.LogMessage, () => {});\n\n this.eventEmitter.addListener(\n FWEventName.CustomLinkButtonClick,\n (event) => {\n FWLoggerUtil.log(\n `Receive CustomLinkButtonClick event url: ${event?.url}`\n );\n this.handleCustomLinkButtonClickEvent(event);\n }\n );\n\n this.eventEmitter.addListener(FWEventName.CustomProductCardTap, (event) => {\n FWLoggerUtil.log(`Receive CustomProductCardTap event url: ${event?.url}`);\n if (event) {\n if (!event.video) {\n event.video = { videoId: '' };\n }\n\n if (event.callbackId) {\n const callbackId = event.callbackId;\n delete event.callbackId;\n if (Platform.OS === 'ios') {\n event.playerHandler = {\n pause: () => ShoppingModule.pausePlayer(callbackId),\n resume: () => ShoppingModule.resumePlayer(callbackId),\n };\n }\n }\n }\n\n this.handleCustomProductCardTapEvent(event ?? {});\n });\n }\n\n /**\n *\n * @param {number} count The number of items in the host app cart.\n * The count should be greater than or equal to 0.\n * We just use count to show or hide red indicator on the cart icon.\n * If cound > 0, we will show the red indicator on the cart icon.\n * Otherwise, we will hide the red indicator on the cart icon.\n */\n public async setCartItemCount(count: number): Promise<void> {\n if (!FWGlobalState.getInstance().sdkInitCalled) {\n await FWGlobalState.getInstance().sdkInitCalledPromise;\n }\n ShoppingModule.setCartItemCount(count);\n }\n\n private async handleShoppingCTAEvent(event: any) {\n const callbackId = event.callbackId;\n delete event.callbackId;\n\n if (this.onShoppingCTA) {\n const result = await this.onShoppingCTA(event as ShoppingCTAEvent);\n if (callbackId) {\n ShoppingModule.updateShoppingCTAResult(result, callbackId);\n }\n } else {\n if (callbackId) {\n if (Platform.OS === 'ios') {\n ShoppingModule.clearCallbackId(\n callbackId,\n FWEventName.ShoppingCTAButtonClick\n );\n }\n }\n }\n }\n\n private async handleClickCartIconEvent() {\n if (this.onCustomClickCartIcon) {\n this.onCustomClickCartIcon();\n }\n }\n\n private async handleUpdateProductDetailsEvent(event: any) {\n const callbackId = event.callbackId;\n delete event.callbackId;\n if (this.onUpdateProductDetails) {\n FWLoggerUtil.log(\n `Call onUpdateProductDetails callback productIds: ${event.productIds} callbackId: ${callbackId}`\n );\n const productList = await this.onUpdateProductDetails(\n event as UpdateProductDetailsEvent\n );\n\n const productIds = (productList || []).map(\n (product) => product.productId ?? ''\n );\n\n FWLoggerUtil.log(\n `Get result from onUpdateProductDetails callback productIds: ${productIds} productListLength: ${\n (productList || []).length\n }`\n );\n\n if (productList) {\n if (callbackId) {\n ShoppingModule.updateVideoProducts(productList, callbackId);\n }\n } else {\n if (callbackId) {\n if (Platform.OS === 'ios') {\n ShoppingModule.clearCallbackId(\n callbackId,\n FWEventName.UpdateProductDetails\n );\n }\n }\n }\n } else {\n FWLoggerUtil.log('onUpdateProductDetails callback is not set.');\n if (callbackId) {\n if (Platform.OS === 'ios') {\n ShoppingModule.clearCallbackId(\n callbackId,\n FWEventName.UpdateProductDetails\n );\n }\n }\n }\n }\n\n private async handleCustomLinkButtonClickEvent(\n event: CustomClickLinkButtonEvent\n ) {\n if (this.onCustomClickLinkButton) {\n this.onCustomClickLinkButton(event);\n }\n }\n\n private async handleCustomProductCardTapEvent(\n event: CustomTapProductCardEvent\n ) {\n if (this.onCustomTapProductCard) {\n this.onCustomTapProductCard(event);\n }\n }\n}\n\nexport default VideoShopping;\n"]}
@@ -35,15 +35,16 @@ const NativeComponentName = 'FWStoryBlock';
35
35
 
36
36
  const StoryBlock = (props, forwardedRef) => {
37
37
  const nativeComponentRef = (0, _react.useRef)(null);
38
- const [isFullscreenState, setIsFullscreenState] = (0, _react.useState)(false);
39
38
  const [sdkInitCalled, setSdkInitCalled] = (0, _react.useState)(_FWGlobalState.default.getInstance().sdkInitCalled);
39
+ const loadedRef = (0, _react.useRef)(false);
40
40
  const [, forceUpdate] = (0, _react.useReducer)(x => x + 1, 0);
41
41
 
42
42
  const handleStoryBlockLoadFinished = event => {
43
43
  _FWLoggerUtil.default.log(`StoryBlock handleStoryBlockLoadFinished ${event.nativeEvent.name}`);
44
44
 
45
45
  const {
46
- onStoryBlockLoadFinished
46
+ onStoryBlockLoadFinished,
47
+ onStoryBlockEmpty
47
48
  } = props;
48
49
  const {
49
50
  name,
@@ -52,22 +53,38 @@ const StoryBlock = (props, forwardedRef) => {
52
53
 
53
54
  if (onStoryBlockLoadFinished) {
54
55
  if (name) {
56
+ let error = {
57
+ name
58
+ };
59
+
55
60
  if (reason) {
56
- onStoryBlockLoadFinished({
57
- name,
58
- reason
59
- });
60
- } else {
61
- onStoryBlockLoadFinished({
62
- name
63
- });
61
+ error.reason = reason;
62
+ }
63
+
64
+ onStoryBlockLoadFinished(error);
65
+
66
+ if (!loadedRef.current) {
67
+ onStoryBlockEmpty === null || onStoryBlockEmpty === void 0 ? void 0 : onStoryBlockEmpty(error);
64
68
  }
65
69
  } else {
66
70
  onStoryBlockLoadFinished();
71
+ loadedRef.current = true;
67
72
  }
68
73
  }
69
74
  };
70
75
 
76
+ const handleStoryBlockEmpty = event => {
77
+ _FWLoggerUtil.default.log(`StoryBlock handleStoryBlockEmpty ${event.nativeEvent}`);
78
+
79
+ const {
80
+ onStoryBlockEmpty
81
+ } = props;
82
+
83
+ if (onStoryBlockEmpty) {
84
+ onStoryBlockEmpty();
85
+ }
86
+ };
87
+
71
88
  const handleStoryBlockDidStartPictureInPicture = event => {
72
89
  _FWLoggerUtil.default.log(`StoryBlock handleStoryBlockDidStartPictureInPicture ${JSON.stringify(event.nativeEvent)}`);
73
90
 
@@ -126,15 +143,6 @@ const StoryBlock = (props, forwardedRef) => {
126
143
  }
127
144
  };
128
145
 
129
- const handleStoryBlockFullScreenStateChanged = event => {
130
- _FWLoggerUtil.default.log(`StoryBlock handleStoryBlockFullScreenStateChanged ${event.nativeEvent.isFullScreen}`);
131
-
132
- const {
133
- isFullScreen
134
- } = event.nativeEvent;
135
- setIsFullscreenState(isFullScreen);
136
- };
137
-
138
146
  const generateDynamicContentParametersString = () => {
139
147
  const {
140
148
  dynamicContentParameters
@@ -329,6 +337,9 @@ const StoryBlock = (props, forwardedRef) => {
329
337
  },
330
338
  pause: () => {
331
339
  sendCommand('pause');
340
+ },
341
+ openFullscreen: () => {
342
+ sendCommand('openFullscreen');
332
343
  }
333
344
  };
334
345
  }, []);
@@ -387,27 +398,6 @@ const StoryBlock = (props, forwardedRef) => {
387
398
  setSdkInitCalled(true);
388
399
  });
389
400
  }, []);
390
- (0, _react.useEffect)(() => {
391
- if (_reactNative.Platform.OS === 'android') {
392
- const onBackPress = () => {
393
- if (isFullscreenState) {
394
- _FireworkSDK.default.getInstance().navigator.popNativeContainer();
395
-
396
- return true;
397
- }
398
-
399
- return false;
400
- };
401
-
402
- const subscription = _reactNative.BackHandler.addEventListener('hardwareBackPress', onBackPress);
403
-
404
- return () => {
405
- subscription.remove();
406
- };
407
- }
408
-
409
- return;
410
- }, [isFullscreenState]);
411
401
 
412
402
  if (!sdkInitCalled) {
413
403
  return null;
@@ -429,9 +419,9 @@ const StoryBlock = (props, forwardedRef) => {
429
419
  storyBlockConfiguration: storyBlockConfiguration,
430
420
  enablePictureInPicture: undefined,
431
421
  onStoryBlockLoadFinished: handleStoryBlockLoadFinished,
422
+ onStoryBlockEmpty: handleStoryBlockEmpty,
432
423
  onStoryBlockDidStartPictureInPicture: handleStoryBlockDidStartPictureInPicture,
433
- onStoryBlockDidStopPictureInPicture: handleStoryBlockDidStopPictureInPicture,
434
- onStoryBlockFullScreenStateChanged: handleStoryBlockFullScreenStateChanged
424
+ onStoryBlockDidStopPictureInPicture: handleStoryBlockDidStopPictureInPicture
435
425
  }));
436
426
  };
437
427