@applicaster/zapp-react-native-ui-components 12.0.0-alpha.7725319213 → 12.0.0-alpha.7855034103
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/Components/AudioPlayer/AudioPlayer.tsx +9 -1
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +5 -0
- package/Components/AudioPlayer/helpers.tsx +1 -0
- package/Components/Cell/Cell.tsx +2 -2
- package/Components/Cell/CellWithFocusable.tsx +21 -14
- package/Components/Cell/TvOSCellComponent.tsx +2 -2
- package/Components/ErrorScreen/index.tsx +1 -1
- package/Components/FocusableCell/index.tsx +7 -7
- package/Components/FocusableList/FocusableChild.ts +24 -14
- package/Components/FocusableList/FocusableItem.tsx +1 -1
- package/Components/FocusableList/FocusableListItemWrapper.tsx +76 -0
- package/Components/FocusableList/hooks/useCellState.android.ts +3 -1
- package/Components/FocusableList/index.tsx +26 -25
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +6 -3
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
- package/Components/HookRenderer/index.tsx +1 -6
- package/Components/Image/Image.android.tsx +3 -25
- package/Components/Image/Image.tsx +18 -2
- package/Components/Image/utils/index.ts +39 -0
- package/Components/Layout/TV/__tests__/index.test.tsx +1 -34
- package/Components/Layout/TV/index.tsx +28 -41
- package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +80 -109
- package/Components/MasterCell/DefaultComponents/DynamicBadge.tsx +4 -2
- package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +9 -26
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImageSize.ts +65 -0
- package/Components/MasterCell/DefaultComponents/ImageContainer/index.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +17 -2
- package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +3 -2
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +14 -2
- package/Components/MasterCell/DefaultComponents/Toggle.tsx +5 -1
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
- package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +24 -9
- package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +6 -14
- package/Components/MasterCell/hooks/useAsyncRendering/index.ts +1 -1
- package/Components/MasterCell/utils/index.ts +16 -5
- package/Components/MeasurmentsPortal/BasicMeasurementsPortal.tsx +11 -7
- package/Components/MeasurmentsPortal/MeasurementsPortal.tsx +10 -1
- package/Components/ModalComponent/BottomSheetModalContent.tsx +121 -0
- package/Components/ModalComponent/Button/Item.tsx +82 -0
- package/Components/ModalComponent/Button/ItemIcon.tsx +60 -0
- package/Components/ModalComponent/Button/ItemLabel.tsx +101 -0
- package/Components/ModalComponent/Button/assets.ts +4 -0
- package/Components/ModalComponent/Button/index.tsx +111 -0
- package/Components/ModalComponent/Header/CloseButton.tsx +59 -0
- package/Components/ModalComponent/Header/Title.tsx +70 -0
- package/Components/ModalComponent/Header/assets.ts +4 -0
- package/Components/ModalComponent/Header/index.tsx +71 -0
- package/Components/ModalComponent/Header/utils.ts +79 -0
- package/Components/ModalComponent/index.tsx +38 -0
- package/Components/ModalComponent/utils.ts +126 -0
- package/Components/PlayerContainer/PlayerContainer.tsx +60 -31
- package/Components/PlayerContainer/ProgramInfo/index.tsx +3 -1
- package/Components/PlayerImageBackground/index.tsx +34 -8
- package/Components/River/ComponentsMap/ComponentsMap.tsx +97 -2
- package/Components/River/RefreshControl.tsx +55 -1
- package/Components/River/TV/River.tsx +2 -2
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -1
- package/Components/River/__tests__/componentsMap.test.js +7 -0
- package/Components/River/useScreenConfiguration.ts +2 -2
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +1 -0
- package/Components/RouteManager/__tests__/routeManager.test.js +9 -2
- package/Components/RouteManager/index.tsx +4 -2
- package/Components/Screen/__tests__/Screen.test.tsx +88 -74
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +24 -6
- package/Components/Screen/__tests__/navigationHandler.test.ts +1 -178
- package/Components/Screen/index.tsx +103 -43
- package/Components/Screen/navigationHandler.ts +0 -82
- package/Components/ScreenResolver/index.tsx +1 -1
- package/Components/Tabs/TV/styles.ts +1 -1
- package/Components/Transitioner/Scene.tsx +24 -19
- package/Components/Transitioner/Transitioner.tsx +9 -2
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +6 -2
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +1 -0
- package/Components/VideoLive/LiveImageManager.ts +5 -2
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +31 -28
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +45 -3
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +18 -28
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +342 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +151 -0
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +438 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +154 -0
- package/Components/VideoModal/ModalAnimation/index.ts +15 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +299 -0
- package/Components/VideoModal/PlayerDetails.tsx +6 -3
- package/Components/VideoModal/PlayerWrapper.tsx +78 -48
- package/Components/VideoModal/VideoModal.tsx +25 -42
- package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +0 -2
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +12 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +246 -166
- package/Components/VideoModal/utils.ts +3 -3
- package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +26 -21
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +31 -40
- package/Components/Viewport/ViewportTracker/__tests__/viewportTracker.test.js +4 -5
- package/Components/Viewport/ViewportTracker/index.tsx +1 -0
- package/Components/Viewport/utils.js +1 -1
- package/Components/ZappUIComponent/index.tsx +22 -12
- package/Components/index.js +2 -0
- package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
- package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
- package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
- package/Contexts/ScreenContext/index.tsx +95 -29
- package/Contexts/ScreenDataContext/index.ts +3 -0
- package/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
- package/events/index.ts +1 -0
- package/package.json +5 -5
- package/Components/VideoModal/hooks/usePosition.ts +0 -50
- /package/Contexts/{index.js → index.ts} +0 -0
|
@@ -1,85 +1,3 @@
|
|
|
1
|
-
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* This function helps to decide wether the navbar should be presented on the screen
|
|
5
|
-
* based on route and / or screen Data
|
|
6
|
-
*
|
|
7
|
-
* Currently the scenarios include
|
|
8
|
-
* - players => false
|
|
9
|
-
* - search screen plugin => false
|
|
10
|
-
* - hooks with `showNavBar: true` or `presentFullScreen` not set to true, defaults to no navbar for hook screens
|
|
11
|
-
* - screens with `allow_screen_plugin_presentation` in general property => false
|
|
12
|
-
*
|
|
13
|
-
* @param {String} route current route of the screen
|
|
14
|
-
* @param {Object} screenData payload associated with the currently presented screen
|
|
15
|
-
* @returns {Boolean}
|
|
16
|
-
*/
|
|
17
|
-
export function isNavBarVisible(
|
|
18
|
-
route,
|
|
19
|
-
screenData,
|
|
20
|
-
showNavBar,
|
|
21
|
-
canGoBack,
|
|
22
|
-
videoModalState: QuickBrickVideoModalState | null = null
|
|
23
|
-
) {
|
|
24
|
-
/* screenData is not actual navigator.data
|
|
25
|
-
* or navigator.screenData,
|
|
26
|
-
* but navigator.data.screen */
|
|
27
|
-
if (route.includes("playable")) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (
|
|
32
|
-
videoModalState?.mode === "FULLSCREEN" &&
|
|
33
|
-
videoModalState?.visible === true
|
|
34
|
-
) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (screenData?.type === "qb_search_screen" && !isTV()) {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/* Match if screen is Hook */
|
|
43
|
-
if (route.startsWith("/hooks/")) {
|
|
44
|
-
const module = screenData?.module;
|
|
45
|
-
|
|
46
|
-
if (module?.presentFullScreen) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return module?.showNavBar ?? false;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (screenData?.hookPlugin) {
|
|
54
|
-
const hookPlugin = screenData?.hookPlugin?.module;
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
hookPlugin?.showNavBar || hookPlugin?.presentFullScreen !== true || false
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
screenData?.general?.allow_screen_plugin_presentation ||
|
|
63
|
-
screenData?.general?.hide_app_nav_bar
|
|
64
|
-
) {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const hideSecondaryLevel = screenData?.navigations?.some(
|
|
69
|
-
(navigation) => navigation.styles?.hide_secondary_level_menu
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
if (canGoBack && hideSecondaryLevel) {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (typeof showNavBar === "boolean" && !showNavBar) {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
1
|
/**
|
|
84
2
|
* This function helps to decide wether the menu should be presented on the screen
|
|
85
3
|
* based on route and / or screen Data
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from "react-native";
|
|
8
8
|
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
|
9
9
|
import { PathnameContext } from "../../Contexts/PathnameContext";
|
|
10
|
+
import { ScreenDataContext } from "../../Contexts/ScreenDataContext";
|
|
10
11
|
|
|
11
12
|
type Props = {
|
|
12
13
|
children: any;
|
|
@@ -16,6 +17,8 @@ type Props = {
|
|
|
16
17
|
animating: boolean;
|
|
17
18
|
contentStyle: ViewStyle;
|
|
18
19
|
pathname: string;
|
|
20
|
+
isActive: boolean;
|
|
21
|
+
screenData: NavigationScreenData;
|
|
19
22
|
};
|
|
20
23
|
|
|
21
24
|
/**
|
|
@@ -38,34 +41,36 @@ export function Scene({
|
|
|
38
41
|
animating,
|
|
39
42
|
contentStyle,
|
|
40
43
|
pathname,
|
|
44
|
+
isActive = false,
|
|
45
|
+
screenData,
|
|
41
46
|
}: Props) {
|
|
47
|
+
const [initialScreenData, setInitialScreenData] = React.useState(screenData);
|
|
48
|
+
|
|
49
|
+
React.useLayoutEffect(() => {
|
|
50
|
+
if (isActive) {
|
|
51
|
+
setInitialScreenData(screenData);
|
|
52
|
+
}
|
|
53
|
+
}, [screenData, isActive]);
|
|
54
|
+
|
|
42
55
|
const frame = useSafeAreaFrame();
|
|
43
56
|
const { height, width } = useWindowDimensions();
|
|
44
57
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
<Animated.View
|
|
50
|
-
pointerEvents={pointerEvents}
|
|
51
|
-
style={[style, contentStyle, { height, width }]}
|
|
52
|
-
>
|
|
53
|
-
<PathnameContext.Provider value={pathname}>
|
|
54
|
-
{children}
|
|
55
|
-
</PathnameContext.Provider>
|
|
56
|
-
<Animated.View style={overlayStyle} />
|
|
57
|
-
</Animated.View>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
58
|
+
// Safe frame takes too long to update,
|
|
59
|
+
// so we can not rely on it there, and use height and width instead.
|
|
60
|
+
const isAnimating = animating && overlayStyle;
|
|
61
|
+
const dimensions = isAnimating ? { height, width } : frame;
|
|
60
62
|
|
|
61
63
|
return (
|
|
62
64
|
<Animated.View
|
|
63
65
|
pointerEvents={pointerEvents}
|
|
64
|
-
style={[style, contentStyle,
|
|
66
|
+
style={[style, contentStyle, dimensions]}
|
|
65
67
|
>
|
|
66
|
-
<
|
|
67
|
-
{
|
|
68
|
-
|
|
68
|
+
<ScreenDataContext.Provider value={initialScreenData}>
|
|
69
|
+
<PathnameContext.Provider value={pathname}>
|
|
70
|
+
{children}
|
|
71
|
+
</PathnameContext.Provider>
|
|
72
|
+
</ScreenDataContext.Provider>
|
|
73
|
+
{isAnimating && <Animated.View style={overlayStyle} />}
|
|
69
74
|
</Animated.View>
|
|
70
75
|
);
|
|
71
76
|
}
|
|
@@ -278,7 +278,8 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
278
278
|
// instead of dangerous nulls or duplicates.
|
|
279
279
|
renderSingleScene({ scenes, to }) {
|
|
280
280
|
const { contentStyle, layoutData } = this.props;
|
|
281
|
-
const screenData =
|
|
281
|
+
const screenData = this.props.children.props.screenData;
|
|
282
|
+
const pathname = scenes[to.index].key;
|
|
282
283
|
|
|
283
284
|
const orientation = getScreenOrientation({
|
|
284
285
|
screenData,
|
|
@@ -296,10 +297,12 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
296
297
|
}) && (
|
|
297
298
|
<Scene
|
|
298
299
|
{...{ style: to.style }}
|
|
299
|
-
pathname={
|
|
300
|
+
pathname={pathname}
|
|
301
|
+
isActive={pathname === this.props.navigator.currentRoute}
|
|
300
302
|
contentStyle={contentStyle}
|
|
301
303
|
key={scenes[to.index].key}
|
|
302
304
|
screenUniqueId={scenes[to.index].screenUniqueId}
|
|
305
|
+
screenData={screenData}
|
|
303
306
|
>
|
|
304
307
|
{scenes[to.index].children}
|
|
305
308
|
</Scene>
|
|
@@ -319,12 +322,14 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
319
322
|
<Scene
|
|
320
323
|
key={scenes[from.index].key}
|
|
321
324
|
pathname={scenes[from.index].key}
|
|
325
|
+
isActive={scenes[from.index].key === this.props.navigator.currentRoute}
|
|
322
326
|
style={from.style}
|
|
323
327
|
pointerEvents="none"
|
|
324
328
|
overlayStyle={from.overlayStyle}
|
|
325
329
|
animating={this.state.animating}
|
|
326
330
|
contentStyle={contentStyle}
|
|
327
331
|
screenUniqueId={scenes[from.index].screenUniqueId}
|
|
332
|
+
screenData={scenes[from.index].children.props.screenData}
|
|
328
333
|
>
|
|
329
334
|
{scenes[from.index].children}
|
|
330
335
|
</Scene>
|
|
@@ -333,12 +338,14 @@ export class TransitionerComponent extends React.PureComponent<Props, State> {
|
|
|
333
338
|
const toScene = scenes[to.index] && (
|
|
334
339
|
<Scene
|
|
335
340
|
pathname={scenes[to.index].key}
|
|
341
|
+
isActive={scenes[to.index].key === this.props.navigator.currentRoute}
|
|
336
342
|
key={scenes[to.index].key}
|
|
337
343
|
style={to.style}
|
|
338
344
|
overlayStyle={to.overlayStyle}
|
|
339
345
|
animating={this.state.animating}
|
|
340
346
|
contentStyle={contentStyle}
|
|
341
347
|
screenUniqueId={scenes[to.index].screenUniqueId}
|
|
348
|
+
screenData={this.props.children.props.screenData}
|
|
342
349
|
>
|
|
343
350
|
{scenes[to.index].children}
|
|
344
351
|
</Scene>
|
|
@@ -21,7 +21,9 @@ exports[`<Scene /> renders correctly 1`] = `
|
|
|
21
21
|
]
|
|
22
22
|
}
|
|
23
23
|
>
|
|
24
|
-
<ContextProvider
|
|
24
|
+
<ContextProvider>
|
|
25
|
+
<ContextProvider />
|
|
26
|
+
</ContextProvider>
|
|
25
27
|
</ForwardRef(AnimatedComponentWrapper)>
|
|
26
28
|
`;
|
|
27
29
|
|
|
@@ -43,7 +45,9 @@ exports[`<Scene /> renders the overlay while animating 1`] = `
|
|
|
43
45
|
]
|
|
44
46
|
}
|
|
45
47
|
>
|
|
46
|
-
<ContextProvider
|
|
48
|
+
<ContextProvider>
|
|
49
|
+
<ContextProvider />
|
|
50
|
+
</ContextProvider>
|
|
47
51
|
<ForwardRef(AnimatedComponentWrapper)
|
|
48
52
|
style={
|
|
49
53
|
Object {
|
|
@@ -351,6 +351,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
351
351
|
item,
|
|
352
352
|
playerId: this.currentlyPlaying?.playerId,
|
|
353
353
|
primaryPlayerId: this.primaryPlayer?.playerId,
|
|
354
|
+
entry: item.getPlayer().getEntry(),
|
|
354
355
|
},
|
|
355
356
|
});
|
|
356
357
|
};
|
|
@@ -369,8 +370,8 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
369
370
|
// TODO: This branch was used when we had play button to toggle replay.
|
|
370
371
|
// Now we mute button instead but we keep it just in case.
|
|
371
372
|
if (IS_ALLOWED_REPLAY && !isTV() && isCurrentItemEnded) {
|
|
372
|
-
this.currentlyPlaying
|
|
373
|
-
this.currentlyPlaying
|
|
373
|
+
this.currentlyPlaying?.player.seekTo(0);
|
|
374
|
+
this.currentlyPlaying?.player.pause();
|
|
374
375
|
|
|
375
376
|
// TODO: ...Maybe player some other item
|
|
376
377
|
} else {
|
|
@@ -385,6 +386,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
385
386
|
item,
|
|
386
387
|
playerId: this.currentlyPlaying?.playerId,
|
|
387
388
|
primaryPlayerId: this.primaryPlayer?.playerId,
|
|
389
|
+
entry: item.getPlayer().getEntry(),
|
|
388
390
|
},
|
|
389
391
|
});
|
|
390
392
|
};
|
|
@@ -419,6 +421,7 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
419
421
|
error,
|
|
420
422
|
playerId: currentItem?.playerId,
|
|
421
423
|
primaryPlayerId: currentItem?.playerId,
|
|
424
|
+
entry: item.getPlayer().getEntry(),
|
|
422
425
|
},
|
|
423
426
|
});
|
|
424
427
|
};
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
15
15
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
|
|
16
16
|
import { getUserCellPlayerMutedPreference } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/userCellPlayerMutedPreference";
|
|
17
|
-
import
|
|
17
|
+
import Image from "@applicaster/zapp-react-native-ui-components/Components/MasterCell/DefaultComponents/Image";
|
|
18
18
|
import { LiveImage, LiveImageManager, LiveImageType } from "./LiveImageManager";
|
|
19
19
|
|
|
20
20
|
import { AnimatedInOut } from "@applicaster/zapp-react-native-ui-components/Components/AnimatedInOut";
|
|
@@ -39,12 +39,13 @@ type Props = {
|
|
|
39
39
|
imageKey?: string;
|
|
40
40
|
screenConfig: Record<string, any>;
|
|
41
41
|
audioMutedByDefault?: boolean;
|
|
42
|
+
uri: string; // cover image url
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
const PlayerLiveImageComponent = (props: Props) => {
|
|
45
46
|
const dimensions = useDimensions("screen", { fullDimensions: true });
|
|
46
47
|
|
|
47
|
-
const { item, style, playerId
|
|
48
|
+
const { item, style, playerId } = props;
|
|
48
49
|
|
|
49
50
|
const timeoutRef = React.useRef<NodeJS.Timeout | null>(null);
|
|
50
51
|
const [mode, setMode] = React.useState(LiveImageType.Image);
|
|
@@ -63,24 +64,27 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
63
64
|
*
|
|
64
65
|
* @param type video or image
|
|
65
66
|
*/
|
|
66
|
-
const setModeDebounced = React.useCallback(
|
|
67
|
-
|
|
68
|
-
if (type ===
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
const setModeDebounced = React.useCallback(
|
|
68
|
+
(type: LiveImageType) => {
|
|
69
|
+
if (type === LiveImageType.Video) {
|
|
70
|
+
if (type === mode) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
timeoutRef.current = setTimeout(() => {
|
|
75
|
+
setMode(type);
|
|
76
|
+
}, 1000) as unknown as NodeJS.Timeout;
|
|
77
|
+
} else {
|
|
78
|
+
if (timeoutRef.current) {
|
|
79
|
+
clearTimeout(timeoutRef.current);
|
|
80
|
+
timeoutRef.current = null;
|
|
81
|
+
}
|
|
71
82
|
|
|
72
|
-
timeoutRef.current = setTimeout(() => {
|
|
73
83
|
setMode(type);
|
|
74
|
-
}, 1000) as unknown as NodeJS.Timeout;
|
|
75
|
-
} else {
|
|
76
|
-
if (timeoutRef.current) {
|
|
77
|
-
clearTimeout(timeoutRef.current);
|
|
78
|
-
timeoutRef.current = null;
|
|
79
84
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}, [mode]);
|
|
85
|
+
},
|
|
86
|
+
[mode]
|
|
87
|
+
);
|
|
84
88
|
|
|
85
89
|
const { screenConfig, playerPluginId } = props;
|
|
86
90
|
|
|
@@ -100,7 +104,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
100
104
|
return new LiveImage({
|
|
101
105
|
playerId,
|
|
102
106
|
player: playerFactoryItem.controller,
|
|
103
|
-
component: playerFactoryItem?.Component
|
|
107
|
+
component: playerFactoryItem?.Component,
|
|
104
108
|
});
|
|
105
109
|
} else {
|
|
106
110
|
throw new Error("Player factory item is null");
|
|
@@ -111,10 +115,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
111
115
|
liveImageItem.setMode = setModeDebounced;
|
|
112
116
|
}, [setModeDebounced, liveImageItem]);
|
|
113
117
|
|
|
114
|
-
const { start, end } = React.useMemo(
|
|
115
|
-
() => getAutoplaySettings(item),
|
|
116
|
-
[item]
|
|
117
|
-
);
|
|
118
|
+
const { start, end } = React.useMemo(() => getAutoplaySettings(item), [item]);
|
|
118
119
|
|
|
119
120
|
const controller = liveImageItem.getPlayer();
|
|
120
121
|
const player = usePlayer(playerId);
|
|
@@ -239,7 +240,12 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
239
240
|
|
|
240
241
|
const onPositionUpdated = React.useCallback(
|
|
241
242
|
(data) => {
|
|
242
|
-
const normalizedRect = (rect: {
|
|
243
|
+
const normalizedRect = (rect: {
|
|
244
|
+
left: number;
|
|
245
|
+
right: number;
|
|
246
|
+
top: number;
|
|
247
|
+
bottom: number;
|
|
248
|
+
}) => {
|
|
243
249
|
if (!rect) {
|
|
244
250
|
return null;
|
|
245
251
|
}
|
|
@@ -283,6 +289,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
283
289
|
const videoStyles = { ...style, position: "absolute", zIndex: -100 };
|
|
284
290
|
const Player: any = liveImageItem.component || BufferAnimation;
|
|
285
291
|
|
|
292
|
+
// TODO: nice to have - resolve imageKey when imageUrl is not provided
|
|
286
293
|
return (
|
|
287
294
|
<TrackedView
|
|
288
295
|
testId={`tracked-view-${playerId}-${item.title}`}
|
|
@@ -307,11 +314,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
307
314
|
animationConfig={overlayFadeIn}
|
|
308
315
|
staticStyles={style}
|
|
309
316
|
>
|
|
310
|
-
<
|
|
311
|
-
entry={item}
|
|
312
|
-
style={style}
|
|
313
|
-
imageKey={imageKey}
|
|
314
|
-
/>
|
|
317
|
+
<Image {...props} resizeMode="cover" style={style} applyMaxSize />
|
|
315
318
|
</AnimatedInOut>
|
|
316
319
|
}
|
|
317
320
|
</TrackedView>
|
|
@@ -3,7 +3,14 @@ import * as React from "react";
|
|
|
3
3
|
import { render } from "@testing-library/react-native";
|
|
4
4
|
import * as PlayerFactory from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerFactory";
|
|
5
5
|
import { Player } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/player";
|
|
6
|
+
import { ThemeContext } from "@applicaster/zapp-react-native-utils/theme";
|
|
7
|
+
import * as navigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
8
|
+
|
|
6
9
|
import { PlayerLiveImage } from "../PlayerLiveImageComponent";
|
|
10
|
+
import * as useNavigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
|
|
11
|
+
|
|
12
|
+
import { Provider } from "react-redux";
|
|
13
|
+
import configureStore from "redux-mock-store";
|
|
7
14
|
|
|
8
15
|
const seekTo = jest.fn();
|
|
9
16
|
|
|
@@ -16,6 +23,27 @@ jest.mock(
|
|
|
16
23
|
})
|
|
17
24
|
);
|
|
18
25
|
|
|
26
|
+
jest
|
|
27
|
+
.spyOn(useNavigationHooks, "useNavigation")
|
|
28
|
+
.mockImplementation(() => ({ videoModalState: { visible: false } }));
|
|
29
|
+
|
|
30
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
|
|
31
|
+
|
|
32
|
+
const mockStore = configureStore();
|
|
33
|
+
|
|
34
|
+
const store = mockStore({ appData: {} });
|
|
35
|
+
|
|
36
|
+
const Wrapper = ({ children }: { children: React.ReactChildren }) => (
|
|
37
|
+
/* @ts-ignore */
|
|
38
|
+
<Provider store={store}>
|
|
39
|
+
<ThemeContext.Provider
|
|
40
|
+
value={{ themes: { myTheme: {} }, selectedThemeId: "myTheme" }}
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</ThemeContext.Provider>
|
|
44
|
+
</Provider>
|
|
45
|
+
);
|
|
46
|
+
|
|
19
47
|
describe("PlayerLiveImageComponent", () => {
|
|
20
48
|
const defaultProps = {
|
|
21
49
|
item: { id: "1", title: "Test", type: { value: "" } },
|
|
@@ -36,10 +64,16 @@ describe("PlayerLiveImageComponent", () => {
|
|
|
36
64
|
controller: new Player({}),
|
|
37
65
|
Component: () => null,
|
|
38
66
|
}));
|
|
67
|
+
|
|
68
|
+
jest.spyOn(navigationHooks, "useIsScreenActive").mockReturnValue(true);
|
|
39
69
|
});
|
|
40
70
|
|
|
41
71
|
it("should render correctly with default props", () => {
|
|
42
|
-
const component = render(
|
|
72
|
+
const component = render(
|
|
73
|
+
<Wrapper>
|
|
74
|
+
<PlayerLiveImage {...defaultProps} />
|
|
75
|
+
</Wrapper>
|
|
76
|
+
);
|
|
43
77
|
|
|
44
78
|
expect(component.toJSON()).toMatchSnapshot();
|
|
45
79
|
});
|
|
@@ -53,7 +87,11 @@ describe("PlayerLiveImageComponent", () => {
|
|
|
53
87
|
},
|
|
54
88
|
};
|
|
55
89
|
|
|
56
|
-
render(
|
|
90
|
+
render(
|
|
91
|
+
<Wrapper>
|
|
92
|
+
<PlayerLiveImage {...props} />
|
|
93
|
+
</Wrapper>
|
|
94
|
+
);
|
|
57
95
|
|
|
58
96
|
// TODO: implement this test
|
|
59
97
|
});
|
|
@@ -67,7 +105,11 @@ describe("PlayerLiveImageComponent", () => {
|
|
|
67
105
|
},
|
|
68
106
|
};
|
|
69
107
|
|
|
70
|
-
render(
|
|
108
|
+
render(
|
|
109
|
+
<Wrapper>
|
|
110
|
+
<PlayerLiveImage {...props} />
|
|
111
|
+
</Wrapper>
|
|
112
|
+
);
|
|
71
113
|
|
|
72
114
|
// TODO: implement this test
|
|
73
115
|
});
|
|
@@ -13,35 +13,25 @@ exports[`PlayerLiveImageComponent should render correctly with default props 1`]
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
>
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
style={
|
|
28
|
-
Array [
|
|
29
|
-
Object {
|
|
30
|
-
"bottom": 0,
|
|
31
|
-
"left": 0,
|
|
32
|
-
"position": "absolute",
|
|
33
|
-
"right": 0,
|
|
34
|
-
"top": 0,
|
|
35
|
-
},
|
|
36
|
-
Object {
|
|
37
|
-
"height": undefined,
|
|
38
|
-
"width": undefined,
|
|
39
|
-
},
|
|
40
|
-
undefined,
|
|
41
|
-
]
|
|
16
|
+
<Image
|
|
17
|
+
applyMaxSize={true}
|
|
18
|
+
audioMutedByDefault={false}
|
|
19
|
+
imageKey="image1"
|
|
20
|
+
item={
|
|
21
|
+
Object {
|
|
22
|
+
"id": "1",
|
|
23
|
+
"title": "Test",
|
|
24
|
+
"type": Object {
|
|
25
|
+
"value": "",
|
|
26
|
+
},
|
|
42
27
|
}
|
|
43
|
-
|
|
44
|
-
|
|
28
|
+
}
|
|
29
|
+
onError={[Function]}
|
|
30
|
+
playerId="player1"
|
|
31
|
+
resizeMode="cover"
|
|
32
|
+
screenConfig={Object {}}
|
|
33
|
+
style={Object {}}
|
|
34
|
+
/>
|
|
45
35
|
</View>
|
|
46
36
|
</TrackedView>
|
|
47
37
|
`;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Animated, ViewStyle } from "react-native";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
useModalAnimationContext,
|
|
6
|
+
PlayerAnimationStateEnum,
|
|
7
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
8
|
+
import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
style: ViewStyle[];
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const AnimatedPlayerModalWrapper = (props: Props) => {
|
|
16
|
+
const {
|
|
17
|
+
playerAnimationState,
|
|
18
|
+
animatedValues: { lastScrollY, dragScrollY, translateYOffset },
|
|
19
|
+
modalSnapPoints,
|
|
20
|
+
setStartComponentsAnimation,
|
|
21
|
+
lastScrollYValue,
|
|
22
|
+
} = useModalAnimationContext();
|
|
23
|
+
|
|
24
|
+
const { height: screenHeight } = useDimensions("screen", {
|
|
25
|
+
deviceInfo: true,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const interpolateConfig: Animated.InterpolationConfigType = React.useMemo(
|
|
29
|
+
() => ({
|
|
30
|
+
inputRange: modalSnapPoints,
|
|
31
|
+
outputRange: modalSnapPoints,
|
|
32
|
+
extrapolate: "clamp",
|
|
33
|
+
}),
|
|
34
|
+
[modalSnapPoints]
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
let translateY;
|
|
38
|
+
|
|
39
|
+
if (playerAnimationState === PlayerAnimationStateEnum.drag_player) {
|
|
40
|
+
translateY = translateYOffset.interpolate(interpolateConfig);
|
|
41
|
+
} else {
|
|
42
|
+
const reverseLastScrollY = Animated.multiply(
|
|
43
|
+
new Animated.Value(-1),
|
|
44
|
+
lastScrollY
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
translateY = Animated.add(
|
|
48
|
+
translateYOffset,
|
|
49
|
+
Animated.add(dragScrollY, reverseLastScrollY)
|
|
50
|
+
).interpolate(interpolateConfig);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
React.useEffect(() => {
|
|
54
|
+
const translateYListener = translateY.addListener(({ value }) => {
|
|
55
|
+
const preparedValue = Math.round(
|
|
56
|
+
Math.abs(value) - lastScrollYValue.current
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
(playerAnimationState === PlayerAnimationStateEnum.minimize ||
|
|
60
|
+
playerAnimationState === PlayerAnimationStateEnum.maximaze) &&
|
|
61
|
+
setStartComponentsAnimation(
|
|
62
|
+
preparedValue >= Math.round((screenHeight * 10) / 100)
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return () => {
|
|
67
|
+
translateYListener && translateY.removeListener(translateYListener);
|
|
68
|
+
};
|
|
69
|
+
}, [playerAnimationState]);
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<Animated.View
|
|
73
|
+
style={[props.style, { transform: [{ translateY: translateY }] }]}
|
|
74
|
+
>
|
|
75
|
+
{props.children}
|
|
76
|
+
</Animated.View>
|
|
77
|
+
);
|
|
78
|
+
};
|