react-native-firework-sdk 2.18.13 → 2.19.1

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 (124) hide show
  1. package/android/gradle.properties +1 -1
  2. package/android/src/main/java/com/fireworksdk/bridge/components/storyblock/StoryBlockFragment.kt +2 -1
  3. package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/FWVideoFeed.kt +2 -1
  4. package/android/src/main/java/com/fireworksdk/bridge/models/FWControlsInsetModel.kt +1 -1
  5. package/android/src/main/java/com/fireworksdk/bridge/models/FWControlsInsetModelDeserializer.kt +2 -0
  6. package/android/src/main/java/com/fireworksdk/bridge/models/FWControlsInsetModelSerializer.kt +2 -0
  7. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModel.kt +4 -0
  8. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelDeserializer.kt +12 -0
  9. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelSerializer.kt +7 -0
  10. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoShoppingProduct.kt +2 -2
  11. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoShoppingProductDeserializer.kt +2 -2
  12. package/android/src/main/java/com/fireworksdk/bridge/models/enums/FWFeedCompleteAction.kt +18 -0
  13. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt +52 -4
  14. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +7 -5
  15. package/android/src/main/java/com/fireworksdk/bridge/utils/FWConfigUtil.kt +45 -3
  16. package/ios/Components/StoryBlock.swift +23 -2
  17. package/ios/Components/StoryBlockConfiguration.swift +3 -0
  18. package/ios/Components/StoryBlockManager.m +1 -1
  19. package/ios/Components/StoryBlockManager.swift +3 -4
  20. package/ios/Components/VideoFeed.swift +17 -2
  21. package/ios/Components/VideoFeedManager.m +1 -1
  22. package/ios/Components/VideoFeedManager.swift +3 -4
  23. package/ios/Components/VideoPlayerConfiguration.swift +7 -0
  24. package/ios/Models/Common/ButtonShape.swift +21 -0
  25. package/ios/Models/Common/ControlsInset.swift +1 -0
  26. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.m +0 -1
  27. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +7 -20
  28. package/ios/Modules/Shopping/ShoppingModule.swift +6 -3
  29. package/ios/Utils/Extensions/UIWindowScene+Swizzle.swift +2 -2
  30. package/lib/commonjs/FireworkSDK.js +19 -27
  31. package/lib/commonjs/FireworkSDK.js.map +1 -1
  32. package/lib/commonjs/VideoShopping.js +6 -6
  33. package/lib/commonjs/VideoShopping.js.map +1 -1
  34. package/lib/commonjs/components/StoryBlock.js +15 -10
  35. package/lib/commonjs/components/StoryBlock.js.map +1 -1
  36. package/lib/commonjs/components/VideoFeed.js +14 -5
  37. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  38. package/lib/commonjs/index.js.map +1 -1
  39. package/lib/commonjs/models/ButtonShape.js +2 -0
  40. package/lib/commonjs/models/ButtonShape.js.map +1 -0
  41. package/lib/commonjs/models/FeedCompleteAction.js +2 -0
  42. package/lib/commonjs/models/FeedCompleteAction.js.map +1 -0
  43. package/lib/commonjs/modules/FireworkSDKModule.js.map +1 -1
  44. package/lib/commonjs/utils/FWGlobalState.js +8 -8
  45. package/lib/commonjs/utils/FWGlobalState.js.map +1 -1
  46. package/lib/module/FireworkSDK.js +19 -27
  47. package/lib/module/FireworkSDK.js.map +1 -1
  48. package/lib/module/VideoShopping.js +6 -6
  49. package/lib/module/VideoShopping.js.map +1 -1
  50. package/lib/module/components/StoryBlock.js +15 -10
  51. package/lib/module/components/StoryBlock.js.map +1 -1
  52. package/lib/module/components/VideoFeed.js +14 -5
  53. package/lib/module/components/VideoFeed.js.map +1 -1
  54. package/lib/module/index.js.map +1 -1
  55. package/lib/module/models/ButtonShape.js +2 -0
  56. package/lib/module/models/ButtonShape.js.map +1 -0
  57. package/lib/module/models/FeedCompleteAction.js +2 -0
  58. package/lib/module/models/FeedCompleteAction.js.map +1 -0
  59. package/lib/module/modules/FireworkSDKModule.js.map +1 -1
  60. package/lib/module/utils/FWGlobalState.js +8 -8
  61. package/lib/module/utils/FWGlobalState.js.map +1 -1
  62. package/lib/typescript/commonjs/src/FireworkSDK.d.ts +0 -6
  63. package/lib/typescript/commonjs/src/FireworkSDK.d.ts.map +1 -1
  64. package/lib/typescript/commonjs/src/components/StoryBlock.d.ts +3 -4
  65. package/lib/typescript/commonjs/src/components/StoryBlock.d.ts.map +1 -1
  66. package/lib/typescript/commonjs/src/components/VideoFeed.d.ts +1 -1
  67. package/lib/typescript/commonjs/src/components/VideoFeed.d.ts.map +1 -1
  68. package/lib/typescript/commonjs/src/index.d.ts +3 -1
  69. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  70. package/lib/typescript/commonjs/src/models/ButtonShape.d.ts +2 -0
  71. package/lib/typescript/commonjs/src/models/ButtonShape.d.ts.map +1 -0
  72. package/lib/typescript/commonjs/src/models/ControlsInset.d.ts +1 -0
  73. package/lib/typescript/commonjs/src/models/ControlsInset.d.ts.map +1 -1
  74. package/lib/typescript/commonjs/src/models/FeedCompleteAction.d.ts +2 -0
  75. package/lib/typescript/commonjs/src/models/FeedCompleteAction.d.ts.map +1 -0
  76. package/lib/typescript/commonjs/src/models/StoryBlockConfiguration.d.ts +21 -3
  77. package/lib/typescript/commonjs/src/models/StoryBlockConfiguration.d.ts.map +1 -1
  78. package/lib/typescript/commonjs/src/models/VideoPlayerCTAStyle.d.ts +6 -3
  79. package/lib/typescript/commonjs/src/models/VideoPlayerCTAStyle.d.ts.map +1 -1
  80. package/lib/typescript/commonjs/src/models/VideoPlayerConfiguration.d.ts +14 -1
  81. package/lib/typescript/commonjs/src/models/VideoPlayerConfiguration.d.ts.map +1 -1
  82. package/lib/typescript/commonjs/src/modules/FireworkSDKModule.d.ts +0 -2
  83. package/lib/typescript/commonjs/src/modules/FireworkSDKModule.d.ts.map +1 -1
  84. package/lib/typescript/commonjs/src/utils/FWGlobalState.d.ts +4 -4
  85. package/lib/typescript/commonjs/src/utils/FWGlobalState.d.ts.map +1 -1
  86. package/lib/typescript/module/src/FireworkSDK.d.ts +0 -6
  87. package/lib/typescript/module/src/FireworkSDK.d.ts.map +1 -1
  88. package/lib/typescript/module/src/components/StoryBlock.d.ts +3 -4
  89. package/lib/typescript/module/src/components/StoryBlock.d.ts.map +1 -1
  90. package/lib/typescript/module/src/components/VideoFeed.d.ts +1 -1
  91. package/lib/typescript/module/src/components/VideoFeed.d.ts.map +1 -1
  92. package/lib/typescript/module/src/index.d.ts +3 -1
  93. package/lib/typescript/module/src/index.d.ts.map +1 -1
  94. package/lib/typescript/module/src/models/ButtonShape.d.ts +2 -0
  95. package/lib/typescript/module/src/models/ButtonShape.d.ts.map +1 -0
  96. package/lib/typescript/module/src/models/ControlsInset.d.ts +1 -0
  97. package/lib/typescript/module/src/models/ControlsInset.d.ts.map +1 -1
  98. package/lib/typescript/module/src/models/FeedCompleteAction.d.ts +2 -0
  99. package/lib/typescript/module/src/models/FeedCompleteAction.d.ts.map +1 -0
  100. package/lib/typescript/module/src/models/StoryBlockConfiguration.d.ts +21 -3
  101. package/lib/typescript/module/src/models/StoryBlockConfiguration.d.ts.map +1 -1
  102. package/lib/typescript/module/src/models/VideoPlayerCTAStyle.d.ts +6 -3
  103. package/lib/typescript/module/src/models/VideoPlayerCTAStyle.d.ts.map +1 -1
  104. package/lib/typescript/module/src/models/VideoPlayerConfiguration.d.ts +14 -1
  105. package/lib/typescript/module/src/models/VideoPlayerConfiguration.d.ts.map +1 -1
  106. package/lib/typescript/module/src/modules/FireworkSDKModule.d.ts +0 -2
  107. package/lib/typescript/module/src/modules/FireworkSDKModule.d.ts.map +1 -1
  108. package/lib/typescript/module/src/utils/FWGlobalState.d.ts +4 -4
  109. package/lib/typescript/module/src/utils/FWGlobalState.d.ts.map +1 -1
  110. package/package.json +1 -1
  111. package/react_native_firework_sdk.podspec +1 -2
  112. package/src/FireworkSDK.ts +25 -29
  113. package/src/VideoShopping.ts +6 -6
  114. package/src/components/StoryBlock.tsx +20 -16
  115. package/src/components/VideoFeed.tsx +15 -6
  116. package/src/index.tsx +4 -0
  117. package/src/models/ButtonShape.ts +1 -0
  118. package/src/models/ControlsInset.ts +1 -0
  119. package/src/models/FeedCompleteAction.ts +1 -0
  120. package/src/models/StoryBlockConfiguration.ts +24 -3
  121. package/src/models/VideoPlayerCTAStyle.ts +6 -3
  122. package/src/models/VideoPlayerConfiguration.ts +16 -1
  123. package/src/modules/FireworkSDKModule.ts +0 -2
  124. package/src/utils/FWGlobalState.ts +10 -10
@@ -15,7 +15,6 @@ import LivestreamPlayerDesignVersion from './models/LivestreamPlayerDesignVersio
15
15
  import ShortVideoPlayerDesignVersion from './models/ShortVideoPlayerDesignVersion';
16
16
  import type MarkInitCalledOptions from './models/MarkInitCalledOptions';
17
17
  import type OpenVideoPlayerConfiguration from './models/OpenVideoPlayerConfiguration';
18
- import type SDKInitOptions from './models/SDKInitOptions';
19
18
  import type { VideoLaunchBehavior } from './models/SDKInitOptions';
20
19
  import type TrackPurchaseParameters from './models/TrackPurchaseParameters';
21
20
  import FireworkSDKModule, {
@@ -257,6 +256,9 @@ class FireworkSDK {
257
256
 
258
257
  this.eventEmitter.addListener(FWEventName.SDKInit, (event) => {
259
258
  FWLoggerUtil.log(`Receive SDKInit event ${event?.error}`);
259
+ FWLoggerUtil.log(
260
+ `FireworkSDKGlobalState.getInstance().sdkInitSucceeded: ${FWGlobalState.getInstance().sdkInitSucceeded}`
261
+ );
260
262
 
261
263
  if (event && !event.error) {
262
264
  this.completeRemainingInitialization();
@@ -264,8 +266,15 @@ class FireworkSDK {
264
266
 
265
267
  if (!this.hasCalledSDKInitCallback) {
266
268
  this.hasCalledSDKInitCallback = true;
267
- if (this.onSDKInit && event) {
268
- this.onSDKInit(event);
269
+ if (this.onSDKInit) {
270
+ this.onSDKInit(
271
+ event ?? {
272
+ error: {
273
+ name: 'SDKInitError',
274
+ reason: 'SDK initialization failed',
275
+ },
276
+ }
277
+ );
269
278
  }
270
279
  }
271
280
  });
@@ -327,22 +336,6 @@ class FireworkSDK {
327
336
  }
328
337
  }
329
338
 
330
- /**
331
- * Initializes Firework SDK.
332
- * @param {SDKInitOptions?} options
333
- */
334
- public async init(options?: SDKInitOptions): Promise<void> {
335
- FWLoggerUtil.log('Call FireworkSDK init method');
336
- const videoLaunchBehaviorUpdated =
337
- this._videoLaunchBehavior !== options?.videoLaunchBehavior;
338
- this._videoLaunchBehavior = options?.videoLaunchBehavior;
339
- await FireworkSDKModule.init(options);
340
- if (videoLaunchBehaviorUpdated) {
341
- this.eventEmitter.emit(FWEventName.VideoLaunchBehaviorUpdated);
342
- }
343
- await this.completeRemainingInitialization();
344
- }
345
-
346
339
  /**
347
340
  * Mark the initialization method as being called on the JS side.
348
341
  * @param {MarkInitCalledOptions} options
@@ -357,8 +350,11 @@ class FireworkSDK {
357
350
  await this.completeRemainingInitialization(options);
358
351
  await FireworkSDKModule.markInitCalled();
359
352
  } else {
360
- const hasCalledSDKInit = await FireworkSDKModule.markInitCalled();
361
- if (hasCalledSDKInit) {
353
+ const initSucceeded = await FireworkSDKModule.markInitCalled();
354
+ FWLoggerUtil.log(
355
+ `FireworkSDK markInitCalled initSucceeded: ${initSucceeded}`
356
+ );
357
+ if (initSucceeded) {
362
358
  await this.completeRemainingInitialization(options);
363
359
  }
364
360
  }
@@ -373,8 +369,8 @@ class FireworkSDK {
373
369
  url: string,
374
370
  config?: OpenVideoPlayerConfiguration
375
371
  ): Promise<void> {
376
- if (!FWGlobalState.getInstance().sdkInitCalled) {
377
- await FWGlobalState.getInstance().sdkInitCalledPromise;
372
+ if (!FWGlobalState.getInstance().sdkInitSucceeded) {
373
+ await FWGlobalState.getInstance().sdkInitSucceededPromise;
378
374
  }
379
375
  FireworkSDKModule.openVideoPlayer(url, config ?? {});
380
376
  }
@@ -386,8 +382,8 @@ class FireworkSDK {
386
382
  public async trackPurchase(
387
383
  parameters: TrackPurchaseParameters
388
384
  ): Promise<void> {
389
- if (!FWGlobalState.getInstance().sdkInitCalled) {
390
- await FWGlobalState.getInstance().sdkInitCalledPromise;
385
+ if (!FWGlobalState.getInstance().sdkInitSucceeded) {
386
+ await FWGlobalState.getInstance().sdkInitSucceededPromise;
391
387
  }
392
388
  FireworkSDKModule.trackPurchase(parameters);
393
389
  }
@@ -398,8 +394,8 @@ class FireworkSDK {
398
394
  * @returns {Promise<boolean>} The result of changing app language.
399
395
  */
400
396
  public async changeAppLanguage(language?: string | null): Promise<boolean> {
401
- if (!FWGlobalState.getInstance().sdkInitCalled) {
402
- await FWGlobalState.getInstance().sdkInitCalledPromise;
397
+ if (!FWGlobalState.getInstance().sdkInitSucceeded) {
398
+ await FWGlobalState.getInstance().sdkInitSucceededPromise;
403
399
  }
404
400
 
405
401
  const result = await FireworkSDKModule.changeAppLanguage(language);
@@ -446,11 +442,11 @@ class FireworkSDK {
446
442
  directlyCallNativeInit: false,
447
443
  }
448
444
  ): Promise<void> {
449
- if (FWGlobalState.getInstance().sdkInitCalled) {
445
+ if (FWGlobalState.getInstance().sdkInitSucceeded) {
450
446
  return;
451
447
  }
452
448
 
453
- FWGlobalState.getInstance().resolveSdkInitCalled();
449
+ FWGlobalState.getInstance().resolveSdkInitSucceeded();
454
450
  if (!options.directlyCallNativeInit) {
455
451
  await ShoppingModule.init();
456
452
  await LiveStreamModule.init();
@@ -126,10 +126,10 @@ class VideoShopping {
126
126
  }
127
127
  public set cartIconVisible(value: boolean) {
128
128
  this._cartIconVisible = value;
129
- if (FWGlobalState.getInstance().sdkInitCalled) {
129
+ if (FWGlobalState.getInstance().sdkInitSucceeded) {
130
130
  ShoppingModule.setCartIconVisible(value);
131
131
  } else {
132
- FWGlobalState.getInstance().sdkInitCalledPromise.then(() => {
132
+ FWGlobalState.getInstance().sdkInitSucceededPromise.then(() => {
133
133
  ShoppingModule.setCartIconVisible(value);
134
134
  });
135
135
  }
@@ -151,10 +151,10 @@ class VideoShopping {
151
151
  ) {
152
152
  const valueHasChanged = this._productInfoViewConfiguration !== value;
153
153
  this._productInfoViewConfiguration = value;
154
- if (FWGlobalState.getInstance().sdkInitCalled) {
154
+ if (FWGlobalState.getInstance().sdkInitSucceeded) {
155
155
  this.updateNativeProductInfoViewConfiguration(value, valueHasChanged);
156
156
  } else {
157
- FWGlobalState.getInstance().sdkInitCalledPromise.then(() => {
157
+ FWGlobalState.getInstance().sdkInitSucceededPromise.then(() => {
158
158
  this.updateNativeProductInfoViewConfiguration(value, valueHasChanged);
159
159
  });
160
160
  }
@@ -258,8 +258,8 @@ class VideoShopping {
258
258
  * Otherwise, we will hide the red indicator on the cart icon.
259
259
  */
260
260
  public async setCartItemCount(count: number): Promise<void> {
261
- if (!FWGlobalState.getInstance().sdkInitCalled) {
262
- await FWGlobalState.getInstance().sdkInitCalledPromise;
261
+ if (!FWGlobalState.getInstance().sdkInitSucceeded) {
262
+ await FWGlobalState.getInstance().sdkInitSucceededPromise;
263
263
  }
264
264
  ShoppingModule.setCartItemCount(count);
265
265
  }
@@ -50,15 +50,11 @@ export interface IStoryBlockMethods {
50
50
  /**
51
51
  * Triggered when the story block enters the viewport.
52
52
  * It is recommended to call this method when the host app detects scroll events.
53
- * Only supported on iOS.
54
- * Android automatically handles visibility detection during scrolling, so this API is only available on iOS.
55
53
  */
56
54
  onViewportEntered: () => void;
57
55
  /**
58
56
  * Triggered when the story block leaves the viewport.
59
57
  * It is recommended that the host app is triggered when listening for scrolling.
60
- * Only supported on iOS.
61
- * Android automatically handles visibility detection during scrolling, so this API is only available on iOS.
62
58
  */
63
59
  onViewportLeft: () => void;
64
60
  }
@@ -115,7 +111,9 @@ export interface IStoryBlockProps {
115
111
  */
116
112
  adConfiguration?: AdConfiguration;
117
113
 
118
- /* The configuration of the story block. */
114
+ /**
115
+ * The configuration of the story block.
116
+ */
119
117
  storyBlockConfiguration?: StoryBlockConfiguration;
120
118
  /**
121
119
  * The feed loading result callback. It means loading successfully when error equals to undefined.
@@ -151,8 +149,8 @@ const StoryBlock: ForwardRefRenderFunction<
151
149
  > = (props: IStoryBlockProps, forwardedRef) => {
152
150
  const nativeComponentRef = useRef(null);
153
151
  const isMountedRef = useRef<boolean>(true);
154
- const [sdkInitCalled, setSdkInitCalled] = useState<boolean>(
155
- FWGlobalState.getInstance().sdkInitCalled
152
+ const [sdkInitSucceeded, setSdkInitSucceeded] = useState<boolean>(
153
+ FWGlobalState.getInstance().sdkInitSucceeded
156
154
  );
157
155
  const loadedRef = useRef<boolean>(false);
158
156
  const [, forceUpdate] = useReducer((x) => x + 1, 0);
@@ -406,6 +404,7 @@ const StoryBlock: ForwardRefRenderFunction<
406
404
  const additionalControlsInsetJsonKey = gennerateJsonKey(
407
405
  storyBlockConfiguration?.additionalControlsInset
408
406
  );
407
+ const feedCompleteAction = storyBlockConfiguration?.feedCompleteAction;
409
408
  const shouldExtendMediaOutsideSafeArea =
410
409
  storyBlockConfiguration?.shouldExtendMediaOutsideSafeArea;
411
410
  const statusBarHidden = storyBlockConfiguration?.statusBarHidden;
@@ -414,6 +413,10 @@ const StoryBlock: ForwardRefRenderFunction<
414
413
  const scrollDirection = storyBlockConfiguration?.scrollDirection;
415
414
  const enableScrollForVertical =
416
415
  storyBlockConfiguration?.enableScrollForVertical;
416
+ const isArrowButtonVisible = storyBlockConfiguration?.isArrowButtonVisible;
417
+ const isFullscreenArrowButtonVisible =
418
+ storyBlockConfiguration?.isFullscreenArrowButtonVisible;
419
+ const ctaButtonStyle = storyBlockConfiguration?.ctaButtonStyle;
417
420
 
418
421
  let key = `gShareBaseURL:${gShareBaseURL}`;
419
422
  if (Platform.OS === 'ios') {
@@ -452,6 +455,10 @@ const StoryBlock: ForwardRefRenderFunction<
452
455
  key += `_ctaHighlightDelayType:${ctaHighlightDelayType}`;
453
456
  key += `_ctaHighlightDelayValue:${ctaHighlightDelayValue}`;
454
457
  key += `_ctaWidth:${ctaWidth}`;
458
+ key += `_ctaButtonStyle.backgroundColor:${ctaButtonStyle?.backgroundColor}`;
459
+ key += `_ctaButtonStyle.textColor:${ctaButtonStyle?.textColor}`;
460
+ key += `_ctaButtonStyle.fontSize:${ctaButtonStyle?.fontSize}`;
461
+ key += `_ctaButtonStyle.shape:${ctaButtonStyle?.shape}`;
455
462
  key += `_buttonConfiguration.videoDetailButton:${generateButtonInfoString(
456
463
  buttonConfiguration?.videoDetailButton
457
464
  )}`;
@@ -482,12 +489,15 @@ const StoryBlock: ForwardRefRenderFunction<
482
489
  key += `_replayBadgeConfiguration:${replayBadgeConfigurationJsonKey}`;
483
490
  key += `_countdownTimerConfiguration:${countdownTimerConfigurationJsonKey}`;
484
491
  key += `_additionalControlsInset:${additionalControlsInsetJsonKey}`;
492
+ key += `_feedCompleteAction:${feedCompleteAction}`;
485
493
  key += `_shouldExtendMediaOutsideSafeArea:${shouldExtendMediaOutsideSafeArea}`;
486
494
  key += `_statusBarHidden:${statusBarHidden}`;
487
495
  key += `_statusBarStyle:${statusBarStyle}`;
488
496
  key += `_pipPlacement:${pipPlacement}`;
489
497
  key += `_scrollDirection:${scrollDirection}`;
490
498
  key += `_enableScrollForVertical:${enableScrollForVertical}`;
499
+ key += `_isArrowButtonVisible:${isArrowButtonVisible}`;
500
+ key += `_isFullscreenArrowButtonVisible:${isFullscreenArrowButtonVisible}`;
491
501
  return key;
492
502
  };
493
503
 
@@ -525,15 +535,9 @@ const StoryBlock: ForwardRefRenderFunction<
525
535
  sendCommand('openFullscreen');
526
536
  },
527
537
  onViewportEntered: () => {
528
- if (Platform.OS !== 'ios') {
529
- return;
530
- }
531
538
  sendCommand('onViewportEntered');
532
539
  },
533
540
  onViewportLeft: () => {
534
- if (Platform.OS !== 'ios') {
535
- return;
536
- }
537
541
  sendCommand('onViewportLeft');
538
542
  },
539
543
  };
@@ -651,9 +655,9 @@ const StoryBlock: ForwardRefRenderFunction<
651
655
  }, [key]);
652
656
 
653
657
  useEffect(() => {
654
- FWGlobalState.getInstance().sdkInitCalledPromise.then(() => {
658
+ FWGlobalState.getInstance().sdkInitSucceededPromise.then(() => {
655
659
  if (!isMountedRef.current) return;
656
- setSdkInitCalled(true);
660
+ setSdkInitSucceeded(true);
657
661
  });
658
662
  }, []);
659
663
 
@@ -666,7 +670,7 @@ const StoryBlock: ForwardRefRenderFunction<
666
670
  };
667
671
  }, []);
668
672
 
669
- if (!sdkInitCalled) {
673
+ if (!sdkInitSucceeded) {
670
674
  return null;
671
675
  }
672
676
  const { style, cornerRadius, ...otherProps } = props;
@@ -123,7 +123,7 @@ export interface IVideoFeedProps {
123
123
  }
124
124
 
125
125
  interface IVideoFeedState {
126
- sdkInitCalled: boolean;
126
+ sdkInitSucceeded: boolean;
127
127
  }
128
128
 
129
129
  const NativeComponentName = 'FWVideoFeed';
@@ -148,7 +148,7 @@ class VideoFeed extends React.Component<IVideoFeedProps, IVideoFeedState> {
148
148
  constructor(props: IVideoFeedProps) {
149
149
  super(props);
150
150
  this.state = {
151
- sdkInitCalled: FWGlobalState.getInstance().sdkInitCalled,
151
+ sdkInitSucceeded: FWGlobalState.getInstance().sdkInitSucceeded,
152
152
  };
153
153
  }
154
154
 
@@ -303,9 +303,9 @@ class VideoFeed extends React.Component<IVideoFeedProps, IVideoFeedState> {
303
303
  `VideoFeed componentDidMount ${JSON.stringify(this.props)}`
304
304
  );
305
305
 
306
- if (!this.state.sdkInitCalled) {
307
- FWGlobalState.getInstance().sdkInitCalledPromise.then(() => {
308
- this.setState({ sdkInitCalled: true });
306
+ if (!this.state.sdkInitSucceeded) {
307
+ FWGlobalState.getInstance().sdkInitSucceededPromise.then(() => {
308
+ this.setState({ sdkInitSucceeded: true });
309
309
  });
310
310
  }
311
311
 
@@ -407,7 +407,7 @@ class VideoFeed extends React.Component<IVideoFeedProps, IVideoFeedState> {
407
407
  * @ignore
408
408
  */
409
409
  render() {
410
- if (!this.state.sdkInitCalled) {
410
+ if (!this.state.sdkInitSucceeded) {
411
411
  return null;
412
412
  }
413
413
 
@@ -505,12 +505,15 @@ class VideoFeed extends React.Component<IVideoFeedProps, IVideoFeedState> {
505
505
  const shadowVideoFeedConfigurationJsonKey = gennerateJsonKey(
506
506
  videoFeedConfiguration?.shadow
507
507
  );
508
+ const feedCompleteAction = videoPlayerConfiguration?.feedCompleteAction;
508
509
  const shouldExtendMediaOutsideSafeArea =
509
510
  videoPlayerConfiguration?.shouldExtendMediaOutsideSafeArea;
510
511
  const statusBarHidden = videoPlayerConfiguration?.statusBarHidden;
511
512
  const statusBarStyle = videoPlayerConfiguration?.statusBarStyle;
512
513
  const pipPlacement = videoPlayerConfiguration?.pipPlacement;
513
514
  const scrollDirection = videoPlayerConfiguration?.scrollDirection;
515
+ const isArrowButtonVisible = videoPlayerConfiguration?.isArrowButtonVisible;
516
+ const ctaButtonStyle = videoPlayerConfiguration?.ctaButtonStyle;
514
517
  let key = `gShareBaseURL:${gShareBaseURL}`;
515
518
  if (Platform.OS === 'ios') {
516
519
  key += `_appLanguage:${appLanguage}`;
@@ -578,6 +581,10 @@ class VideoFeed extends React.Component<IVideoFeedProps, IVideoFeedState> {
578
581
  key += `_ctaHighlightDelayType:${ctaHighlightDelayType}`;
579
582
  key += `_ctaHighlightDelayValue:${ctaHighlightDelayValue}`;
580
583
  key += `_ctaWidth:${ctaWidth}`;
584
+ key += `_ctaButtonStyle.backgroundColor:${ctaButtonStyle?.backgroundColor}`;
585
+ key += `_ctaButtonStyle.textColor:${ctaButtonStyle?.textColor}`;
586
+ key += `_ctaButtonStyle.fontSize:${ctaButtonStyle?.fontSize}`;
587
+ key += `_ctaButtonStyle.shape:${ctaButtonStyle?.shape}`;
581
588
  key += `_buttonConfiguration.videoDetailButton:${this._generateButtonInfoString(
582
589
  buttonConfiguration?.videoDetailButton
583
590
  )}`;
@@ -607,11 +614,13 @@ class VideoFeed extends React.Component<IVideoFeedProps, IVideoFeedState> {
607
614
  key += `_replayBadgeVideoFeedConfiguration:${replayBadgeVideoFeedConfigurationJsonKey}`;
608
615
  key += `_replayBadgeVideoPlayerConfiguration:${replayBadgeVideoPlayerConfigurationJsonKey}`;
609
616
  key += `_shadowVideoFeedConfiguration:${shadowVideoFeedConfigurationJsonKey}`;
617
+ key += `_feedCompleteAction:${feedCompleteAction}`;
610
618
  key += `_shouldExtendMediaOutsideSafeArea:${shouldExtendMediaOutsideSafeArea}`;
611
619
  key += `_statusBarHidden:${statusBarHidden}`;
612
620
  key += `_statusBarStyle:${statusBarStyle}`;
613
621
  key += `_pipPlacement:${pipPlacement}`;
614
622
  key += `_scrollDirection:${scrollDirection}`;
623
+ key += `_isArrowButtonVisible:${isArrowButtonVisible}`;
615
624
 
616
625
  return (
617
626
  <FWVideoFeed
package/src/index.tsx CHANGED
@@ -25,10 +25,12 @@ import type AdConfiguration from './models/AdConfiguration';
25
25
  import type { VastAttribute } from './models/AdConfiguration';
26
26
  import type AndroidFontInfo from './models/AndroidFontInfo';
27
27
  import type ButtonInfo from './models/ButtonInfo';
28
+ import type { ButtonShape } from './models/ButtonShape';
28
29
  import type ControlsInset from './models/ControlsInset';
29
30
  import type CountdownTimerConfiguration from './models/CountdownTimerConfiguration';
30
31
  import type { CountdownTimerAppearanceMode } from './models/CountdownTimerConfiguration';
31
32
  import type { DataTrackingLevel } from './models/DataTrackingLevel';
33
+ import type { FeedCompleteAction } from './models/FeedCompleteAction';
32
34
  import type FeedItemDetails from './models/FeedItemDetails';
33
35
  import { FWComponentType } from './models/FWComponentType';
34
36
  import type FWError from './models/FWError';
@@ -157,6 +159,7 @@ export type {
157
159
  AdConfiguration,
158
160
  AndroidFontInfo,
159
161
  ButtonInfo,
162
+ ButtonShape,
160
163
  ClickProductCallback,
161
164
  ClickProductEvent,
162
165
  ControlsInset,
@@ -173,6 +176,7 @@ export type {
173
176
  CustomTapProductCardCallback,
174
177
  CustomTapProductCardEvent,
175
178
  DataTrackingLevel,
179
+ FeedCompleteAction,
176
180
  FeedItemDetails,
177
181
  FWError,
178
182
  GradientDrawable,
@@ -0,0 +1 @@
1
+ export type ButtonShape = 'roundRectangle' | 'oval';
@@ -1,3 +1,4 @@
1
1
  export default interface ControlsInset {
2
2
  top?: number;
3
+ bottom?: number;
3
4
  }
@@ -0,0 +1 @@
1
+ export type FeedCompleteAction = 'loop' | 'dismiss';
@@ -5,6 +5,7 @@ import type VideoPlayerButtonConfiguration from './VideoPlayerButtonConfiguratio
5
5
  import type { VideoPlayerCTADelay } from './VideoPlayerCTADelay';
6
6
  import type { VideoPlayerCTAStyle } from './VideoPlayerCTAStyle';
7
7
  import type { VideoPlayerCTAWidth } from './VideoPlayerCTAWidth';
8
+ import type { FeedCompleteAction } from './FeedCompleteAction';
8
9
  import type { VideoPlayerCompleteAction } from './VideoPlayerCompleteAction';
9
10
  import type { VideoPlayerLogoConfiguration } from './VideoPlayerLogoConfiguration';
10
11
  import type { VideoPlayerStyle } from './VideoPlayerStyle';
@@ -28,8 +29,8 @@ export interface StoryBlockConfiguration {
28
29
  */
29
30
  showShareButton?: boolean;
30
31
  /**
31
- * The style of CTA button style.
32
- * Only supported on iOS.
32
+ * The style of CTA button.
33
+ * Note: iOSFontInfo property is only supported on iOS.
33
34
  */
34
35
  ctaButtonStyle?: VideoPlayerCTAStyle;
35
36
  /**
@@ -85,7 +86,6 @@ export interface StoryBlockConfiguration {
85
86
 
86
87
  /**
87
88
  * Specifies the additional controls inset for embedded mode.
88
- * We support only the top inset on Android, while both top and bottom insets are supported on iOS.
89
89
  */
90
90
  additionalControlsInset?: ControlsInset;
91
91
 
@@ -124,4 +124,25 @@ export interface StoryBlockConfiguration {
124
124
  * This property only takes effect when scrollDirection is set to vertical.
125
125
  */
126
126
  enableScrollForVertical?: boolean;
127
+
128
+ /**
129
+ * Indicates if the navigation arrow buttons for switching between
130
+ * previous and next videos are enabled in embedded story block mode.
131
+ * Defaults to true.
132
+ */
133
+ isArrowButtonVisible?: boolean;
134
+
135
+ /**
136
+ * Indicates if the navigation arrow buttons for switching between
137
+ * previous and next videos are enabled in fullscreen mode.
138
+ * Defaults to true.
139
+ */
140
+ isFullscreenArrowButtonVisible?: boolean;
141
+
142
+ /**
143
+ * Behavior occurring after feed plays the last video.
144
+ * This property only applies to full screen mode.
145
+ * Defaults to loop.
146
+ */
147
+ feedCompleteAction?: FeedCompleteAction;
127
148
  }
@@ -1,8 +1,6 @@
1
1
  import type IOSFontInfo from './IOSFontInfo';
2
+ import type { ButtonShape } from './ButtonShape';
2
3
 
3
- /**
4
- * Only supported on iOS.
5
- */
6
4
  export interface VideoPlayerCTAStyle {
7
5
  /**
8
6
  * The background color of CTA button.
@@ -19,6 +17,11 @@ export interface VideoPlayerCTAStyle {
19
17
  * Defaults to 14.
20
18
  */
21
19
  fontSize?: number;
20
+ /**
21
+ * The shape of CTA button.
22
+ * Defaults to roundRectangle.
23
+ */
24
+ shape?: ButtonShape;
22
25
  /**
23
26
  * The iOS font info of CTA button.
24
27
  * The property is ignored when fontSize is not set.
@@ -2,6 +2,7 @@ import type VideoPlayerButtonConfiguration from './VideoPlayerButtonConfiguratio
2
2
  import type { VideoPlayerCTADelay } from './VideoPlayerCTADelay';
3
3
  import type { VideoPlayerCTAStyle } from './VideoPlayerCTAStyle';
4
4
  import type { VideoPlayerCTAWidth } from './VideoPlayerCTAWidth';
5
+ import type { FeedCompleteAction } from './FeedCompleteAction';
5
6
  import type { VideoPlayerCompleteAction } from './VideoPlayerCompleteAction';
6
7
  import type { VideoPlayerStyle } from './VideoPlayerStyle';
7
8
  import type { VideoPlayerLogoConfiguration } from './VideoPlayerLogoConfiguration';
@@ -28,7 +29,8 @@ export default interface VideoPlayerConfiguration {
28
29
  */
29
30
  showShareButton?: boolean;
30
31
  /**
31
- * The style of CTA button style. Only supported on iOS.
32
+ * The style of CTA button.
33
+ * Note: iOSFontInfo property is only supported on iOS.
32
34
  */
33
35
  ctaButtonStyle?: VideoPlayerCTAStyle;
34
36
  /**
@@ -114,4 +116,17 @@ export default interface VideoPlayerConfiguration {
114
116
  * Specifies the scroll direction.
115
117
  */
116
118
  scrollDirection?: ScrollDirection;
119
+
120
+ /**
121
+ * Indicates if the navigation arrow buttons for switching between
122
+ * previous and next videos are enabled.
123
+ * Defaults to true.
124
+ */
125
+ isArrowButtonVisible?: boolean;
126
+
127
+ /**
128
+ * Behavior occurring after feed plays the last video.
129
+ * Defaults to dismiss.
130
+ */
131
+ feedCompleteAction?: FeedCompleteAction;
117
132
  }
@@ -6,7 +6,6 @@ import {
6
6
 
7
7
  import { LINKING_ERROR } from '../constants/FWErrorMessage';
8
8
  import type AdBadgeConfiguration from '../models/AdBadgeConfiguration';
9
- import type SDKInitOptions from '../models/SDKInitOptions';
10
9
  import type TrackPurchaseParameters from '../models/TrackPurchaseParameters';
11
10
  import type VideoPlayerNativeConfiguration from '../models/VideoPlayerNativeConfiguration';
12
11
  import type { DataTrackingLevel } from '../models/DataTrackingLevel';
@@ -25,7 +24,6 @@ const FireworkSDKModule = NativeModules.FireworkSDK
25
24
  );
26
25
 
27
26
  interface IFireworkSDKModule extends NativeModule {
28
- init(options?: SDKInitOptions): Promise<any>;
29
27
  markInitCalled(): Promise<boolean>;
30
28
  openVideoPlayer(url: string, config?: VideoPlayerNativeConfiguration): void;
31
29
  setVideoFeedClickCallbackEnabled(enabled: boolean): void; // Only supported on iOS
@@ -2,9 +2,9 @@ import type { FWComponentType } from '../models/FWComponentType';
2
2
 
3
3
  class FWGlobalState {
4
4
  private static _instance?: FWGlobalState;
5
- private sdkInitCalledResolveFunc?: () => void;
6
- sdkInitCalledPromise: Promise<void>;
7
- sdkInitCalled: boolean = false;
5
+ private sdkInitSucceededResolveFunc?: () => void;
6
+ sdkInitSucceededPromise: Promise<void>;
7
+ sdkInitSucceeded: boolean = false;
8
8
  componentTypeByFeedIdMap = new Map<string, FWComponentType>();
9
9
 
10
10
  static getInstance() {
@@ -16,18 +16,18 @@ class FWGlobalState {
16
16
  }
17
17
 
18
18
  private constructor() {
19
- this.sdkInitCalledPromise = new Promise((resolve) => {
20
- this.sdkInitCalledResolveFunc = resolve;
19
+ this.sdkInitSucceededPromise = new Promise((resolve) => {
20
+ this.sdkInitSucceededResolveFunc = resolve;
21
21
  });
22
22
  }
23
23
 
24
- resolveSdkInitCalled() {
25
- if (this.sdkInitCalledResolveFunc) {
24
+ resolveSdkInitSucceeded() {
25
+ if (this.sdkInitSucceededResolveFunc) {
26
26
  // only call once
27
- this.sdkInitCalledResolveFunc();
28
- this.sdkInitCalledResolveFunc = undefined;
27
+ this.sdkInitSucceededResolveFunc();
28
+ this.sdkInitSucceededResolveFunc = undefined;
29
29
  }
30
- this.sdkInitCalled = true;
30
+ this.sdkInitSucceeded = true;
31
31
  }
32
32
  }
33
33