@applicaster/zapp-react-native-ui-components 14.0.0-alpha.5621117258 → 14.0.0-alpha.6242515303
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/index.tsx +15 -0
- package/Components/AudioPlayer/mobile/Layout.tsx +66 -0
- package/Components/AudioPlayer/{__tests__/__snapshots__/audioPlayer.test.js.snap → mobile/__tests__/__snapshots__/audioPlayerMobileLayout.test.js.snap} +2 -8
- package/Components/AudioPlayer/mobile/__tests__/audioPlayerMobileLayout.test.js +18 -0
- package/Components/AudioPlayer/mobile/index.tsx +18 -0
- package/Components/AudioPlayer/{Artwork.tsx → tv/Artwork.tsx} +3 -2
- package/Components/AudioPlayer/{Channel.tsx → tv/Channel.tsx} +7 -7
- package/Components/AudioPlayer/tv/Layout.tsx +168 -0
- package/Components/AudioPlayer/{Runtime.tsx → tv/Runtime.tsx} +7 -1
- package/Components/AudioPlayer/{Summary.tsx → tv/Summary.tsx} +6 -2
- package/Components/AudioPlayer/{Title.tsx → tv/Title.tsx} +6 -2
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/Runtime.test.js.snap +2 -2
- package/Components/AudioPlayer/tv/__tests__/__snapshots__/audioPlayer.test.js.snap +164 -0
- package/Components/AudioPlayer/tv/__tests__/__snapshots__/channel.test.js.snap +19 -0
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/summary.test.js.snap +1 -2
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/title.test.js.snap +1 -2
- package/Components/AudioPlayer/{__tests__ → tv/__tests__}/audioPlayer.test.js +7 -3
- package/Components/AudioPlayer/{helpers.tsx → tv/helpers.tsx} +1 -2
- package/Components/AudioPlayer/{AudioPlayer.tsx → tv/index.tsx} +17 -58
- package/Components/AudioPlayer/types.ts +40 -0
- package/Components/Cell/index.js +6 -2
- package/Components/Focusable/__tests__/index.android.test.tsx +3 -0
- package/Components/Focusable/index.android.tsx +12 -8
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +0 -2
- package/Components/HandlePlayable/HandlePlayable.tsx +11 -1
- package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -27
- package/Components/MasterCell/DefaultComponents/Text/index.tsx +1 -0
- package/Components/MasterCell/index.tsx +1 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +7 -22
- package/Components/PlayerImageBackground/index.tsx +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +1 -5
- package/Components/River/RiverItem.tsx +8 -8
- package/Components/River/TV/River.tsx +0 -3
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +0 -6
- package/Components/TopMarginApplicator/TopMarginApplicator.tsx +16 -15
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +1 -9
- package/Components/VideoModal/PlayerDetails.tsx +2 -24
- package/Components/VideoModal/PlayerWrapper.tsx +142 -26
- package/Components/VideoModal/VideoModal.tsx +17 -3
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +7 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +240 -44
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +17 -55
- package/Components/VideoModal/hooks/index.ts +2 -0
- package/Components/VideoModal/hooks/useBackgroundColor.ts +10 -0
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +15 -26
- package/Components/VideoModal/utils.ts +0 -6
- package/Components/Viewport/VisibilitySensor/VisibilitySensor.tsx +3 -3
- package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/index.ts +3 -3
- package/index.d.ts +0 -1
- package/package.json +5 -8
- package/Components/AudioPlayer/AudioPlayerLayout.tsx +0 -202
- package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +0 -72
- package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +0 -28
- package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +0 -26
- package/Components/AudioPlayer/index.ts +0 -1
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/Runtime.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/__snapshots__/artWork.test.js.snap +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/artWork.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/channel.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/summary.test.js +0 -0
- /package/Components/AudioPlayer/{__tests__ → tv/__tests__}/title.test.js +0 -0
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, ViewStyle } from "react-native";
|
|
3
3
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
4
4
|
import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
5
5
|
import { isFirstComponentScreenPicker } from "@applicaster/zapp-react-native-utils/componentsUtils";
|
|
6
|
+
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
6
7
|
|
|
7
8
|
interface IProps {
|
|
8
9
|
targetScreenId?: string;
|
|
9
10
|
children?: React.ReactNode;
|
|
10
11
|
style?: ViewStyle;
|
|
11
|
-
|
|
12
|
+
extraVerticalOffset: Option<number>;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
type CombinedProps = IProps & ViewProps;
|
|
15
15
|
/**
|
|
16
16
|
* The MarginTop is essentially a feature used for managing the visibility of components on your screen.
|
|
17
17
|
* A more accurate term for this might be something like a 'component visibility threshold' or 'cut-off point'.
|
|
@@ -47,7 +47,7 @@ export const useMarginTop = (targetScreenId: string): number => {
|
|
|
47
47
|
|
|
48
48
|
// Empty string means that value is blank in the CMS. Fallback to theme
|
|
49
49
|
if (String(screenData?.styles?.screen_margin_top) === "") {
|
|
50
|
-
return
|
|
50
|
+
return toNumberWithDefault(0, theme.screen_margin_top);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
@@ -58,28 +58,29 @@ export const useMarginTop = (targetScreenId: string): number => {
|
|
|
58
58
|
*/
|
|
59
59
|
if (screenData?.styles?.screen_margin_top === undefined) {
|
|
60
60
|
if (isGeneralContentScreen || supportsUiComponents) {
|
|
61
|
-
return
|
|
61
|
+
return toNumberWithDefault(0, theme.screen_margin_top);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
return 0;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
return
|
|
67
|
+
return toNumberWithDefault(0, screenData?.styles?.screen_margin_top);
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
export const TopMarginApplicator: React.FC<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
export const TopMarginApplicator: React.FC<IProps> = ({
|
|
71
|
+
targetScreenId,
|
|
72
|
+
style,
|
|
73
|
+
children,
|
|
74
|
+
extraVerticalOffset,
|
|
75
|
+
}: IProps) => {
|
|
76
|
+
const extraOffset = toNumberWithDefault(0, extraVerticalOffset);
|
|
74
77
|
|
|
75
78
|
// HACK: Remove extraOffset when focusIssue with absolute elements is fixed on tvos
|
|
76
|
-
const marginTop = useMarginTop(
|
|
77
|
-
const style = { ...((props.style as {}) || {}), marginTop };
|
|
79
|
+
const marginTop = useMarginTop(targetScreenId);
|
|
78
80
|
|
|
79
|
-
// Then, spread the rest of the props on your returned JSX.
|
|
80
81
|
return (
|
|
81
|
-
<View
|
|
82
|
-
{
|
|
82
|
+
<View style={[style, { marginTop: marginTop + extraOffset }]}>
|
|
83
|
+
{children}
|
|
83
84
|
</View>
|
|
84
85
|
);
|
|
85
86
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect } from "react";
|
|
2
|
-
import { Animated
|
|
2
|
+
import { Animated } from "react-native";
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
useSafeAreaInsets,
|
|
@@ -23,7 +23,6 @@ export enum PlayerAnimationStateEnum {
|
|
|
23
23
|
export type PlayerAnimationStateT = number | PlayerAnimationStateEnum | null;
|
|
24
24
|
|
|
25
25
|
export type ModalAnimationContextT = {
|
|
26
|
-
yTranslate: React.MutableRefObject<Animated.Value | null>;
|
|
27
26
|
isActiveGesture: boolean;
|
|
28
27
|
playerAnimationState: PlayerAnimationStateT;
|
|
29
28
|
setPlayerAnimationState: (value: PlayerAnimationStateT) => void;
|
|
@@ -49,7 +48,6 @@ export type ModalAnimationContextT = {
|
|
|
49
48
|
};
|
|
50
49
|
|
|
51
50
|
export const ReactContext = React.createContext<ModalAnimationContextT>({
|
|
52
|
-
yTranslate: React.createRef<Animated.Value | null>(),
|
|
53
51
|
isActiveGesture: false,
|
|
54
52
|
playerAnimationState: null,
|
|
55
53
|
setPlayerAnimationState: () => null,
|
|
@@ -75,10 +73,6 @@ export const ReactContext = React.createContext<ModalAnimationContextT>({
|
|
|
75
73
|
});
|
|
76
74
|
|
|
77
75
|
const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
78
|
-
const yTranslate = React.useRef(
|
|
79
|
-
new Animated.Value(Dimensions.get("window").height)
|
|
80
|
-
);
|
|
81
|
-
|
|
82
76
|
const [playerAnimationState, setPlayerAnimationState] =
|
|
83
77
|
React.useState<PlayerAnimationStateT>(null);
|
|
84
78
|
|
|
@@ -106,7 +100,6 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
|
106
100
|
// Reset player animation state when video modal is closed
|
|
107
101
|
if (!visible) {
|
|
108
102
|
resetPlayerAnimationState();
|
|
109
|
-
yTranslate.current?.setValue(Dimensions.get("window").height);
|
|
110
103
|
}
|
|
111
104
|
}, [visible, resetPlayerAnimationState]);
|
|
112
105
|
|
|
@@ -148,7 +141,6 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
|
148
141
|
return (
|
|
149
142
|
<ReactContext.Provider
|
|
150
143
|
value={{
|
|
151
|
-
yTranslate,
|
|
152
144
|
startComponentsAnimation,
|
|
153
145
|
setStartComponentsAnimation,
|
|
154
146
|
isActiveGesture: playerAnimationState !== null,
|
|
@@ -11,8 +11,6 @@ import { useTargetScreenData } from "@applicaster/zapp-react-native-utils/reactH
|
|
|
11
11
|
import { ComponentsMap } from "@applicaster/zapp-react-native-ui-components/Components/River/ComponentsMap";
|
|
12
12
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
13
13
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
14
|
-
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
15
|
-
import { useDelayedPlayerDetails } from "./hooks";
|
|
16
14
|
|
|
17
15
|
const { width: SCREEN_WIDTH } = Dimensions.get("screen");
|
|
18
16
|
|
|
@@ -28,10 +26,6 @@ type Props = {
|
|
|
28
26
|
isTabletLandscape?: boolean;
|
|
29
27
|
isAudioPlayer?: boolean;
|
|
30
28
|
isTablet?: boolean;
|
|
31
|
-
inline?: any;
|
|
32
|
-
docked?: boolean;
|
|
33
|
-
isModal?: boolean;
|
|
34
|
-
pip?: boolean;
|
|
35
29
|
};
|
|
36
30
|
|
|
37
31
|
const containerStyle = ({
|
|
@@ -48,24 +42,8 @@ export const PlayerDetails = ({
|
|
|
48
42
|
configuration,
|
|
49
43
|
isTabletLandscape = false,
|
|
50
44
|
isAudioPlayer,
|
|
51
|
-
|
|
52
|
-
docked,
|
|
53
|
-
isModal,
|
|
54
|
-
pip,
|
|
45
|
+
isTablet = false,
|
|
55
46
|
}: Props) => {
|
|
56
|
-
const isInlineModal = inline && isModal;
|
|
57
|
-
|
|
58
|
-
// Mounting the PlayerDetails component is a resource-intensive process.
|
|
59
|
-
// Therefore, for performance reasons, we mount it with a delay to make the rotation process as smooth as possible.
|
|
60
|
-
// The flow is as follows: the rotation occurs first, and then, after a short delay, we mount the PlayerDetails component.
|
|
61
|
-
// This helps to avoid blocking the rotation and any animations related to the rotation.
|
|
62
|
-
const isShowPlayerDetails = useDelayedPlayerDetails({
|
|
63
|
-
isInline: isInlineModal,
|
|
64
|
-
isDocked: docked,
|
|
65
|
-
isPip: pip,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const isTablet = useIsTablet();
|
|
69
47
|
const screenData = useTargetScreenData(entry);
|
|
70
48
|
const insets = useSafeAreaInsets();
|
|
71
49
|
|
|
@@ -101,7 +79,7 @@ export const PlayerDetails = ({
|
|
|
101
79
|
}
|
|
102
80
|
}, [isAudioPlayer]);
|
|
103
81
|
|
|
104
|
-
if (isNilOrEmpty(screenData?.ui_components)
|
|
82
|
+
if (isNilOrEmpty(screenData?.ui_components)) {
|
|
105
83
|
return null;
|
|
106
84
|
}
|
|
107
85
|
|
|
@@ -9,8 +9,16 @@ import {
|
|
|
9
9
|
import { Edge, SafeAreaView } from "react-native-safe-area-context";
|
|
10
10
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
11
11
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
|
+
import { PlayerDetails } from "./PlayerDetails";
|
|
12
13
|
import { playerDimensionsHack } from "./utils";
|
|
13
|
-
import {
|
|
14
|
+
import { useDelayedPlayerDetails } from "./hooks";
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
AnimatedScrollModal,
|
|
18
|
+
AnimatedVideoPlayerComponent,
|
|
19
|
+
AnimationComponent,
|
|
20
|
+
ComponentAnimationType,
|
|
21
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
14
22
|
|
|
15
23
|
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("screen");
|
|
16
24
|
|
|
@@ -36,15 +44,29 @@ type Props = {
|
|
|
36
44
|
isModal?: boolean;
|
|
37
45
|
fullscreen?: boolean;
|
|
38
46
|
isTabletPortrait?: boolean;
|
|
47
|
+
children: (playerDimensions: DimensionsT) => React.ReactNode;
|
|
39
48
|
configuration: Configuration;
|
|
40
|
-
|
|
41
|
-
playerContent: (styles: ViewStyle) => React.ReactNode;
|
|
42
49
|
};
|
|
43
50
|
|
|
44
51
|
const defaultStyles = StyleSheet.create({
|
|
45
52
|
playerContainer: { position: "relative", alignSelf: "center", zIndex: 200 },
|
|
53
|
+
playerDetails: { flex: 1, paddingTop: 20 },
|
|
54
|
+
flex: { flex: 1 },
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const orientationStyles = StyleSheet.create({
|
|
58
|
+
landscape: { flexDirection: "row" },
|
|
59
|
+
portrait: { flexDirection: "column" },
|
|
46
60
|
});
|
|
47
61
|
|
|
62
|
+
const directionStyles = (isTabletLandscape: boolean): ViewStyle => {
|
|
63
|
+
if (isTabletLandscape) {
|
|
64
|
+
return orientationStyles.landscape;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return orientationStyles.portrait;
|
|
68
|
+
};
|
|
69
|
+
|
|
48
70
|
const getScreenAspectRatio = () => {
|
|
49
71
|
const longEdge = Math.max(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
50
72
|
const shortEdge = Math.min(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
@@ -64,6 +86,51 @@ const getEdges = (isTablet: boolean, isInlineModal: boolean) => {
|
|
|
64
86
|
return ["top"];
|
|
65
87
|
};
|
|
66
88
|
|
|
89
|
+
const isPercentage = (value: string | number): boolean => {
|
|
90
|
+
if (typeof value === "string") {
|
|
91
|
+
return value.includes("%");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return false;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const getPercentageOf = (percent: string, value: number) => {
|
|
98
|
+
const percentageValue = parseFloat(percent.replace("%", ""));
|
|
99
|
+
|
|
100
|
+
if (isNaN(percentageValue)) {
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return (value * percentageValue) / 100;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const getTabletWidth = (
|
|
108
|
+
configuration: Configuration,
|
|
109
|
+
dimensions: DimensionsT
|
|
110
|
+
) => {
|
|
111
|
+
const tablet_landscape_sidebar_width =
|
|
112
|
+
configuration?.tablet_landscape_sidebar_width;
|
|
113
|
+
|
|
114
|
+
const { width } = dimensions;
|
|
115
|
+
let widthValue = Number(width);
|
|
116
|
+
|
|
117
|
+
if (isPercentage(width)) {
|
|
118
|
+
widthValue = getPercentageOf(width.toString(), SCREEN_WIDTH);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const sidebarWidth = Number(tablet_landscape_sidebar_width?.replace("%", ""));
|
|
122
|
+
|
|
123
|
+
if (tablet_landscape_sidebar_width?.includes("%")) {
|
|
124
|
+
return widthValue * (1 - sidebarWidth / 100);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (Number.isNaN(sidebarWidth)) {
|
|
128
|
+
return widthValue * 0.65;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return widthValue - sidebarWidth;
|
|
132
|
+
};
|
|
133
|
+
|
|
67
134
|
const PlayerWrapperComponent = (props: Props) => {
|
|
68
135
|
const {
|
|
69
136
|
entry,
|
|
@@ -72,26 +139,35 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
72
139
|
inline,
|
|
73
140
|
docked,
|
|
74
141
|
isModal,
|
|
142
|
+
children,
|
|
75
143
|
isTabletPortrait,
|
|
76
144
|
configuration,
|
|
145
|
+
fullscreen,
|
|
77
146
|
pip,
|
|
78
|
-
playerContent,
|
|
79
147
|
} = props;
|
|
80
148
|
|
|
81
149
|
const isTablet = useIsTablet();
|
|
82
150
|
|
|
83
151
|
const isInlineModal = inline && isModal;
|
|
84
152
|
|
|
153
|
+
// Mounting the PlayerDetails component is a resource-intensive process.
|
|
154
|
+
// Therefore, for performance reasons, we mount it with a delay to make the rotation process as smooth as possible.
|
|
155
|
+
// The flow is as follows: the rotation occurs first, and then, after a short delay, we mount the PlayerDetails component.
|
|
156
|
+
// This helps to avoid blocking the rotation and any animations related to the rotation.
|
|
157
|
+
const isShowPlayerDetails = useDelayedPlayerDetails({
|
|
158
|
+
isInline: isInlineModal,
|
|
159
|
+
isDocked: docked,
|
|
160
|
+
isPip: pip,
|
|
161
|
+
});
|
|
162
|
+
|
|
85
163
|
const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
|
|
86
164
|
|
|
87
|
-
const tabletWidth = getTabletWidth(
|
|
88
|
-
configuration.tablet_landscape_sidebar_width,
|
|
89
|
-
style
|
|
90
|
-
);
|
|
165
|
+
const tabletWidth = getTabletWidth(configuration, style);
|
|
91
166
|
|
|
92
167
|
const baseDimensions: DimensionsT = React.useMemo(
|
|
93
168
|
() => ({
|
|
94
|
-
width:
|
|
169
|
+
width:
|
|
170
|
+
isInlineModal && !docked && isTabletLandscape ? tabletWidth : "100%",
|
|
95
171
|
height: undefined,
|
|
96
172
|
}),
|
|
97
173
|
[isInlineModal, tabletWidth, docked]
|
|
@@ -100,7 +176,7 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
100
176
|
const playerDimensions: DimensionsT = React.useMemo(
|
|
101
177
|
() => ({
|
|
102
178
|
...baseDimensions,
|
|
103
|
-
width: baseDimensions.width,
|
|
179
|
+
width: isInlineModal && docked ? undefined : baseDimensions.width,
|
|
104
180
|
aspectRatio: !isInlineModal && !pip ? getScreenAspectRatio() : 16 / 9,
|
|
105
181
|
}),
|
|
106
182
|
[baseDimensions, isInlineModal, pip]
|
|
@@ -109,7 +185,8 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
109
185
|
const containerDimensions: DimensionsT = React.useMemo(
|
|
110
186
|
() => ({
|
|
111
187
|
...baseDimensions,
|
|
112
|
-
aspectRatio:
|
|
188
|
+
aspectRatio:
|
|
189
|
+
isInlineModal && docked ? undefined : playerDimensions.aspectRatio,
|
|
113
190
|
}),
|
|
114
191
|
[baseDimensions, isInlineModal, docked, playerDimensions.aspectRatio]
|
|
115
192
|
);
|
|
@@ -117,29 +194,68 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
117
194
|
const WrapperView = React.useMemo(() => (isTV() ? View : SafeAreaView), []);
|
|
118
195
|
|
|
119
196
|
const childrenStyles = React.useMemo(
|
|
120
|
-
() => ({
|
|
121
|
-
...playerDimensions,
|
|
122
|
-
...playerDimensionsHack,
|
|
123
|
-
}),
|
|
197
|
+
() => ({ ...playerDimensions, ...playerDimensionsHack }),
|
|
124
198
|
[containerDimensions, playerDimensionsHack]
|
|
125
199
|
);
|
|
126
200
|
|
|
201
|
+
const wrapperViewStyle: ViewStyle = {
|
|
202
|
+
backgroundColor:
|
|
203
|
+
isTablet && !fullscreen
|
|
204
|
+
? configuration?.tablet_landscape_player_container_background_color
|
|
205
|
+
: "transparent",
|
|
206
|
+
};
|
|
207
|
+
|
|
127
208
|
return (
|
|
128
209
|
<WrapperView
|
|
129
210
|
edges={getEdges(isTablet, isInlineModal) as readonly Edge[]}
|
|
130
|
-
style={playerDimensionsHack}
|
|
211
|
+
style={[wrapperViewStyle, style, playerDimensionsHack]}
|
|
131
212
|
>
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
playerDimensionsHack,
|
|
137
|
-
containerDimensions,
|
|
138
|
-
containerStyle,
|
|
139
|
-
]}
|
|
213
|
+
<AnimationComponent
|
|
214
|
+
animationType={ComponentAnimationType.moveUpComponent}
|
|
215
|
+
additionalData={{ saveArea: true }}
|
|
216
|
+
style={[directionStyles(isTabletLandscape), defaultStyles.flex]}
|
|
140
217
|
>
|
|
141
|
-
|
|
142
|
-
|
|
218
|
+
<View
|
|
219
|
+
testID={`${entry?.id}-player-container`}
|
|
220
|
+
style={[
|
|
221
|
+
defaultStyles.playerContainer,
|
|
222
|
+
containerDimensions,
|
|
223
|
+
containerStyle,
|
|
224
|
+
playerDimensionsHack,
|
|
225
|
+
]}
|
|
226
|
+
>
|
|
227
|
+
<AnimationComponent
|
|
228
|
+
animationType={ComponentAnimationType.moveUpComponent}
|
|
229
|
+
style={isTabletLandscape ? defaultStyles.flex : undefined}
|
|
230
|
+
additionalData={{
|
|
231
|
+
useLayoutMeasure: isTabletLandscape,
|
|
232
|
+
disableAnimatedComponent: !isTabletLandscape,
|
|
233
|
+
resetAnimationValue: isTabletLandscape && docked,
|
|
234
|
+
}}
|
|
235
|
+
>
|
|
236
|
+
<AnimatedVideoPlayerComponent>
|
|
237
|
+
{children(childrenStyles)}
|
|
238
|
+
</AnimatedVideoPlayerComponent>
|
|
239
|
+
</AnimationComponent>
|
|
240
|
+
</View>
|
|
241
|
+
|
|
242
|
+
<AnimatedScrollModal>
|
|
243
|
+
{isShowPlayerDetails ? (
|
|
244
|
+
<AnimationComponent
|
|
245
|
+
animationType={ComponentAnimationType.componentFade}
|
|
246
|
+
style={defaultStyles.flex}
|
|
247
|
+
>
|
|
248
|
+
<PlayerDetails
|
|
249
|
+
configuration={configuration}
|
|
250
|
+
style={defaultStyles.playerDetails}
|
|
251
|
+
entry={entry}
|
|
252
|
+
isTabletLandscape={isTabletLandscape}
|
|
253
|
+
isTablet={isTablet}
|
|
254
|
+
/>
|
|
255
|
+
</AnimationComponent>
|
|
256
|
+
) : null}
|
|
257
|
+
</AnimatedScrollModal>
|
|
258
|
+
</AnimationComponent>
|
|
143
259
|
</WrapperView>
|
|
144
260
|
);
|
|
145
261
|
};
|
|
@@ -17,7 +17,11 @@ import {
|
|
|
17
17
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks/device/useIsTablet";
|
|
18
18
|
|
|
19
19
|
import { withModalNavigationContextProvider } from "../../Contexts/ModalNavigationContext";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
useModalSize,
|
|
22
|
+
useBackgroundColor,
|
|
23
|
+
useInitialPlayerState,
|
|
24
|
+
} from "./hooks";
|
|
21
25
|
|
|
22
26
|
import { APP_EVENTS } from "@applicaster/zapp-react-native-utils/appUtils/events";
|
|
23
27
|
import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
|
|
@@ -29,6 +33,8 @@ import { ScreenContextProvider } from "../../Contexts/ScreenContext";
|
|
|
29
33
|
import { Spinner } from "../Spinner";
|
|
30
34
|
import { OpaqueLayer } from "./OpaqueLayer";
|
|
31
35
|
|
|
36
|
+
import { AnimatedPlayerModalWrapper } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
37
|
+
|
|
32
38
|
const LOADER_BACKGROUND_COLOR = "rgba(64,64,64,0.5)";
|
|
33
39
|
|
|
34
40
|
const styles = StyleSheet.create({
|
|
@@ -59,6 +65,7 @@ const VideoModalComponent = () => {
|
|
|
59
65
|
|
|
60
66
|
const modalSize = useModalSize();
|
|
61
67
|
const isFirstRender = useIsInitialRender();
|
|
68
|
+
const backgroundColor = useBackgroundColor();
|
|
62
69
|
|
|
63
70
|
const {
|
|
64
71
|
closeVideoModal,
|
|
@@ -138,13 +145,20 @@ const VideoModalComponent = () => {
|
|
|
138
145
|
{mode === "FULLSCREEN" && <OpaqueLayer />}
|
|
139
146
|
|
|
140
147
|
{itemIdHooksFinished === item?.id ? (
|
|
141
|
-
<
|
|
148
|
+
<AnimatedPlayerModalWrapper
|
|
149
|
+
style={[
|
|
150
|
+
styles.container,
|
|
151
|
+
{
|
|
152
|
+
backgroundColor,
|
|
153
|
+
},
|
|
154
|
+
]}
|
|
155
|
+
>
|
|
142
156
|
<HandlePlayable
|
|
143
157
|
item={item}
|
|
144
158
|
isModal={mode !== "PIP"}
|
|
145
159
|
mode={mode}
|
|
146
160
|
/>
|
|
147
|
-
</
|
|
161
|
+
</AnimatedPlayerModalWrapper>
|
|
148
162
|
) : (
|
|
149
163
|
<View style={styles.loaderContainer}>
|
|
150
164
|
<Spinner />
|
|
@@ -13,7 +13,6 @@ const props = {
|
|
|
13
13
|
tablet_landscape_sidebar_width: "35%",
|
|
14
14
|
tablet_landscape_player_container_background_color: "red",
|
|
15
15
|
},
|
|
16
|
-
playerContent: jest.fn(() => <></>),
|
|
17
16
|
};
|
|
18
17
|
|
|
19
18
|
const mockUseIsDeviceTablet = jest.fn();
|
|
@@ -123,6 +122,13 @@ describe("PlayerWrapper", () => {
|
|
|
123
122
|
</PlayerWrapper>
|
|
124
123
|
);
|
|
125
124
|
|
|
125
|
+
const expectDimensions = {
|
|
126
|
+
...dimensions,
|
|
127
|
+
width: undefined,
|
|
128
|
+
aspectRatio: 16 / 9,
|
|
129
|
+
};
|
|
130
|
+
|
|
126
131
|
expect(element).toMatchSnapshot();
|
|
132
|
+
expect(children).toHaveBeenCalledWith(expectDimensions);
|
|
127
133
|
});
|
|
128
134
|
});
|