react-native-firework-sdk 2.0.0-beta.5 → 2.1.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.
- package/android/build.gradle +5 -3
- package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/StoryBlockFragment.kt +129 -0
- package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/StoryBlockFrameLayout.kt +84 -0
- package/android/src/main/java/com/fireworksdk/bridge/models/FWEventName.kt +2 -1
- package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfiguration.kt +18 -5
- package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfigurationDeserializer.kt +33 -9
- package/android/src/main/java/com/fireworksdk/bridge/models/FWShoppingCtaResult.kt +17 -0
- package/android/src/main/java/com/fireworksdk/bridge/models/FWShoppingCtaResultDeserializer.kt +33 -0
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWStoryBlockManager.kt +126 -45
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWVideoFeedManager.kt +6 -3
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FWVideoShoppingInterface.kt +2 -2
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWNavigatorModule.kt +9 -1
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt +81 -50
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +9 -2
- package/android/src/main/java/com/fireworksdk/bridge/utils/FWConfigUtil.kt +1 -1
- package/android/src/main/java/com/fireworksdk/bridge/utils/FWGlobalDataUtil.kt +4 -0
- package/android/src/main/java/com/fireworksdk/bridge/utils/FWLanguageUtil.kt +48 -16
- package/android/src/main/res/layout/fw_bridge_story_block.xml +24 -0
- package/ios/Components/StoryBlock.swift +33 -2
- package/ios/Components/StoryBlockManager.m +32 -0
- package/ios/Components/VideoFeed.swift +9 -29
- package/ios/Components/VideoFeedManager.m +11 -6
- package/ios/FireworkSdk.xcodeproj/project.pbxproj +378 -104
- package/ios/Models/NativeToRN/FireworkEventName.swift +3 -1
- package/ios/Models/RNToNative/RCTConvert+Shopping.swift +21 -0
- package/ios/Models/RNToNative/RCTConvert+VideoFeed.swift +27 -0
- package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +5 -1
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule.m +1 -0
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +30 -0
- package/ios/Modules/Shopping/ProductInfoViewConfiguration.swift +13 -0
- package/ios/Modules/Shopping/ShoppingCTAResult.swift +16 -0
- package/ios/Modules/Shopping/ShoppingModule.m +2 -1
- package/ios/Modules/Shopping/ShoppingModule.swift +106 -30
- package/ios/Support/MultiHostStreaming/FWMultiHostStreaming.podspec +24 -0
- package/ios/Support/MultiHostStreaming/src/MultiHostStreamingSDK.swift +17 -0
- package/ios/Utils/AppLanguage/Bundle+FWSwizzle.swift +58 -0
- package/ios/Utils/AppLanguage/FWAppLanguageManager.swift +139 -0
- package/ios/Utils/AppLanguage/FWLanguageUtil.swift +43 -0
- package/ios/Utils/AppLanguage/NumberFormatter+FWSwizzle.swift +25 -0
- package/ios/Utils/AppLanguage/UIImageView+FWSwizzle.swift +91 -0
- package/ios/Utils/AppLanguage/UILabel+FWSwizzle.swift +98 -0
- package/ios/Utils/AppLanguage/UITextField+FWSwizzle.swift +97 -0
- package/ios/Utils/AppLanguage/UITextView+FWSwizzle.swift +97 -0
- package/ios/Utils/AppLanguage/UIView+FWSwizzle.swift +38 -0
- package/ios/Utils/AppLanguage/UIViewController+FWSwizzle.swift +32 -0
- package/ios/Utils/AppLanguage/UIWindow+FWSwizzle.swift +26 -0
- package/ios/Utils/AppLanguage/URLSession+FWSwizzle.swift +69 -0
- package/ios/Utils/{DispatchQueue+FWOnce.swift → Extensions/DispatchQueue+FWOnce.swift} +3 -3
- package/ios/Utils/{UINavigationController+FWSwizzle.swift → Extensions/Swizzle/UINavigationController+FWSwizzle.swift} +6 -8
- package/ios/Utils/Extensions/UIView+FWUIHierarchy.swift +47 -0
- package/ios/Utils/FWRTL/Classes/Manager/FWRTLManager.h +25 -0
- package/ios/Utils/FWRTL/Classes/Manager/FWRTLManager.m +75 -0
- package/ios/Utils/FWRTL/Classes/UICategories/CALayer+FWRTL.h +21 -0
- package/ios/Utils/FWRTL/Classes/UICategories/CALayer+FWRTL.m +124 -0
- package/ios/Utils/FWRTL/Classes/UICategories/FWRTLRemoteViewControllerAdaptor.h +11 -0
- package/ios/Utils/FWRTL/Classes/UICategories/FWRTLRemoteViewControllerAdaptor.m +86 -0
- package/ios/Utils/FWRTL/Classes/UICategories/FWRTLWhiteListManager.h +16 -0
- package/ios/Utils/FWRTL/Classes/UICategories/FWRTLWhiteListManager.m +55 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UILabel+FWRTL.h +18 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UILabel+FWRTL.m +39 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UIView+FWRTL.h +54 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UIView+FWRTL.m +141 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UIWindow+FWRTL.h +16 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UIWindow+FWRTL.m +20 -0
- package/ios/Utils/FWRTL/Classes/Utils/FWRTLDefinitions.h +52 -0
- package/ios/Utils/FWRTL/Classes/Utils/NSObject+FWRTLReloadBlock.h +19 -0
- package/ios/Utils/FWRTL/Classes/Utils/NSObject+FWRTLReloadBlock.m +49 -0
- package/ios/Utils/FWRTL/Classes/Utils/NSString+FWRTL.h +21 -0
- package/ios/Utils/FWRTL/Classes/Utils/NSString+FWRTL.m +38 -0
- package/ios/Utils/FWRTL/Classes/Utils/UIImage+FWRTL.h +18 -0
- package/ios/Utils/FWRTL/Classes/Utils/UIImage+FWRTL.m +43 -0
- package/ios/Utils/FWSwizzleLoader.m +6 -1
- package/ios/Utils/FWSwizzleLoader.swift +13 -0
- package/ios/Utils/FWSwizzleUtil.swift +17 -9
- package/ios/react_native_firework_sdk.h +1 -0
- package/ios/scripts/react_native_firework_sdk_pods.rb +31 -0
- package/lib/commonjs/FireworkSDK.js +21 -4
- package/lib/commonjs/FireworkSDK.js.map +1 -1
- package/lib/commonjs/VideoShopping.js +20 -37
- package/lib/commonjs/VideoShopping.js.map +1 -1
- package/lib/commonjs/components/StoryBlock.js +193 -116
- package/lib/commonjs/components/StoryBlock.js.map +1 -1
- package/lib/commonjs/components/VideoFeed.js +32 -10
- package/lib/commonjs/components/VideoFeed.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/FWEventName.js +2 -0
- package/lib/commonjs/models/FWEventName.js.map +1 -1
- package/lib/commonjs/models/ShoppingCTAResult.js +2 -0
- package/lib/commonjs/modules/FireworkSDKModule.js.map +1 -1
- package/lib/commonjs/modules/ShoppingModule.js.map +1 -1
- package/lib/module/FireworkSDK.js +21 -4
- package/lib/module/FireworkSDK.js.map +1 -1
- package/lib/module/VideoShopping.js +20 -39
- package/lib/module/VideoShopping.js.map +1 -1
- package/lib/module/components/StoryBlock.js +181 -116
- package/lib/module/components/StoryBlock.js.map +1 -1
- package/lib/module/components/VideoFeed.js +37 -10
- package/lib/module/components/VideoFeed.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/FWEventName.js +2 -0
- package/lib/module/models/FWEventName.js.map +1 -1
- package/lib/module/models/ShoppingCTAResult.js +2 -0
- package/lib/module/modules/FireworkSDKModule.js.map +1 -1
- package/lib/module/modules/ShoppingModule.js.map +1 -1
- package/lib/typescript/FireworkSDK.d.ts +7 -4
- package/lib/typescript/VideoShopping.d.ts +9 -11
- package/lib/typescript/components/StoryBlock.d.ts +19 -16
- package/lib/typescript/components/VideoFeed.d.ts +15 -6
- package/lib/typescript/index.d.ts +6 -6
- package/lib/typescript/models/FWEventName.d.ts +2 -0
- package/lib/typescript/models/FWEvents.d.ts +14 -1
- package/lib/typescript/models/ProductInfoViewConfiguration.d.ts +36 -1
- package/lib/typescript/models/ShoppingCTAResult.d.ts +11 -0
- package/lib/typescript/modules/FireworkSDKModule.d.ts +1 -2
- package/lib/typescript/modules/ShoppingModule.d.ts +2 -1
- package/package.json +5 -4
- package/react-native-firework-sdk.podspec +26 -24
- package/src/FireworkSDK.ts +18 -5
- package/src/VideoShopping.ts +40 -53
- package/src/components/StoryBlock.tsx +201 -88
- package/src/components/VideoFeed.tsx +32 -12
- package/src/index.ts +15 -7
- package/src/models/FWEventName.ts +2 -0
- package/src/models/FWEvents.ts +14 -1
- package/src/models/ProductInfoViewConfiguration.ts +38 -1
- package/src/models/ShoppingCTAResult.ts +11 -0
- package/src/modules/FireworkSDKModule.ts +1 -2
- package/src/modules/ShoppingModule.ts +5 -5
- package/android/src/main/java/com/fireworksdk/bridge/constants/FWCommandConstant.kt +0 -6
- package/ios/Utils/UIView+ParentViewController.swift +0 -21
- package/lib/commonjs/models/AddToCartResult.js +0 -2
- package/lib/module/models/AddToCartResult.js +0 -2
- package/lib/typescript/models/AddToCartResult.d.ts +0 -10
- package/src/models/AddToCartResult.ts +0 -10
- /package/ios/Utils/{String+Color.swift → Extensions/String+Color.swift} +0 -0
- /package/ios/Utils/{UIView+Constraints.swift → Extensions/UIView+Constraints.swift} +0 -0
- /package/ios/Utils/{UIViewController+AttachChild.swift → Extensions/UIViewController+AttachChild.swift} +0 -0
- /package/lib/commonjs/models/{AddToCartResult.js.map → ShoppingCTAResult.js.map} +0 -0
- /package/lib/module/models/{AddToCartResult.js.map → ShoppingCTAResult.js.map} +0 -0
package/src/VideoShopping.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { NativeEventEmitter, Platform } from 'react-native';
|
|
2
2
|
|
|
3
|
-
import type AddToCartResult from './models/AddToCartResult';
|
|
4
3
|
import { FWEventName } from './models/FWEventName';
|
|
5
4
|
import type {
|
|
6
|
-
AddToCartEvent,
|
|
7
5
|
CustomClickLinkButtonEvent,
|
|
6
|
+
ShoppingCTAEvent,
|
|
8
7
|
UpdateProductDetailsEvent,
|
|
9
8
|
} from './models/FWEvents';
|
|
10
9
|
import type Product from './models/Product';
|
|
@@ -13,10 +12,11 @@ import ShoppingModule, {
|
|
|
13
12
|
ShoppingModuleEventEmitter,
|
|
14
13
|
} from './modules/ShoppingModule';
|
|
15
14
|
import FWLoggerUtil from './utils/FWLoggerUtil';
|
|
15
|
+
import type ShoppingCTAResult from './models/ShoppingCTAResult';
|
|
16
16
|
|
|
17
|
-
export type
|
|
18
|
-
event:
|
|
19
|
-
) => Promise<
|
|
17
|
+
export type ShoppingCTACallback = (
|
|
18
|
+
event: ShoppingCTAEvent
|
|
19
|
+
) => Promise<ShoppingCTAResult>;
|
|
20
20
|
|
|
21
21
|
export type CustomClickCartIconCallback = () => Promise<void>;
|
|
22
22
|
|
|
@@ -35,12 +35,10 @@ class VideoShopping {
|
|
|
35
35
|
private static _instance?: VideoShopping;
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* This callback is triggered when the user clicks the "Add to cart" button.
|
|
39
|
-
*
|
|
40
|
-
* The host apps can return an AddToCartResult object to tell FireworkSDK the result of adding to cart.
|
|
41
|
-
* If the host apps want to customize the processing logic of clicking "Add to cart" button, they could return null or undefined in the callback.
|
|
38
|
+
* This callback is triggered when the user clicks the "Add to cart" or "Shop now" button.
|
|
39
|
+
* The host app can return a ShoppingCTAResult object to tell SDK how to handle the result.
|
|
42
40
|
*/
|
|
43
|
-
public
|
|
41
|
+
public onShoppingCTA?: ShoppingCTACallback;
|
|
44
42
|
|
|
45
43
|
/**
|
|
46
44
|
* This callback is triggered when the user clicks the shopping cart icon.
|
|
@@ -82,8 +80,8 @@ class VideoShopping {
|
|
|
82
80
|
private _cartIconVisible: boolean = true;
|
|
83
81
|
|
|
84
82
|
/**
|
|
85
|
-
* The
|
|
86
|
-
*
|
|
83
|
+
* The configuration of product info view.
|
|
84
|
+
* Please refer to {@link ProductInfoViewConfiguration} for more details.
|
|
87
85
|
*/
|
|
88
86
|
public get productInfoViewConfiguration():
|
|
89
87
|
| ProductInfoViewConfiguration
|
|
@@ -95,9 +93,7 @@ class VideoShopping {
|
|
|
95
93
|
value: ProductInfoViewConfiguration | undefined
|
|
96
94
|
) {
|
|
97
95
|
this._productInfoViewConfiguration = value;
|
|
98
|
-
|
|
99
|
-
ShoppingModule.setProductInfoViewConfiguration(value ?? {});
|
|
100
|
-
}
|
|
96
|
+
ShoppingModule.setProductInfoViewConfiguration(value ?? {});
|
|
101
97
|
}
|
|
102
98
|
|
|
103
99
|
private _productInfoViewConfiguration?:
|
|
@@ -120,9 +116,7 @@ class VideoShopping {
|
|
|
120
116
|
value: CustomClickLinkButtonCallback | undefined
|
|
121
117
|
) {
|
|
122
118
|
this._onCustomClickLinkButton = value;
|
|
123
|
-
|
|
124
|
-
ShoppingModule.setCustomClickLinkButtonEnabled(!!value);
|
|
125
|
-
}
|
|
119
|
+
ShoppingModule.setCustomClickLinkButtonEnabled(!!value);
|
|
126
120
|
}
|
|
127
121
|
private _onCustomClickLinkButton?: CustomClickLinkButtonCallback | undefined;
|
|
128
122
|
|
|
@@ -140,12 +134,15 @@ class VideoShopping {
|
|
|
140
134
|
}
|
|
141
135
|
|
|
142
136
|
private constructor() {
|
|
143
|
-
this.eventEmitter.addListener(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
137
|
+
this.eventEmitter.addListener(
|
|
138
|
+
FWEventName.ShoppingCTAButtonClick,
|
|
139
|
+
(event) => {
|
|
140
|
+
FWLoggerUtil.log(
|
|
141
|
+
`Receive ShoppingCTA event productId: ${event?.productId} unitId: ${event?.unitId} url: ${event?.url}`
|
|
142
|
+
);
|
|
143
|
+
this.handleShoppingCTAEvent(event);
|
|
144
|
+
}
|
|
145
|
+
);
|
|
149
146
|
|
|
150
147
|
this.eventEmitter.addListener(FWEventName.ClickCartIcon, () => {
|
|
151
148
|
FWLoggerUtil.log('Receive ClickCartIcon event');
|
|
@@ -161,17 +158,15 @@ class VideoShopping {
|
|
|
161
158
|
|
|
162
159
|
this.eventEmitter.addListener(FWEventName.LogMessage, () => {});
|
|
163
160
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
(
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
);
|
|
174
|
-
}
|
|
161
|
+
this.eventEmitter.addListener(
|
|
162
|
+
FWEventName.CustomLinkButtonClick,
|
|
163
|
+
(event) => {
|
|
164
|
+
FWLoggerUtil.log(
|
|
165
|
+
`Receive CustomLinkButtonClick event url: ${event?.url}`
|
|
166
|
+
);
|
|
167
|
+
this.handleCustomLinkButtonClickEvent(event);
|
|
168
|
+
}
|
|
169
|
+
);
|
|
175
170
|
}
|
|
176
171
|
|
|
177
172
|
/**
|
|
@@ -186,30 +181,22 @@ class VideoShopping {
|
|
|
186
181
|
ShoppingModule.setCartItemCount(count);
|
|
187
182
|
}
|
|
188
183
|
|
|
189
|
-
private async
|
|
184
|
+
private async handleShoppingCTAEvent(event: any) {
|
|
190
185
|
const callbackId = event.callbackId;
|
|
191
186
|
delete event.callbackId;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
result.res,
|
|
198
|
-
result.tips,
|
|
199
|
-
callbackId
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
} else {
|
|
203
|
-
if (callbackId) {
|
|
204
|
-
if (Platform.OS === 'ios') {
|
|
205
|
-
ShoppingModule.clearCallbackId(callbackId, FWEventName.AddToCart);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
187
|
+
|
|
188
|
+
if (this.onShoppingCTA) {
|
|
189
|
+
const result = await this.onShoppingCTA(event as ShoppingCTAEvent);
|
|
190
|
+
if (callbackId) {
|
|
191
|
+
ShoppingModule.updateShoppingCTAResult(result, callbackId);
|
|
208
192
|
}
|
|
209
193
|
} else {
|
|
210
194
|
if (callbackId) {
|
|
211
195
|
if (Platform.OS === 'ios') {
|
|
212
|
-
ShoppingModule.clearCallbackId(
|
|
196
|
+
ShoppingModule.clearCallbackId(
|
|
197
|
+
callbackId,
|
|
198
|
+
FWEventName.ShoppingCTAButtonClick
|
|
199
|
+
);
|
|
213
200
|
}
|
|
214
201
|
}
|
|
215
202
|
}
|
|
@@ -1,14 +1,25 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { ForwardRefRenderFunction } from 'react';
|
|
2
|
+
import React, {
|
|
3
|
+
forwardRef,
|
|
4
|
+
useEffect,
|
|
5
|
+
useImperativeHandle,
|
|
6
|
+
useReducer,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from 'react';
|
|
2
10
|
|
|
3
|
-
import
|
|
4
|
-
|
|
11
|
+
import {
|
|
12
|
+
BackHandler,
|
|
13
|
+
findNodeHandle,
|
|
5
14
|
NativeSyntheticEvent,
|
|
15
|
+
Platform,
|
|
6
16
|
StyleProp,
|
|
17
|
+
UIManager,
|
|
7
18
|
ViewStyle,
|
|
8
19
|
} from 'react-native';
|
|
9
|
-
import { findNodeHandle, Platform, UIManager } from 'react-native';
|
|
10
20
|
|
|
11
21
|
import FireworkSDK from '../FireworkSDK';
|
|
22
|
+
import type AdConfiguration from '../models/AdConfiguration';
|
|
12
23
|
import type FWError from '../models/FWError';
|
|
13
24
|
import { FWEventName } from '../models/FWEventName';
|
|
14
25
|
import type { StoryBlockSource } from '../models/StoryBlockSource';
|
|
@@ -18,17 +29,16 @@ import FWStoryBlock from './FWStoryBlock';
|
|
|
18
29
|
|
|
19
30
|
const NativeComponentName = 'FWStoryBlock';
|
|
20
31
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
};
|
|
32
|
+
export interface IStoryBlockMethods {
|
|
33
|
+
/**
|
|
34
|
+
* Play the story block.
|
|
35
|
+
*/
|
|
36
|
+
play: () => void;
|
|
37
|
+
/**
|
|
38
|
+
* Pause the story block.
|
|
39
|
+
*/
|
|
40
|
+
pause: () => void;
|
|
41
|
+
}
|
|
32
42
|
|
|
33
43
|
/**
|
|
34
44
|
* The props type of StoryBlock component.
|
|
@@ -55,88 +65,119 @@ export interface IStoryBlockProps {
|
|
|
55
65
|
*/
|
|
56
66
|
dynamicContentParameters?: { [key: string]: string[] };
|
|
57
67
|
/**
|
|
58
|
-
* Specifies if Picture in Picture is enabled.
|
|
68
|
+
* Specifies if Picture in Picture is enabled. Only supported on iOS.
|
|
59
69
|
*/
|
|
60
70
|
enablePictureInPicture?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Ad configuration of the feed. Only supported on iOS.
|
|
73
|
+
*/
|
|
74
|
+
adConfiguration?: AdConfiguration;
|
|
61
75
|
/**
|
|
62
76
|
* The feed loading result callback. It means loading successfully when error equals to undefined.
|
|
63
77
|
*/
|
|
64
78
|
onStoryBlockLoadFinished?: (error?: FWError) => void;
|
|
65
79
|
}
|
|
66
80
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
nativeComponentRef =
|
|
81
|
+
const StoryBlock: ForwardRefRenderFunction<
|
|
82
|
+
IStoryBlockMethods,
|
|
83
|
+
IStoryBlockProps
|
|
84
|
+
> = (props: IStoryBlockProps, forwardedRef) => {
|
|
85
|
+
const nativeComponentRef = useRef(null);
|
|
86
|
+
const [isFullscreenState, setIsFullscreenState] = useState<boolean>(false);
|
|
87
|
+
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
88
|
+
useImperativeHandle(
|
|
89
|
+
forwardedRef,
|
|
90
|
+
() => {
|
|
91
|
+
const sendCommand = (command: string) => {
|
|
92
|
+
const nativeNodeHandle = findNodeHandle(nativeComponentRef.current);
|
|
72
93
|
|
|
73
|
-
|
|
74
|
-
|
|
94
|
+
let commandId: string | number =
|
|
95
|
+
UIManager.getViewManagerConfig(NativeComponentName).Commands[command];
|
|
96
|
+
if (Platform.OS === 'android') {
|
|
97
|
+
commandId = commandId.toString();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
UIManager.dispatchViewManagerCommand(
|
|
101
|
+
findNodeHandle(nativeNodeHandle),
|
|
102
|
+
commandId,
|
|
103
|
+
[]
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
play: () => {
|
|
108
|
+
sendCommand('play');
|
|
109
|
+
},
|
|
110
|
+
pause: () => {
|
|
111
|
+
sendCommand('pause');
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
[]
|
|
116
|
+
);
|
|
117
|
+
useEffect(() => {
|
|
75
118
|
const subscriptionOfShareBaseURLUpdated =
|
|
76
119
|
FireworkSDKModuleEventEmitter.addListener(
|
|
77
120
|
FWEventName.ShareBaseURLUpdated,
|
|
78
121
|
() => {
|
|
79
|
-
|
|
122
|
+
FWLoggerUtil.log('Receive FWEventName.ShareBaseURLUpdated');
|
|
123
|
+
forceUpdate();
|
|
80
124
|
}
|
|
81
125
|
);
|
|
82
|
-
this.subscriptions.push(subscriptionOfShareBaseURLUpdated);
|
|
83
|
-
|
|
84
126
|
const subscriptionOfAdBadgeConfigurationUpdated =
|
|
85
127
|
FireworkSDKModuleEventEmitter.addListener(
|
|
86
128
|
FWEventName.AdBadgeConfigurationUpdated,
|
|
87
129
|
() => {
|
|
88
|
-
|
|
130
|
+
FWLoggerUtil.log('Receive FWEventName.AdBadgeConfigurationUpdated');
|
|
131
|
+
forceUpdate();
|
|
89
132
|
}
|
|
90
133
|
);
|
|
91
|
-
this.subscriptions.push(subscriptionOfAdBadgeConfigurationUpdated);
|
|
92
134
|
|
|
93
135
|
const subscriptionOfVideoLaunchBehaviorUpdated =
|
|
94
136
|
FireworkSDKModuleEventEmitter.addListener(
|
|
95
137
|
FWEventName.VideoLaunchBehaviorUpdated,
|
|
96
138
|
() => {
|
|
97
139
|
FWLoggerUtil.log('Receive FWEventName.VideoLaunchBehaviorUpdated');
|
|
98
|
-
|
|
140
|
+
forceUpdate();
|
|
99
141
|
}
|
|
100
142
|
);
|
|
101
|
-
this.subscriptions.push(subscriptionOfVideoLaunchBehaviorUpdated);
|
|
102
143
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
144
|
+
const subscriptionOfAppLanguageUpdated =
|
|
145
|
+
FireworkSDKModuleEventEmitter.addListener(
|
|
146
|
+
FWEventName.AppLanguageUpdated,
|
|
147
|
+
() => {
|
|
148
|
+
FWLoggerUtil.log('Receive FWEventName.AppLanguageUpdated');
|
|
149
|
+
forceUpdate();
|
|
150
|
+
}
|
|
107
151
|
);
|
|
108
|
-
|
|
152
|
+
|
|
153
|
+
if (Platform.OS === 'android') {
|
|
154
|
+
setTimeout(() => {
|
|
155
|
+
const viewId = findNodeHandle(nativeComponentRef.current);
|
|
156
|
+
FWLoggerUtil.log(`StoryBlock createFragment viewId: ${viewId}`);
|
|
157
|
+
UIManager.dispatchViewManagerCommand(
|
|
158
|
+
viewId,
|
|
159
|
+
UIManager.getViewManagerConfig(
|
|
160
|
+
NativeComponentName
|
|
161
|
+
).Commands.create.toString(),
|
|
162
|
+
[viewId]
|
|
163
|
+
);
|
|
164
|
+
}, 500);
|
|
109
165
|
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
componentWillUnmount() {
|
|
113
|
-
this.subscriptions.forEach((value) => {
|
|
114
|
-
value.remove();
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
this.subscriptions = [];
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
render() {
|
|
121
|
-
const { style } = this.props;
|
|
122
|
-
|
|
123
|
-
return (
|
|
124
|
-
<FWStoryBlock
|
|
125
|
-
ref={this.nativeComponentRef}
|
|
126
|
-
key={this._generateKey()}
|
|
127
|
-
{...this.props}
|
|
128
|
-
onStoryBlockLoadFinished={this._onStoryBlockLoadFinished}
|
|
129
|
-
style={Object.assign({}, style, { zIndex: -1 })}
|
|
130
|
-
/>
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
166
|
|
|
134
|
-
|
|
167
|
+
return () => {
|
|
168
|
+
subscriptionOfShareBaseURLUpdated.remove();
|
|
169
|
+
subscriptionOfAdBadgeConfigurationUpdated.remove();
|
|
170
|
+
subscriptionOfVideoLaunchBehaviorUpdated.remove();
|
|
171
|
+
subscriptionOfAppLanguageUpdated.remove();
|
|
172
|
+
};
|
|
173
|
+
}, []);
|
|
174
|
+
|
|
175
|
+
const handleStoryBlockLoadFinished = (event: NativeSyntheticEvent<any>) => {
|
|
135
176
|
FWLoggerUtil.log(
|
|
136
|
-
`StoryBlock
|
|
177
|
+
`StoryBlock handleStoryBlockLoadFinished ${event.nativeEvent.name}`
|
|
137
178
|
);
|
|
138
179
|
|
|
139
|
-
const { onStoryBlockLoadFinished } =
|
|
180
|
+
const { onStoryBlockLoadFinished } = props;
|
|
140
181
|
const { name, reason } = event.nativeEvent;
|
|
141
182
|
|
|
142
183
|
if (onStoryBlockLoadFinished) {
|
|
@@ -152,60 +193,132 @@ class StoryBlock extends React.Component<IStoryBlockProps> {
|
|
|
152
193
|
}
|
|
153
194
|
};
|
|
154
195
|
|
|
155
|
-
|
|
196
|
+
const handleStoryBlockFullscreenStateChanged = (
|
|
197
|
+
event: NativeSyntheticEvent<any>
|
|
198
|
+
) => {
|
|
199
|
+
FWLoggerUtil.log(
|
|
200
|
+
`StoryBlock handleStoryBlockFullscreenStateChanged ${event.nativeEvent.isFullScreen}`
|
|
201
|
+
);
|
|
202
|
+
const { isFullScreen } = event.nativeEvent;
|
|
203
|
+
setIsFullscreenState(isFullScreen);
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const generateDynamicContentParametersString = (): string => {
|
|
207
|
+
const { dynamicContentParameters } = props;
|
|
208
|
+
|
|
209
|
+
if (!dynamicContentParameters) {
|
|
210
|
+
return '';
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
let resultString = '';
|
|
214
|
+
const sortedKeyList = Object.keys(dynamicContentParameters).sort();
|
|
215
|
+
for (const key of sortedKeyList) {
|
|
216
|
+
const value = dynamicContentParameters[key];
|
|
217
|
+
const valueString = value.join(',');
|
|
218
|
+
if (resultString.length > 0) {
|
|
219
|
+
resultString += '_';
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
resultString += `${key}:${valueString}`;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return resultString;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const generateVastAttributesString = () => {
|
|
229
|
+
const { adConfiguration } = props;
|
|
230
|
+
const vastAttributes = adConfiguration?.vastAttributes ?? '';
|
|
231
|
+
if (!vastAttributes) {
|
|
232
|
+
return '';
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let resultString = '';
|
|
236
|
+
for (const attribute of vastAttributes) {
|
|
237
|
+
if (resultString.length > 0) {
|
|
238
|
+
resultString += '_';
|
|
239
|
+
}
|
|
240
|
+
resultString += `${attribute.name ?? ''}:${attribute.value}`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return resultString;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const generateKey = (): string => {
|
|
156
247
|
const {
|
|
157
248
|
source,
|
|
158
249
|
channel = '',
|
|
159
250
|
playlist = '',
|
|
160
251
|
enablePictureInPicture = false,
|
|
161
|
-
|
|
252
|
+
adConfiguration,
|
|
253
|
+
} = props;
|
|
162
254
|
|
|
163
255
|
const shareBaseURL = FireworkSDK.getInstance().getShareBaseURL() ?? '';
|
|
256
|
+
const videoLaunchBehavior =
|
|
257
|
+
FireworkSDK.getInstance().getVideoLaunchBehavior();
|
|
164
258
|
const adBadgeConfiguration =
|
|
165
259
|
FireworkSDK.getInstance().getAdBadgeConfiguration() ?? {};
|
|
166
260
|
const adBadgeTextType = adBadgeConfiguration.badgeTextType ?? '';
|
|
167
261
|
const backgroundColorOfAdBadge = adBadgeConfiguration.backgroundColor ?? '';
|
|
168
262
|
const textColorOfAdBadge = adBadgeConfiguration.textColor ?? '';
|
|
169
263
|
const dynamicContentParametersString =
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
264
|
+
generateDynamicContentParametersString();
|
|
265
|
+
const appLanguage = FireworkSDK.getInstance().appLanguage ?? '';
|
|
266
|
+
const requiresAds = adConfiguration?.requiresAds ?? false;
|
|
267
|
+
const adsFetchTimeout = adConfiguration?.adsFetchTimeout ?? 10;
|
|
268
|
+
const vastAttributesString = generateVastAttributesString();
|
|
173
269
|
|
|
174
270
|
let key = `source:${source}`;
|
|
175
271
|
key += `_channel:${channel}`;
|
|
176
272
|
key += `_playlist:${playlist}`;
|
|
177
273
|
key += `_shareBaseURL:${shareBaseURL}`;
|
|
274
|
+
key += `_videoLaunchBehavior:${videoLaunchBehavior}`;
|
|
178
275
|
key += `_adBadgeTextType:${adBadgeTextType}`;
|
|
179
276
|
key += `_backgroundColorOfAdBadge:${backgroundColorOfAdBadge}`;
|
|
180
277
|
key += `_textColorOfAdBadge:${textColorOfAdBadge}`;
|
|
181
278
|
key += `_dynamicContentParameters:${dynamicContentParametersString}`;
|
|
182
279
|
key += `_enablePictureInPicture:${enablePictureInPicture}`;
|
|
183
|
-
key += `
|
|
280
|
+
key += `_appLanguage:${appLanguage}`;
|
|
281
|
+
key += `_requiresAds:${requiresAds}`;
|
|
282
|
+
key += `_adsFetchTimeout:${adsFetchTimeout}`;
|
|
283
|
+
key += `_vastAttributes:${vastAttributesString}`;
|
|
184
284
|
|
|
185
285
|
return key;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
private _generateDynamicContentParametersString(): string {
|
|
189
|
-
const { dynamicContentParameters } = this.props;
|
|
286
|
+
};
|
|
190
287
|
|
|
191
|
-
|
|
192
|
-
|
|
288
|
+
useEffect(() => {
|
|
289
|
+
if (Platform.OS === 'android') {
|
|
290
|
+
const onBackPress = () => {
|
|
291
|
+
if (isFullscreenState) {
|
|
292
|
+
FireworkSDK.getInstance().navigator.popNativeContainer();
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
return false;
|
|
296
|
+
};
|
|
297
|
+
const subscription = BackHandler.addEventListener(
|
|
298
|
+
'hardwareBackPress',
|
|
299
|
+
onBackPress
|
|
300
|
+
);
|
|
301
|
+
return () => {
|
|
302
|
+
subscription.remove();
|
|
303
|
+
};
|
|
193
304
|
}
|
|
194
305
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
for (const key of sortedKeyList) {
|
|
198
|
-
const value = dynamicContentParameters[key];
|
|
199
|
-
const valueString = value.join(',');
|
|
200
|
-
if (resultString.length > 0) {
|
|
201
|
-
resultString += '_';
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
resultString += `${key}:${valueString}`;
|
|
205
|
-
}
|
|
306
|
+
return;
|
|
307
|
+
}, [isFullscreenState]);
|
|
206
308
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
309
|
+
const { style } = props;
|
|
310
|
+
return (
|
|
311
|
+
<FWStoryBlock
|
|
312
|
+
ref={nativeComponentRef}
|
|
313
|
+
key={generateKey()}
|
|
314
|
+
{...props}
|
|
315
|
+
onStoryBlockLoadFinished={handleStoryBlockLoadFinished}
|
|
316
|
+
onStoryBlockFullScreenStateChanged={
|
|
317
|
+
handleStoryBlockFullscreenStateChanged
|
|
318
|
+
}
|
|
319
|
+
style={Object.assign({}, style, { zIndex: -1 })}
|
|
320
|
+
/>
|
|
321
|
+
);
|
|
322
|
+
};
|
|
210
323
|
|
|
211
|
-
export default StoryBlock;
|
|
324
|
+
export default forwardRef(StoryBlock);
|
|
@@ -83,21 +83,21 @@ const NativeComponentName = 'FWVideoFeed';
|
|
|
83
83
|
* VideoFeed component.
|
|
84
84
|
*/
|
|
85
85
|
class VideoFeed extends React.Component<IVideoFeedProps> {
|
|
86
|
+
/**
|
|
87
|
+
* @ignore
|
|
88
|
+
*/
|
|
86
89
|
static defaultProps = {
|
|
87
90
|
mode: 'row',
|
|
88
91
|
};
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
private _nativeComponentRef = React.createRef<any>();
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
private _subscriptions: EmitterSubscription[] = [];
|
|
93
96
|
|
|
94
|
-
/**
|
|
95
|
-
* Force refreshing the video feed.
|
|
96
|
-
*/
|
|
97
97
|
public refresh = () => {
|
|
98
98
|
FWLoggerUtil.log(`VideoFeed refresh ${JSON.stringify(this.props)}`);
|
|
99
99
|
|
|
100
|
-
const nativeNodeHandle = findNodeHandle(this.
|
|
100
|
+
const nativeNodeHandle = findNodeHandle(this._nativeComponentRef.current);
|
|
101
101
|
|
|
102
102
|
let commandId: string | number =
|
|
103
103
|
UIManager.getViewManagerConfig(NativeComponentName).Commands.refresh;
|
|
@@ -133,6 +133,9 @@ class VideoFeed extends React.Component<IVideoFeedProps> {
|
|
|
133
133
|
}
|
|
134
134
|
};
|
|
135
135
|
|
|
136
|
+
/**
|
|
137
|
+
* @ignore
|
|
138
|
+
*/
|
|
136
139
|
componentDidMount() {
|
|
137
140
|
FWLoggerUtil.log(
|
|
138
141
|
`VideoFeed componentDidMount ${JSON.stringify(this.props)}`
|
|
@@ -146,7 +149,7 @@ class VideoFeed extends React.Component<IVideoFeedProps> {
|
|
|
146
149
|
this.setState({});
|
|
147
150
|
}
|
|
148
151
|
);
|
|
149
|
-
this.
|
|
152
|
+
this._subscriptions.push(subscriptionOfShareBaseURLUpdated);
|
|
150
153
|
|
|
151
154
|
const subscriptionOfAdBadgeConfigurationUpdated =
|
|
152
155
|
FireworkSDKModuleEventEmitter.addListener(
|
|
@@ -156,7 +159,7 @@ class VideoFeed extends React.Component<IVideoFeedProps> {
|
|
|
156
159
|
this.setState({});
|
|
157
160
|
}
|
|
158
161
|
);
|
|
159
|
-
this.
|
|
162
|
+
this._subscriptions.push(subscriptionOfAdBadgeConfigurationUpdated);
|
|
160
163
|
|
|
161
164
|
const subscriptionOfVideoLaunchBehaviorUpdated =
|
|
162
165
|
FireworkSDKModuleEventEmitter.addListener(
|
|
@@ -166,21 +169,36 @@ class VideoFeed extends React.Component<IVideoFeedProps> {
|
|
|
166
169
|
this.setState({});
|
|
167
170
|
}
|
|
168
171
|
);
|
|
169
|
-
this.
|
|
172
|
+
this._subscriptions.push(subscriptionOfVideoLaunchBehaviorUpdated);
|
|
173
|
+
const subscriptionOfAppLanguageUpdated =
|
|
174
|
+
FireworkSDKModuleEventEmitter.addListener(
|
|
175
|
+
FWEventName.AppLanguageUpdated,
|
|
176
|
+
() => {
|
|
177
|
+
FWLoggerUtil.log('Receive FWEventName.AppLanguageUpdated');
|
|
178
|
+
this.setState({});
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
this._subscriptions.push(subscriptionOfAppLanguageUpdated);
|
|
170
182
|
}
|
|
171
183
|
|
|
184
|
+
/**
|
|
185
|
+
* @ignore
|
|
186
|
+
*/
|
|
172
187
|
componentWillUnmount() {
|
|
173
188
|
FWLoggerUtil.log(
|
|
174
189
|
`VideoFeed componentWillUnmount ${JSON.stringify(this.props)}`
|
|
175
190
|
);
|
|
176
191
|
|
|
177
|
-
this.
|
|
192
|
+
this._subscriptions.forEach((value) => {
|
|
178
193
|
value.remove();
|
|
179
194
|
});
|
|
180
195
|
|
|
181
|
-
this.
|
|
196
|
+
this._subscriptions = [];
|
|
182
197
|
}
|
|
183
198
|
|
|
199
|
+
/**
|
|
200
|
+
* @ignore
|
|
201
|
+
*/
|
|
184
202
|
render() {
|
|
185
203
|
FWLoggerUtil.log(`VideoFeed render ${JSON.stringify(this.props)}`);
|
|
186
204
|
|
|
@@ -213,6 +231,7 @@ class VideoFeed extends React.Component<IVideoFeedProps> {
|
|
|
213
231
|
const showAdBadge = videoFeedConfiguration?.showAdBadge ?? false;
|
|
214
232
|
const videoLaunchBehavior =
|
|
215
233
|
FireworkSDK.getInstance().getVideoLaunchBehavior() ?? 'default';
|
|
234
|
+
const appLanguage = FireworkSDK.getInstance().appLanguage ?? '';
|
|
216
235
|
|
|
217
236
|
let key = `source:${source}`;
|
|
218
237
|
key += `_channel:${channel}`;
|
|
@@ -234,12 +253,13 @@ class VideoFeed extends React.Component<IVideoFeedProps> {
|
|
|
234
253
|
key += `_vastAttributes:${vastAttributesString}`;
|
|
235
254
|
key += `_showAdBadge:${showAdBadge}`;
|
|
236
255
|
key += `_videoLaunchBehavior:${videoLaunchBehavior}`;
|
|
256
|
+
key += `_appLanguage:${appLanguage}`;
|
|
237
257
|
|
|
238
258
|
return (
|
|
239
259
|
<FWVideoFeed
|
|
240
260
|
key={key}
|
|
241
261
|
{...this.props}
|
|
242
|
-
ref={this.
|
|
262
|
+
ref={this._nativeComponentRef}
|
|
243
263
|
onVideoFeedLoadFinished={this._onVideoFeedLoadFinished}
|
|
244
264
|
mode={mode}
|
|
245
265
|
style={Object.assign({}, this.props.style, { zIndex: -1 })}
|