@applicaster/zapp-react-native-ui-components 13.0.0-alpha.6400875052 → 13.0.0-alpha.6444233049
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 +0 -11
- package/Components/AudioPlayer/helpers.tsx +0 -2
- package/Components/Cell/CellWithFocusable.tsx +4 -2
- package/Components/Cell/CellWrapper.tsx +18 -0
- package/Components/CellRendererResolver/index.ts +2 -1
- package/Components/GeneralContentScreen/GeneralContentScreen.tsx +3 -0
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +4 -2
- package/Components/GeneralContentScreen/utils/useEventAlerts.ts +30 -0
- package/Components/Layout/TV/LayoutBackground.tsx +28 -0
- package/Components/Layout/TV/ScreenContainer.tsx +0 -1
- package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +15 -10
- package/Components/Layout/TV/__tests__/index.test.tsx +8 -2
- package/Components/Layout/TV/index.tsx +6 -20
- package/Components/Layout/TV/index.web.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
- package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
- package/Components/ModalComponent/BottomSheetModalContent.tsx +34 -45
- package/Components/ModalComponent/Button/Item.tsx +5 -5
- package/Components/ModalComponent/Button/index.tsx +25 -29
- package/Components/ModalComponent/Header/index.tsx +9 -8
- package/Components/ModalComponent/utils.ts +3 -3
- package/Components/PlayerContainer/PlayerContainer.tsx +18 -5
- package/Components/River/ComponentsMap/ComponentsMap.tsx +11 -3
- package/Components/River/RiverItem.tsx +8 -3
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +7 -1
- package/Components/Screen/TV/__tests__/index.web.test.tsx +26 -0
- package/Components/Screen/__tests__/Screen.test.tsx +22 -14
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -2
- package/Components/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +4 -2
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +17 -10
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +9 -1
- package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
- package/Components/VideoModal/ModalAnimation/const.ts +5 -0
- package/Components/VideoModal/ModalAnimation/index.ts +2 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +30 -0
- package/Components/VideoModal/PlayerDetails.tsx +5 -0
- package/Components/VideoModal/PlayerWrapper.tsx +9 -19
- package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
- package/Components/VideoModal/utils.ts +3 -4
- package/package.json +5 -5
- package/Components/Cell/CellWrapper.ts +0 -5
|
@@ -8,13 +8,18 @@ import { PluginConfiguration } from "../index";
|
|
|
8
8
|
type Props = {
|
|
9
9
|
dismiss: () => void;
|
|
10
10
|
configuration: PluginConfiguration;
|
|
11
|
-
width: number;
|
|
12
11
|
onLayout?: (event: LayoutChangeEvent) => void;
|
|
13
12
|
summary?: string;
|
|
14
13
|
title?: string;
|
|
15
14
|
};
|
|
16
15
|
|
|
17
16
|
const styles = StyleSheet.create({
|
|
17
|
+
noFlex: {
|
|
18
|
+
flex: 0,
|
|
19
|
+
},
|
|
20
|
+
flex: {
|
|
21
|
+
flex: 1,
|
|
22
|
+
},
|
|
18
23
|
container: {
|
|
19
24
|
flexDirection: "row",
|
|
20
25
|
alignItems: "center",
|
|
@@ -22,7 +27,7 @@ const styles = StyleSheet.create({
|
|
|
22
27
|
});
|
|
23
28
|
|
|
24
29
|
export function ModalHeader(props: Props) {
|
|
25
|
-
const { configuration, dismiss,
|
|
30
|
+
const { configuration, dismiss, onLayout, summary, title } = props;
|
|
26
31
|
|
|
27
32
|
const closeButtonProps = useMemo<CloseButtonProps>(
|
|
28
33
|
() => ({
|
|
@@ -55,15 +60,11 @@ export function ModalHeader(props: Props) {
|
|
|
55
60
|
|
|
56
61
|
return (
|
|
57
62
|
<View onLayout={onLayout} style={styles.container}>
|
|
58
|
-
<View
|
|
59
|
-
style={{
|
|
60
|
-
width: width - buttonsContainerWidth,
|
|
61
|
-
}}
|
|
62
|
-
>
|
|
63
|
+
<View style={styles.flex}>
|
|
63
64
|
{title ? <Title {...titleProps} /> : null}
|
|
64
65
|
{summary ? <Title {...summaryProps} /> : null}
|
|
65
66
|
</View>
|
|
66
|
-
<View style={{ width: buttonsContainerWidth }}>
|
|
67
|
+
<View style={[styles.noFlex, { width: buttonsContainerWidth }]}>
|
|
67
68
|
<CloseButton {...closeButtonProps} />
|
|
68
69
|
</View>
|
|
69
70
|
</View>
|
|
@@ -12,7 +12,7 @@ export function defaultItemProps(
|
|
|
12
12
|
modal_bottom_sheet_item_background_color,
|
|
13
13
|
modal_bottom_sheet_item_focus_background_color,
|
|
14
14
|
modal_bottom_sheet_item_selected_background_color,
|
|
15
|
-
|
|
15
|
+
modal_bottom_sheet_item_focused_selected_background_color,
|
|
16
16
|
modal_bottom_sheet_item_corner_radius,
|
|
17
17
|
modal_bottom_sheet_item_margin_bottom,
|
|
18
18
|
modal_bottom_sheet_item_margin_left,
|
|
@@ -28,8 +28,8 @@ export function defaultItemProps(
|
|
|
28
28
|
backgroundColor: modal_bottom_sheet_item_background_color,
|
|
29
29
|
focusedBackgroundColor: modal_bottom_sheet_item_focus_background_color,
|
|
30
30
|
selectedBackgroundColor: modal_bottom_sheet_item_selected_background_color,
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
focusedSelectedBackgroundColor:
|
|
32
|
+
modal_bottom_sheet_item_focused_selected_background_color,
|
|
33
33
|
borderRadius: modal_bottom_sheet_item_corner_radius,
|
|
34
34
|
marginBottom: modal_bottom_sheet_item_margin_bottom,
|
|
35
35
|
marginTop: modal_bottom_sheet_item_margin_top,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
isApplePlatform,
|
|
10
10
|
isTV,
|
|
11
11
|
platformSelect,
|
|
12
|
+
isAndroidTVPlatform,
|
|
12
13
|
} from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
13
14
|
|
|
14
15
|
import { TVEventHandlerComponent } from "@applicaster/zapp-react-native-tvos-ui-components/Components/TVEventHandlerComponent";
|
|
@@ -93,6 +94,20 @@ export type PlayNextData = {
|
|
|
93
94
|
|
|
94
95
|
const focusableBottomContainerId = "player-container-bottom";
|
|
95
96
|
|
|
97
|
+
const isAndroidTV = isAndroidTVPlatform();
|
|
98
|
+
|
|
99
|
+
const withBorderHack = () => {
|
|
100
|
+
if (isAndroidTV) {
|
|
101
|
+
/* @HACK: see GH#7269 */
|
|
102
|
+
return {
|
|
103
|
+
borderWidth: 1,
|
|
104
|
+
borderColor: "transparent",
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return {};
|
|
109
|
+
};
|
|
110
|
+
|
|
96
111
|
// Styles
|
|
97
112
|
const webStyles = {
|
|
98
113
|
focusableGroup: {
|
|
@@ -582,7 +597,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
582
597
|
);
|
|
583
598
|
}
|
|
584
599
|
|
|
585
|
-
if (screen_background_color) {
|
|
600
|
+
if (screen_background_color && mode !== VideoModalMode.FULLSCREEN) {
|
|
586
601
|
updatedStyles.playerScreen.backgroundColor = screen_background_color;
|
|
587
602
|
}
|
|
588
603
|
|
|
@@ -600,6 +615,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
600
615
|
tv_component_container_height,
|
|
601
616
|
screen_background_color,
|
|
602
617
|
isInlineTV,
|
|
618
|
+
mode,
|
|
603
619
|
]);
|
|
604
620
|
|
|
605
621
|
const applePlayerProps = {
|
|
@@ -648,10 +664,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
648
664
|
style={[
|
|
649
665
|
styles.playerWrapper,
|
|
650
666
|
// eslint-disable-next-line react-native/no-inline-styles, react-native/no-color-literals
|
|
651
|
-
|
|
652
|
-
borderWidth: 1,
|
|
653
|
-
borderColor: "transparent",
|
|
654
|
-
} /* @HACK: see GH#7269 */,
|
|
667
|
+
withBorderHack(),
|
|
655
668
|
]}
|
|
656
669
|
testID={"player-wrapper"}
|
|
657
670
|
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
|
-
import { View, StyleSheet,
|
|
3
|
+
import { View, StyleSheet, FlatList } from "react-native";
|
|
4
4
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
5
5
|
import { RiverItem } from "../RiverItem";
|
|
6
6
|
import { RiverFooter } from "../RiverFooter";
|
|
@@ -24,6 +24,10 @@ import { withComponentsMapProvider } from "@applicaster/zapp-react-native-ui-com
|
|
|
24
24
|
import { useScreenContextV2 } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
|
|
25
25
|
import { useShallow } from "zustand/react/shallow";
|
|
26
26
|
|
|
27
|
+
import { isAndroidPlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
28
|
+
|
|
29
|
+
const isAndroid = isAndroidPlatform();
|
|
30
|
+
|
|
27
31
|
type Props = {
|
|
28
32
|
feed: ZappFeed;
|
|
29
33
|
groupId?: string;
|
|
@@ -273,12 +277,12 @@ function ComponentsMapComponent(props: Props) {
|
|
|
273
277
|
}}
|
|
274
278
|
// Fix for WebView rerender crashes on Android API 28+
|
|
275
279
|
// https://github.com/react-native-webview/react-native-webview/issues/1915#issuecomment-964035468
|
|
276
|
-
overScrollMode={
|
|
280
|
+
overScrollMode={isAndroid ? "never" : "auto"}
|
|
277
281
|
scrollIndicatorInsets={scrollIndicatorInsets}
|
|
278
282
|
extraData={feed}
|
|
279
283
|
stickyHeaderIndices={stickyHeaderIndices}
|
|
280
284
|
onLayout={handleOnLayout}
|
|
281
|
-
removeClippedSubviews
|
|
285
|
+
removeClippedSubviews={isAndroid}
|
|
282
286
|
initialNumToRender={3}
|
|
283
287
|
maxToRenderPerBatch={10}
|
|
284
288
|
windowSize={12}
|
|
@@ -299,6 +303,10 @@ function ComponentsMapComponent(props: Props) {
|
|
|
299
303
|
onMomentumScrollEnd={_onMomentumScrollEnd}
|
|
300
304
|
onScrollEndDrag={_onScrollEndDrag}
|
|
301
305
|
scrollEventThrottle={16}
|
|
306
|
+
maintainVisibleContentPosition={{
|
|
307
|
+
minIndexForVisible: 0,
|
|
308
|
+
autoscrollToTopThreshold: 10,
|
|
309
|
+
}}
|
|
302
310
|
{...scrollViewExtraProps}
|
|
303
311
|
/>
|
|
304
312
|
</ViewportTracker>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React, { useEffect } from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
|
+
import { isGroup } from "@applicaster/zapp-react-native-utils/componentsUtils";
|
|
3
4
|
|
|
4
5
|
import { applyDecorators } from "../../Decorators";
|
|
5
6
|
|
|
@@ -47,16 +48,20 @@ const useLoadingState = (
|
|
|
47
48
|
loadingState: RiverItemType["loadingState"]
|
|
48
49
|
) => {
|
|
49
50
|
const [readyToBeDisplayed, setReadyToBeDisplayed] = React.useState(
|
|
50
|
-
loadingState.getValue().index + 1
|
|
51
|
+
loadingState.getValue().index + 1 >= currentIndex
|
|
51
52
|
);
|
|
52
53
|
|
|
53
54
|
useEffect(() => {
|
|
54
55
|
const subscription = loadingState.subscribe(({ index }) => {
|
|
55
|
-
if (index + 1
|
|
56
|
+
if (index + 1 >= currentIndex) {
|
|
56
57
|
setReadyToBeDisplayed(true);
|
|
57
58
|
}
|
|
58
59
|
});
|
|
59
60
|
|
|
61
|
+
if (loadingState.getValue().index + 1 >= currentIndex) {
|
|
62
|
+
setReadyToBeDisplayed(true);
|
|
63
|
+
}
|
|
64
|
+
|
|
60
65
|
return () => {
|
|
61
66
|
subscription.unsubscribe();
|
|
62
67
|
};
|
|
@@ -112,7 +117,7 @@ function RiverItemComponent(props: RiverItemType) {
|
|
|
112
117
|
jsOnly: true,
|
|
113
118
|
});
|
|
114
119
|
|
|
115
|
-
if (!CellRenderer && item
|
|
120
|
+
if (!CellRenderer && !isGroup(item)) {
|
|
116
121
|
riverLogger.warning({
|
|
117
122
|
message: "Cell Renderer is null - will fallback to default cell",
|
|
118
123
|
data: { item, CellRenderer },
|
|
@@ -135,6 +135,12 @@ exports[`componentsMap renders renders components map correctly 1`] = `
|
|
|
135
135
|
getItemCount={[Function]}
|
|
136
136
|
initialNumToRender={3}
|
|
137
137
|
keyExtractor={[Function]}
|
|
138
|
+
maintainVisibleContentPosition={
|
|
139
|
+
{
|
|
140
|
+
"autoscrollToTopThreshold": 10,
|
|
141
|
+
"minIndexForVisible": 0,
|
|
142
|
+
}
|
|
143
|
+
}
|
|
138
144
|
maxToRenderPerBatch={10}
|
|
139
145
|
onContentSizeChange={[Function]}
|
|
140
146
|
onLayout={[Function]}
|
|
@@ -145,7 +151,7 @@ exports[`componentsMap renders renders components map correctly 1`] = `
|
|
|
145
151
|
onScrollEndDrag={[Function]}
|
|
146
152
|
overScrollMode="auto"
|
|
147
153
|
refreshControl={null}
|
|
148
|
-
removeClippedSubviews={
|
|
154
|
+
removeClippedSubviews={false}
|
|
149
155
|
renderItem={[Function]}
|
|
150
156
|
scrollEventThrottle={16}
|
|
151
157
|
scrollIndicatorInsets={
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const {
|
|
2
|
+
useScreenBackgroundColor,
|
|
3
|
+
} = require("@applicaster/zapp-react-native-utils/reactHooks/screen");
|
|
4
|
+
|
|
5
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen", () => ({
|
|
6
|
+
useScreenBackgroundColor: jest.fn(),
|
|
7
|
+
useNavbarState: jest.fn().mockReturnValue({ visible: true }),
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
describe("TV Screen Component", () => {
|
|
11
|
+
it("uses the useScreenBackgroundColor hook with the correct screen ID", () => {
|
|
12
|
+
useScreenBackgroundColor.mockReturnValue("#FF0000");
|
|
13
|
+
|
|
14
|
+
expect(useScreenBackgroundColor("test-screen-id")).toBe("#FF0000");
|
|
15
|
+
|
|
16
|
+
// Verify the hook was called with the correct screen ID
|
|
17
|
+
expect(useScreenBackgroundColor).toHaveBeenCalledWith("test-screen-id");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("returns 'transparent' when the screen background color is not defined", () => {
|
|
21
|
+
useScreenBackgroundColor.mockReturnValue("transparent");
|
|
22
|
+
|
|
23
|
+
// Verify the hook returns 'transparent'
|
|
24
|
+
expect(useScreenBackgroundColor("test-screen-id")).toBe("transparent");
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -68,21 +68,21 @@ jest.mock(
|
|
|
68
68
|
})
|
|
69
69
|
);
|
|
70
70
|
|
|
71
|
-
jest.mock(
|
|
72
|
-
"@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenData",
|
|
73
|
-
() => ({
|
|
74
|
-
useScreenData: jest.fn(() => ({
|
|
75
|
-
id: "testId",
|
|
76
|
-
navigations: [{ id: "testId", category: "nav_bar" }],
|
|
77
|
-
})),
|
|
78
|
-
})
|
|
79
|
-
);
|
|
80
|
-
|
|
81
71
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
|
|
82
72
|
isNavBarVisible: mockIsNavBarVisible,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
73
|
+
useIsScreenActive: jest.fn().mockReturnValue(true),
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => ({
|
|
77
|
+
useCurrentScreenData: jest.fn(() => ({
|
|
78
|
+
id: "testId",
|
|
79
|
+
})),
|
|
80
|
+
useNavbarState: jest.fn(() => ({
|
|
81
|
+
title: "Test Title",
|
|
82
|
+
})),
|
|
83
|
+
useScreenData: jest.fn(() => ({
|
|
84
|
+
id: "testId",
|
|
85
|
+
navigations: [{ id: "testId", category: "nav_bar" }],
|
|
86
86
|
})),
|
|
87
87
|
useNavigation: jest.fn(() => ({
|
|
88
88
|
canGoBack: () => false,
|
|
@@ -91,7 +91,15 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
|
|
|
91
91
|
screenData: { id: "testId" },
|
|
92
92
|
data: { screen: { id: "testId" } },
|
|
93
93
|
})),
|
|
94
|
-
|
|
94
|
+
useRoute: jest.fn(() => ({
|
|
95
|
+
pathname: "/river/testId",
|
|
96
|
+
screenData: { id: "testId" },
|
|
97
|
+
})),
|
|
98
|
+
useDimensions: jest.fn(() => ({
|
|
99
|
+
width: 1920,
|
|
100
|
+
height: 1080,
|
|
101
|
+
})),
|
|
102
|
+
useIsTablet: jest.fn(() => false),
|
|
95
103
|
}));
|
|
96
104
|
|
|
97
105
|
jest.mock("@applicaster/zapp-react-native-redux/hooks/usePickFromState", () => {
|
|
@@ -16,7 +16,7 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
|
|
|
16
16
|
pathname="/river/testId"
|
|
17
17
|
selected="testId"
|
|
18
18
|
testID="navBar"
|
|
19
|
-
title=""
|
|
19
|
+
title="Test Title"
|
|
20
20
|
/>
|
|
21
21
|
<View>
|
|
22
22
|
<View
|
|
@@ -48,7 +48,7 @@ exports[`<Screen Component /> when the navbar should show renders correctly 1`]
|
|
|
48
48
|
pathname="/river/testId"
|
|
49
49
|
selected="testId"
|
|
50
50
|
testID="navBar"
|
|
51
|
-
title=""
|
|
51
|
+
title="Test Title"
|
|
52
52
|
/>
|
|
53
53
|
<View>
|
|
54
54
|
<View
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { View, ViewProps, 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
|
+
import { isFirstComponentScreenPicker } from "@applicaster/zapp-react-native-utils/componentsUtils";
|
|
5
6
|
|
|
6
7
|
interface IProps {
|
|
7
8
|
targetScreenId?: string;
|
|
@@ -31,11 +32,9 @@ export const useMarginTop = (targetScreenId: string): number => {
|
|
|
31
32
|
* ScreenPicker is a component but should really be a screen.
|
|
32
33
|
* We need to skip margin top for it as it's already applied to the target screen
|
|
33
34
|
**/
|
|
34
|
-
const isScreenPicker =
|
|
35
|
-
screenData?.ui_components?.[0]?.component_type === "screen-picker-qb-tv";
|
|
36
35
|
|
|
37
36
|
// ignore margin on screenPicker
|
|
38
|
-
if (
|
|
37
|
+
if (isFirstComponentScreenPicker(screenData?.ui_components)) {
|
|
39
38
|
return 0;
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -23,10 +23,12 @@ import {
|
|
|
23
23
|
setScrollModalAnimatedValue,
|
|
24
24
|
} from "./utils";
|
|
25
25
|
|
|
26
|
+
import { DURATION_TO_MINIMIZE } from "./const";
|
|
27
|
+
|
|
26
28
|
const getAnimatedConfig = (toValue) => {
|
|
27
29
|
return {
|
|
28
30
|
toValue,
|
|
29
|
-
duration:
|
|
31
|
+
duration: DURATION_TO_MINIMIZE,
|
|
30
32
|
useNativeDriver: true,
|
|
31
33
|
};
|
|
32
34
|
};
|
|
@@ -142,7 +144,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
|
|
|
142
144
|
|
|
143
145
|
setLastSnap(destSnapPoint);
|
|
144
146
|
|
|
145
|
-
if (destSnapPoint === modalSnapPoints[0]
|
|
147
|
+
if (destSnapPoint === modalSnapPoints[0]) {
|
|
146
148
|
translateYOffset.extractOffset();
|
|
147
149
|
translateYOffset.setValue(preparedTranslationY);
|
|
148
150
|
translateYOffset.flattenOffset();
|
|
@@ -24,8 +24,11 @@ import {
|
|
|
24
24
|
gestureListenerHelper,
|
|
25
25
|
getAnimationDefaultValue,
|
|
26
26
|
getAnimationStyle,
|
|
27
|
+
getMoveUpValue,
|
|
27
28
|
} from "./utils";
|
|
28
29
|
|
|
30
|
+
import { DURATION_TO_MINIMIZE, DEFAULT_DURATION_FOR_ANIMATION } from "./const";
|
|
31
|
+
|
|
29
32
|
type Props = {
|
|
30
33
|
animationType: string;
|
|
31
34
|
children: React.ReactNode;
|
|
@@ -91,20 +94,21 @@ export const AnimationView = ({
|
|
|
91
94
|
const isAudioItem = React.useMemo(
|
|
92
95
|
() =>
|
|
93
96
|
videoModalItem?.content?.type?.includes?.("audio") ||
|
|
94
|
-
videoModalItem?.type?.value
|
|
97
|
+
videoModalItem?.type?.value?.includes?.("audio"),
|
|
95
98
|
[videoModalItem]
|
|
96
99
|
);
|
|
97
100
|
|
|
98
101
|
const inlineAudioPlayer = additionalData.inlineAudioPlayer;
|
|
99
102
|
|
|
100
|
-
const moveUpValue =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
const moveUpValue = getMoveUpValue({
|
|
104
|
+
additionalData,
|
|
105
|
+
insets,
|
|
106
|
+
isAudioItem,
|
|
107
|
+
progressBarHeight,
|
|
108
|
+
isTablet,
|
|
109
|
+
isTabletLandscape,
|
|
110
|
+
tabletLandscapePlayerTopPosition,
|
|
111
|
+
});
|
|
108
112
|
|
|
109
113
|
const moveComponentHorizontalValue = additionalData.moveValue
|
|
110
114
|
? isRTL
|
|
@@ -119,7 +123,10 @@ export const AnimationView = ({
|
|
|
119
123
|
(animationType, state) => {
|
|
120
124
|
const defaultConfig = {
|
|
121
125
|
toValue: 0,
|
|
122
|
-
duration:
|
|
126
|
+
duration:
|
|
127
|
+
state === PlayerAnimationStateEnum.minimize
|
|
128
|
+
? DURATION_TO_MINIMIZE
|
|
129
|
+
: DEFAULT_DURATION_FOR_ANIMATION,
|
|
123
130
|
useNativeDriver: true,
|
|
124
131
|
};
|
|
125
132
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
2
|
import { Animated } from "react-native";
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -17,6 +17,7 @@ export enum PlayerAnimationStateEnum {
|
|
|
17
17
|
maximize = "maximize",
|
|
18
18
|
drag_player = "drag_player",
|
|
19
19
|
drag_scroll = "drag_scroll",
|
|
20
|
+
appear_as_docked = "appear_as_docked",
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export type PlayerAnimationStateT = number | PlayerAnimationStateEnum | null;
|
|
@@ -95,6 +96,13 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
|
95
96
|
setStartComponentsAnimation(false);
|
|
96
97
|
}, []);
|
|
97
98
|
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
// Reset player animation state when video modal is closed
|
|
101
|
+
if (!visible) {
|
|
102
|
+
resetPlayerAnimationState();
|
|
103
|
+
}
|
|
104
|
+
}, [visible, resetPlayerAnimationState]);
|
|
105
|
+
|
|
98
106
|
// Animated values
|
|
99
107
|
const lastScrollY = React.useRef(new Animated.Value(0)).current;
|
|
100
108
|
const dragScrollY = React.useRef(new Animated.Value(0)).current;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { getMoveUpValue } from "../utils";
|
|
2
|
+
|
|
3
|
+
describe("getMoveUpValue", () => {
|
|
4
|
+
it("returns correct value when additionalData.saveArea is true and isAudioItem is false", () => {
|
|
5
|
+
const result = getMoveUpValue({
|
|
6
|
+
additionalData: { saveArea: true },
|
|
7
|
+
insets: { top: 20 },
|
|
8
|
+
isAudioItem: false,
|
|
9
|
+
progressBarHeight: 10,
|
|
10
|
+
isTablet: false,
|
|
11
|
+
isTabletLandscape: false,
|
|
12
|
+
inlineAudioPlayer: false,
|
|
13
|
+
tabletLandscapePlayerTopPosition: 100,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect(result).toBe(-20 + 10);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("returns correct value when additionalData.saveArea is true and isAudioItem is true", () => {
|
|
20
|
+
const result = getMoveUpValue({
|
|
21
|
+
additionalData: { saveArea: true },
|
|
22
|
+
insets: { top: 15 },
|
|
23
|
+
isAudioItem: true,
|
|
24
|
+
progressBarHeight: 5,
|
|
25
|
+
isTablet: false,
|
|
26
|
+
isTabletLandscape: false,
|
|
27
|
+
inlineAudioPlayer: false,
|
|
28
|
+
tabletLandscapePlayerTopPosition: 100,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
expect(result).toBe(-15 + 0);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("returns correct value for audio item (tablet or not)", () => {
|
|
35
|
+
const result = getMoveUpValue({
|
|
36
|
+
additionalData: { marginTop: 30 },
|
|
37
|
+
insets: { top: 0 },
|
|
38
|
+
isAudioItem: true,
|
|
39
|
+
progressBarHeight: 0,
|
|
40
|
+
isTablet: false,
|
|
41
|
+
isTabletLandscape: false,
|
|
42
|
+
inlineAudioPlayer: false,
|
|
43
|
+
tabletLandscapePlayerTopPosition: 0,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
expect(result).toBe(-30);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("returns correct value for tablet landscape with inline audio player", () => {
|
|
50
|
+
const result = getMoveUpValue({
|
|
51
|
+
additionalData: {},
|
|
52
|
+
insets: { top: 0 },
|
|
53
|
+
isAudioItem: true,
|
|
54
|
+
progressBarHeight: 8,
|
|
55
|
+
isTablet: true,
|
|
56
|
+
isTabletLandscape: true,
|
|
57
|
+
inlineAudioPlayer: true,
|
|
58
|
+
tabletLandscapePlayerTopPosition: 50,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
expect(result).toBe(-0);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("returns correct value for tablet landscape without audio item", () => {
|
|
65
|
+
const result = getMoveUpValue({
|
|
66
|
+
additionalData: {},
|
|
67
|
+
insets: { top: 0 },
|
|
68
|
+
isAudioItem: false,
|
|
69
|
+
progressBarHeight: 12,
|
|
70
|
+
isTablet: true,
|
|
71
|
+
isTabletLandscape: true,
|
|
72
|
+
inlineAudioPlayer: false,
|
|
73
|
+
tabletLandscapePlayerTopPosition: 60,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
expect(result).toBe(-60 + 12);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("returns -130 for tablet portrait (not landscape)", () => {
|
|
80
|
+
const result = getMoveUpValue({
|
|
81
|
+
additionalData: {},
|
|
82
|
+
insets: { top: 0 },
|
|
83
|
+
isAudioItem: false,
|
|
84
|
+
progressBarHeight: 0,
|
|
85
|
+
isTablet: true,
|
|
86
|
+
isTabletLandscape: false,
|
|
87
|
+
inlineAudioPlayer: false,
|
|
88
|
+
tabletLandscapePlayerTopPosition: 0,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(result).toBe(-130);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("returns -50 + progressBarHeight for mobile audio player in docked mode", () => {
|
|
95
|
+
const result = getMoveUpValue({
|
|
96
|
+
additionalData: {},
|
|
97
|
+
insets: { top: 0 },
|
|
98
|
+
isAudioItem: false,
|
|
99
|
+
progressBarHeight: 7,
|
|
100
|
+
isTablet: false,
|
|
101
|
+
isTabletLandscape: false,
|
|
102
|
+
inlineAudioPlayer: false,
|
|
103
|
+
tabletLandscapePlayerTopPosition: 0,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
expect(result).toBe(-50 + 7);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -14,3 +14,5 @@ export { useModalAnimationContext } from "./useModalAnimationContext";
|
|
|
14
14
|
export { AnimationComponent } from "./AnimationComponent";
|
|
15
15
|
|
|
16
16
|
export { ComponentAnimationType, defaultAspectRatioWidth } from "./utils";
|
|
17
|
+
|
|
18
|
+
export { DURATION_TO_MINIMIZE, DURATION_TO_MAXIMIZE } from "./const";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable padding-line-between-statements */
|
|
2
2
|
|
|
3
3
|
import { PlayerAnimationStateEnum } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
4
|
+
import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
4
5
|
|
|
5
6
|
export enum ComponentAnimationType {
|
|
6
7
|
bottomBar = "bottomBar",
|
|
@@ -300,3 +301,32 @@ export const resetScrollAnimatedValues = (
|
|
|
300
301
|
dragScrollY.setValue(0);
|
|
301
302
|
dragVideoPlayerY.setValue(0);
|
|
302
303
|
};
|
|
304
|
+
|
|
305
|
+
export const getMoveUpValue = ({
|
|
306
|
+
additionalData,
|
|
307
|
+
insets,
|
|
308
|
+
isAudioItem,
|
|
309
|
+
progressBarHeight,
|
|
310
|
+
isTablet,
|
|
311
|
+
isTabletLandscape,
|
|
312
|
+
tabletLandscapePlayerTopPosition,
|
|
313
|
+
}) => {
|
|
314
|
+
if (additionalData.saveArea) {
|
|
315
|
+
return -insets.top + (isAudioItem ? 0 : progressBarHeight);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (isAudioItem) {
|
|
319
|
+
// for any layouts in audioPlayer
|
|
320
|
+
return -1 * toNumberWithDefaultZero(additionalData?.marginTop);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (isTablet) {
|
|
324
|
+
if (isTabletLandscape) {
|
|
325
|
+
return -tabletLandscapePlayerTopPosition + progressBarHeight;
|
|
326
|
+
} else {
|
|
327
|
+
return -130;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return -50 + progressBarHeight;
|
|
332
|
+
};
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { useTargetScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
|
|
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
|
+
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
13
14
|
|
|
14
15
|
const { width: SCREEN_WIDTH } = Dimensions.get("screen");
|
|
15
16
|
|
|
@@ -78,6 +79,10 @@ export const PlayerDetails = ({
|
|
|
78
79
|
}
|
|
79
80
|
}, [isAudioPlayer]);
|
|
80
81
|
|
|
82
|
+
if (isNilOrEmpty(screenData?.ui_components)) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
81
86
|
return (
|
|
82
87
|
<Animated.View
|
|
83
88
|
style={[
|