@applicaster/zapp-react-native-ui-components 13.0.0-alpha.7586259907 → 13.0.0-alpha.7620873141
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/Cell/CellWithFocusable.tsx +4 -2
- package/Components/Cell/CellWrapper.tsx +18 -0
- package/Components/CellRendererResolver/index.ts +2 -1
- 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 +45 -19
- package/Components/ModalComponent/Button/Item.tsx +6 -5
- package/Components/ModalComponent/Button/index.tsx +29 -42
- package/Components/ModalComponent/utils.ts +55 -7
- package/Components/PlayerContainer/PlayerContainer.tsx +16 -1
- package/Components/River/RiverItem.tsx +2 -1
- package/Components/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +4 -2
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +21 -9
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +8 -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 +36 -0
- package/Components/VideoModal/PlayerDetails.tsx +9 -4
- package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
- package/Components/VideoModal/utils.ts +3 -4
- package/Components/ZappUIComponent/index.tsx +4 -4
- package/package.json +5 -5
- package/Components/Cell/CellWrapper.ts +0 -5
|
@@ -23,6 +23,8 @@ type Props = {
|
|
|
23
23
|
focused?: boolean;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
const addPrefix = (id: string) => `focusable-cell-wrapper-${id}`;
|
|
27
|
+
|
|
26
28
|
export function CellWithFocusable(props: Props) {
|
|
27
29
|
const {
|
|
28
30
|
index,
|
|
@@ -81,7 +83,7 @@ export function CellWithFocusable(props: Props) {
|
|
|
81
83
|
|
|
82
84
|
return (
|
|
83
85
|
<FocusableGroup
|
|
84
|
-
id={
|
|
86
|
+
id={addPrefix(id)}
|
|
85
87
|
testID={"cell-with-focusable-cell-renderer-focusable-group"}
|
|
86
88
|
groupId={groupId}
|
|
87
89
|
preferredFocus={preferredFocus}
|
|
@@ -94,7 +96,7 @@ export function CellWithFocusable(props: Props) {
|
|
|
94
96
|
<CellRenderer
|
|
95
97
|
testID={"cell-with-focusable-cell-renderer"}
|
|
96
98
|
item={item}
|
|
97
|
-
groupId={
|
|
99
|
+
groupId={addPrefix(id)}
|
|
98
100
|
onToggleFocus={handleToggleFocus}
|
|
99
101
|
state={state}
|
|
100
102
|
prefixId={id}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { View, ViewStyle } from "react-native";
|
|
3
|
+
import { isTvOSPlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
|
+
|
|
5
|
+
const isTvOS = isTvOSPlatform();
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
style: ViewStyle;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const CellWrapper = ({ style, children }: Props) => {
|
|
13
|
+
if (isTvOS) {
|
|
14
|
+
return <View style={style}>{children}</View>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return <>{children}</>;
|
|
18
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { findPluginByIdentifier } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
2
|
+
import { isGroup } from "@applicaster/zapp-react-native-utils/componentsUtils";
|
|
2
3
|
|
|
3
4
|
import { componentsLogger } from "../../Helpers/logger";
|
|
4
5
|
import defaultCellRenderer from "../default-cell-renderer";
|
|
@@ -80,7 +81,7 @@ export function CellRendererResolver({
|
|
|
80
81
|
}: Props) {
|
|
81
82
|
const cellRendererPlugin = getRendererPlugin(component, plugins, cellStyles);
|
|
82
83
|
|
|
83
|
-
if (!cellRendererPlugin && component
|
|
84
|
+
if (!cellRendererPlugin && !isGroup(component)) {
|
|
84
85
|
logger.warning({
|
|
85
86
|
message: "Could not resolve cell builder plugin",
|
|
86
87
|
data: { component },
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks/usePickFromState";
|
|
3
|
+
import { getBackgroundImageUrl } from "../utils";
|
|
4
|
+
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
5
|
+
|
|
6
|
+
export const LayoutBackground = ({
|
|
7
|
+
Background,
|
|
8
|
+
children,
|
|
9
|
+
}: {
|
|
10
|
+
Background: React.ComponentType<any>;
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
}) => {
|
|
13
|
+
const theme = useTheme();
|
|
14
|
+
|
|
15
|
+
const { remoteConfigurations } = usePickFromState(["remoteConfigurations"]);
|
|
16
|
+
|
|
17
|
+
const backgroundColor = theme.app_background_color;
|
|
18
|
+
const backgroundImageUrl = getBackgroundImageUrl(remoteConfigurations);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Background
|
|
22
|
+
backgroundColor={backgroundColor}
|
|
23
|
+
backgroundImageUrl={backgroundImageUrl}
|
|
24
|
+
>
|
|
25
|
+
{children}
|
|
26
|
+
</Background>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
@@ -2,18 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`Layout TV renders 1`] = `
|
|
4
4
|
<View
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
preferredFocus={true}
|
|
5
|
+
backgroundColor="#000000"
|
|
6
|
+
testID="background-component"
|
|
8
7
|
>
|
|
9
8
|
<View
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
excludeFromFocusSearching={true}
|
|
10
|
+
id="/river/A1234"
|
|
11
|
+
preferredFocus={true}
|
|
12
|
+
>
|
|
13
|
+
<View
|
|
14
|
+
Components={
|
|
15
|
+
{
|
|
16
|
+
"Background": [Function],
|
|
17
|
+
"NavBar": [Function],
|
|
18
|
+
}
|
|
14
19
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
route="/river/A1234"
|
|
21
|
+
/>
|
|
22
|
+
</View>
|
|
18
23
|
</View>
|
|
19
24
|
`;
|
|
@@ -5,6 +5,14 @@ import { render } from "@testing-library/react-native";
|
|
|
5
5
|
import { Provider } from "react-redux";
|
|
6
6
|
import { NavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NavigationContext";
|
|
7
7
|
import configureStore from "redux-mock-store";
|
|
8
|
+
import Layout from "../index.web";
|
|
9
|
+
|
|
10
|
+
// mock useTheme to provide app_background_color
|
|
11
|
+
jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
|
|
12
|
+
useTheme: () => ({
|
|
13
|
+
app_background_color: "#000000",
|
|
14
|
+
}),
|
|
15
|
+
}));
|
|
8
16
|
|
|
9
17
|
const withoutChildren = omit(["children"]);
|
|
10
18
|
|
|
@@ -16,8 +24,6 @@ jest.mock("../../../Screen/TV/index.web", () => {
|
|
|
16
24
|
};
|
|
17
25
|
});
|
|
18
26
|
|
|
19
|
-
const Layout = require("../index.web").default;
|
|
20
|
-
|
|
21
27
|
const mockStore = configureStore()({
|
|
22
28
|
appState: { appReady: true },
|
|
23
29
|
});
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import * as R from "ramda";
|
|
3
2
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
4
3
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
5
|
-
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
6
4
|
|
|
7
|
-
import { getBackgroundImageUrl } from "../utils";
|
|
8
5
|
import { LayoutContainer } from "./LayoutContainer";
|
|
9
6
|
import { ScreenContainer } from "./ScreenContainer";
|
|
10
7
|
|
|
@@ -12,6 +9,7 @@ import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
|
|
|
12
9
|
import { PathnameContext } from "../../../Contexts/PathnameContext";
|
|
13
10
|
import { ScreenDataContext } from "../../../Contexts/ScreenDataContext";
|
|
14
11
|
import { ScreenContextProvider } from "../../../Contexts/ScreenContext";
|
|
12
|
+
import { LayoutBackground } from "./LayoutBackground";
|
|
15
13
|
|
|
16
14
|
type Components = {
|
|
17
15
|
NavBar: React.ComponentType<any>;
|
|
@@ -19,7 +17,6 @@ type Components = {
|
|
|
19
17
|
};
|
|
20
18
|
|
|
21
19
|
type ComponentsExtraProps = {
|
|
22
|
-
Background?: Record<string, any>;
|
|
23
20
|
NavBar?: Record<string, any>;
|
|
24
21
|
};
|
|
25
22
|
|
|
@@ -31,17 +28,10 @@ type Props = {
|
|
|
31
28
|
|
|
32
29
|
const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
33
30
|
const navigator = useNavigation();
|
|
34
|
-
const theme = useTheme();
|
|
35
31
|
|
|
36
|
-
const { appState: { appReady = false } = {}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const backgroundColor = React.useMemo(() => theme.app_background_color, []);
|
|
40
|
-
|
|
41
|
-
const backgroundImageUrl = React.useMemo(
|
|
42
|
-
() => getBackgroundImageUrl(remoteConfigurations),
|
|
43
|
-
[remoteConfigurations]
|
|
44
|
-
);
|
|
32
|
+
const { appState: { appReady = false } = {} } = usePickFromState([
|
|
33
|
+
"appState",
|
|
34
|
+
]);
|
|
45
35
|
|
|
46
36
|
if (!appReady) {
|
|
47
37
|
return null;
|
|
@@ -50,11 +40,7 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
|
50
40
|
return (
|
|
51
41
|
<LayoutContainer>
|
|
52
42
|
<ScreenLayoutContextProvider>
|
|
53
|
-
<Components.Background
|
|
54
|
-
backgroundColor={backgroundColor}
|
|
55
|
-
backgroundImageUrl={backgroundImageUrl}
|
|
56
|
-
{...R.omit(["ref"])(ComponentsExtraProps?.Background)}
|
|
57
|
-
>
|
|
43
|
+
<LayoutBackground Background={Components.Background}>
|
|
58
44
|
<ScreenDataContext.Provider value={navigator.data}>
|
|
59
45
|
<PathnameContext.Provider value={navigator.currentRoute}>
|
|
60
46
|
<ScreenContextProvider pathname={navigator.currentRoute}>
|
|
@@ -67,7 +53,7 @@ const Layout = ({ Components, ComponentsExtraProps, children }: Props) => {
|
|
|
67
53
|
</ScreenContextProvider>
|
|
68
54
|
</PathnameContext.Provider>
|
|
69
55
|
</ScreenDataContext.Provider>
|
|
70
|
-
</
|
|
56
|
+
</LayoutBackground>
|
|
71
57
|
</ScreenLayoutContextProvider>
|
|
72
58
|
</LayoutContainer>
|
|
73
59
|
);
|
|
@@ -5,6 +5,7 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
|
5
5
|
|
|
6
6
|
import { ScreenLayoutContextProvider } from "./ScreenLayoutContextProvider";
|
|
7
7
|
import { StackNavigator } from "../../Navigator";
|
|
8
|
+
import { LayoutBackground } from "./LayoutBackground";
|
|
8
9
|
|
|
9
10
|
type Components = {
|
|
10
11
|
NavBar: React.ComponentType<any>;
|
|
@@ -25,7 +26,9 @@ const Layout = ({ Components }: Props) => {
|
|
|
25
26
|
|
|
26
27
|
return (
|
|
27
28
|
<ScreenLayoutContextProvider>
|
|
28
|
-
<
|
|
29
|
+
<LayoutBackground Background={Components.Background}>
|
|
30
|
+
<StackNavigator Components={Components} />
|
|
31
|
+
</LayoutBackground>
|
|
29
32
|
</ScreenLayoutContextProvider>
|
|
30
33
|
);
|
|
31
34
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { times } from "@applicaster/zapp-react-native-utils/utils";
|
|
2
2
|
import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
3
3
|
|
|
4
4
|
import { Button } from "./Button";
|
|
@@ -9,13 +9,14 @@ import {
|
|
|
9
9
|
} from "./utils";
|
|
10
10
|
|
|
11
11
|
import { compact } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
12
|
+
import { PREFIX, BUTTON_PREFIX } from "./const";
|
|
12
13
|
|
|
13
14
|
export {
|
|
14
15
|
insertButtonsBetweenLabels,
|
|
15
16
|
insertButtonsBetweenLabelContainers,
|
|
16
17
|
} from "./utils";
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
+
const buttonId = (index: number) => `${BUTTON_PREFIX}_${index}`;
|
|
19
20
|
|
|
20
21
|
type Props = {
|
|
21
22
|
value: Function;
|
|
@@ -42,7 +43,6 @@ export const TvActionButtons = ({
|
|
|
42
43
|
return null;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
const prefix1Button = `${PREFIX}_button_1`;
|
|
46
46
|
const independentStyles = value(`${PREFIX}_container_independent_styles`);
|
|
47
47
|
|
|
48
48
|
return {
|
|
@@ -73,11 +73,11 @@ export const TvActionButtons = ({
|
|
|
73
73
|
buttonsCount,
|
|
74
74
|
},
|
|
75
75
|
elements: compact(
|
|
76
|
-
|
|
77
|
-
const prefixSpecificButton =
|
|
76
|
+
times((index) => {
|
|
77
|
+
const prefixSpecificButton = buttonId(index + 1);
|
|
78
78
|
|
|
79
79
|
return Button({
|
|
80
|
-
prefix: independentStyles ? prefixSpecificButton :
|
|
80
|
+
prefix: independentStyles ? prefixSpecificButton : buttonId(1),
|
|
81
81
|
value,
|
|
82
82
|
platformValue,
|
|
83
83
|
pluginIdentifier: getPluginIdentifier(configuration, PREFIX, index),
|
|
@@ -10,13 +10,11 @@ import { Button } from "./Button";
|
|
|
10
10
|
import { ItemIconProps } from "./Button/ItemIcon";
|
|
11
11
|
import { ItemProps } from "./Button/Item";
|
|
12
12
|
import { ItemLabelProps } from "./Button/ItemLabel";
|
|
13
|
-
import {
|
|
14
|
-
defaultItemIconProps,
|
|
15
|
-
defaultItemLabelProps,
|
|
16
|
-
defaultItemProps,
|
|
17
|
-
} from "./utils";
|
|
13
|
+
import { getItemIconProps, getItemLabelProps, getItemProps } from "./utils";
|
|
18
14
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
19
15
|
|
|
16
|
+
import type { PluginConfiguration } from "./";
|
|
17
|
+
|
|
20
18
|
import { ModalHeader } from "./Header";
|
|
21
19
|
|
|
22
20
|
type ModalComponentProps = {
|
|
@@ -30,6 +28,20 @@ type ModalComponentProps = {
|
|
|
30
28
|
maxHeight?: number;
|
|
31
29
|
dismiss: () => void;
|
|
32
30
|
buttonComponent?: React.ComponentType;
|
|
31
|
+
iconProps?: ItemIconProps | ((theme: PluginConfiguration) => ItemIconProps);
|
|
32
|
+
itemProps?:
|
|
33
|
+
| ItemProps
|
|
34
|
+
| ((theme: PluginConfiguration, width: number) => ItemProps);
|
|
35
|
+
labelProps?:
|
|
36
|
+
| ItemLabelProps
|
|
37
|
+
| ((theme: PluginConfiguration, width: number) => ItemLabelProps);
|
|
38
|
+
getSelectedItemIcon: (
|
|
39
|
+
theme: PluginConfiguration
|
|
40
|
+
) => ItemIconProps["asset"] | null;
|
|
41
|
+
getDefaultItemIcon: (
|
|
42
|
+
theme: PluginConfiguration
|
|
43
|
+
) => ItemIconProps["asset"] | null;
|
|
44
|
+
iconPlacement?: "left" | "right";
|
|
33
45
|
};
|
|
34
46
|
|
|
35
47
|
export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
@@ -43,14 +55,20 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
43
55
|
summary,
|
|
44
56
|
title,
|
|
45
57
|
buttonComponent: ButtonComponent = Button,
|
|
58
|
+
getSelectedItemIcon = (theme) =>
|
|
59
|
+
theme.modal_bottom_sheet_item_selected_icon,
|
|
60
|
+
getDefaultItemIcon = () => null,
|
|
61
|
+
iconPlacement,
|
|
46
62
|
} = props;
|
|
47
63
|
|
|
48
64
|
const [headerHeight, setHeaderHeight] = useState(0);
|
|
49
65
|
const route = useRef(currentRoute);
|
|
50
66
|
const theme = useTheme<BaseThemePropertiesMobile>();
|
|
67
|
+
const paddingTop = Number(theme.modal_bottom_sheet_padding_top);
|
|
68
|
+
const paddingBottom = Number(theme.modal_bottom_sheet_padding_bottom);
|
|
51
69
|
|
|
52
70
|
const maxContentHeight = maxHeight
|
|
53
|
-
? maxHeight - headerHeight -
|
|
71
|
+
? maxHeight - headerHeight - paddingTop
|
|
54
72
|
: undefined;
|
|
55
73
|
|
|
56
74
|
const onHeaderLayout = useCallback((event: LayoutChangeEvent) => {
|
|
@@ -64,26 +82,30 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
64
82
|
}, [currentRoute]);
|
|
65
83
|
|
|
66
84
|
const iconBaseProps = useMemo<ItemIconProps>(() => {
|
|
67
|
-
return
|
|
68
|
-
}, [theme]);
|
|
85
|
+
return getItemIconProps(theme, props.iconProps);
|
|
86
|
+
}, [theme, props.iconProps]);
|
|
69
87
|
|
|
70
88
|
const itemBaseProps = useMemo<ItemProps>(() => {
|
|
71
|
-
return
|
|
72
|
-
}, [theme, props.width]);
|
|
89
|
+
return getItemProps(theme, props.width, props.itemProps);
|
|
90
|
+
}, [theme, props.width, props.itemProps]);
|
|
73
91
|
|
|
74
92
|
const labelBaseProps = useMemo<ItemLabelProps>(() => {
|
|
75
|
-
return
|
|
76
|
-
}, [theme, props.width]);
|
|
93
|
+
return getItemLabelProps(theme, props.width, props.labelProps);
|
|
94
|
+
}, [theme, props.width, props.labelProps]);
|
|
77
95
|
|
|
78
|
-
const handlePress = (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
96
|
+
const handlePress = useCallback(
|
|
97
|
+
(item: any) => {
|
|
98
|
+
onPress(item);
|
|
99
|
+
dismiss();
|
|
100
|
+
},
|
|
101
|
+
[onPress, dismiss]
|
|
102
|
+
);
|
|
82
103
|
|
|
83
104
|
return (
|
|
84
105
|
<View
|
|
85
106
|
style={{
|
|
86
|
-
|
|
107
|
+
maxWidth: props.width,
|
|
108
|
+
paddingTop,
|
|
87
109
|
}}
|
|
88
110
|
>
|
|
89
111
|
<ModalHeader
|
|
@@ -98,8 +120,8 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
98
120
|
bounces={false}
|
|
99
121
|
style={{ maxHeight: maxContentHeight }}
|
|
100
122
|
contentContainerStyle={{
|
|
101
|
-
paddingBottom
|
|
102
|
-
paddingTop
|
|
123
|
+
paddingBottom,
|
|
124
|
+
paddingTop,
|
|
103
125
|
}}
|
|
104
126
|
>
|
|
105
127
|
{items.map((item, index) => (
|
|
@@ -110,9 +132,13 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
110
132
|
selectedItem={current_selection}
|
|
111
133
|
item={item}
|
|
112
134
|
onPress={handlePress}
|
|
135
|
+
label={theme[item?.label] ?? item?.label}
|
|
113
136
|
iconBaseProps={iconBaseProps}
|
|
114
137
|
itemBaseProps={itemBaseProps}
|
|
115
138
|
labelBaseProps={labelBaseProps}
|
|
139
|
+
selectedItemIcon={getSelectedItemIcon(theme)}
|
|
140
|
+
defaultItemIcon={getDefaultItemIcon(theme)}
|
|
141
|
+
iconPlacement={iconPlacement}
|
|
116
142
|
/>
|
|
117
143
|
))}
|
|
118
144
|
</ScrollView>
|
|
@@ -5,7 +5,7 @@ export type ItemProps = {
|
|
|
5
5
|
backgroundColor: string;
|
|
6
6
|
focusedBackgroundColor: string;
|
|
7
7
|
selectedBackgroundColor?: string;
|
|
8
|
-
|
|
8
|
+
focusedSelectedBackgroundColor?: string;
|
|
9
9
|
borderRadius: number;
|
|
10
10
|
marginBottom: number;
|
|
11
11
|
marginLeft: number;
|
|
@@ -15,6 +15,7 @@ export type ItemProps = {
|
|
|
15
15
|
paddingBottom: number;
|
|
16
16
|
paddingRight: number;
|
|
17
17
|
paddingLeft: number;
|
|
18
|
+
maxWidth: number;
|
|
18
19
|
focused?: boolean;
|
|
19
20
|
selected?: boolean;
|
|
20
21
|
children?: ReactChild[];
|
|
@@ -33,11 +34,11 @@ function getBackgroundColor({
|
|
|
33
34
|
backgroundColor,
|
|
34
35
|
focusedBackgroundColor,
|
|
35
36
|
selectedBackgroundColor,
|
|
36
|
-
|
|
37
|
+
focusedSelectedBackgroundColor,
|
|
37
38
|
}) {
|
|
38
39
|
switch (true) {
|
|
39
40
|
case selected && focused:
|
|
40
|
-
return
|
|
41
|
+
return focusedSelectedBackgroundColor;
|
|
41
42
|
case selected && !focused:
|
|
42
43
|
return selectedBackgroundColor;
|
|
43
44
|
case !selected && focused:
|
|
@@ -51,7 +52,7 @@ export function Item(props: ItemProps) {
|
|
|
51
52
|
const {
|
|
52
53
|
backgroundColor,
|
|
53
54
|
focusedBackgroundColor,
|
|
54
|
-
|
|
55
|
+
focusedSelectedBackgroundColor,
|
|
55
56
|
selectedBackgroundColor,
|
|
56
57
|
children,
|
|
57
58
|
focused,
|
|
@@ -68,7 +69,7 @@ export function Item(props: ItemProps) {
|
|
|
68
69
|
backgroundColor: getBackgroundColor({
|
|
69
70
|
selected,
|
|
70
71
|
focused,
|
|
71
|
-
|
|
72
|
+
focusedSelectedBackgroundColor,
|
|
72
73
|
focusedBackgroundColor,
|
|
73
74
|
selectedBackgroundColor,
|
|
74
75
|
backgroundColor,
|
|
@@ -3,7 +3,6 @@ import { StyleSheet, TouchableOpacity, View } from "react-native";
|
|
|
3
3
|
import { Item, ItemProps } from "./Item";
|
|
4
4
|
import { ItemIcon, ItemIconProps } from "./ItemIcon";
|
|
5
5
|
import { ItemLabel, ItemLabelProps } from "./ItemLabel";
|
|
6
|
-
import * as assets from "./assets";
|
|
7
6
|
import { defaultSelectedAsset } from "./assets";
|
|
8
7
|
|
|
9
8
|
type ButtonProps = {
|
|
@@ -17,6 +16,9 @@ type ButtonProps = {
|
|
|
17
16
|
labelBaseProps?: ItemLabelProps;
|
|
18
17
|
disabled?: boolean;
|
|
19
18
|
label?: string | Record<string, string>;
|
|
19
|
+
iconPlacement?: "left" | "right";
|
|
20
|
+
selectedItemIcon?: ItemIconProps["asset"];
|
|
21
|
+
defaultItemIcon?: ItemIconProps["asset"];
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
const styles = StyleSheet.create({
|
|
@@ -33,52 +35,32 @@ export function Button({
|
|
|
33
35
|
configuration,
|
|
34
36
|
width,
|
|
35
37
|
iconBaseProps,
|
|
36
|
-
itemBaseProps,
|
|
38
|
+
itemBaseProps: itemProps,
|
|
37
39
|
labelBaseProps,
|
|
38
40
|
label,
|
|
41
|
+
iconPlacement = "left",
|
|
42
|
+
defaultItemIcon,
|
|
43
|
+
selectedItemIcon,
|
|
39
44
|
disabled = false,
|
|
40
45
|
}: ButtonProps) {
|
|
41
46
|
const [focused, setFocused] = useState(false);
|
|
42
47
|
|
|
43
|
-
const selected =
|
|
44
|
-
() => selectedItem && item.value === selectedItem?.value,
|
|
45
|
-
[selectedItem, selectedItem]
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const itemProps = useMemo<ItemProps>(
|
|
49
|
-
() => ({
|
|
50
|
-
...itemBaseProps,
|
|
51
|
-
width,
|
|
52
|
-
}),
|
|
53
|
-
[configuration, width]
|
|
54
|
-
);
|
|
48
|
+
const selected = selectedItem && item.value === selectedItem?.value;
|
|
55
49
|
|
|
56
|
-
const
|
|
57
|
-
() =>
|
|
58
|
-
|
|
59
|
-
asset: configuration[item.asset] ?? assets[item.asset] ?? item.asset,
|
|
60
|
-
}),
|
|
61
|
-
[configuration, item.asset]
|
|
50
|
+
const itemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
|
|
51
|
+
() => configuration[item.asset] ?? item.asset ?? defaultItemIcon,
|
|
52
|
+
[item.asset, defaultItemIcon]
|
|
62
53
|
);
|
|
63
54
|
|
|
64
|
-
const
|
|
65
|
-
() =>
|
|
66
|
-
|
|
67
|
-
asset:
|
|
68
|
-
configuration["modal_bottom_sheet_item_selected_icon"] ||
|
|
69
|
-
defaultSelectedAsset,
|
|
70
|
-
marginRight: 10,
|
|
71
|
-
}),
|
|
72
|
-
[configuration]
|
|
55
|
+
const selectedItemIconPropsAssets = useMemo<ItemIconProps["asset"]>(
|
|
56
|
+
() => selectedItemIcon || defaultSelectedAsset,
|
|
57
|
+
[selectedItemIcon]
|
|
73
58
|
);
|
|
74
59
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
...
|
|
78
|
-
|
|
79
|
-
}),
|
|
80
|
-
[configuration, item?.label]
|
|
81
|
-
);
|
|
60
|
+
const renderItemIcon =
|
|
61
|
+
itemIconPropsAssets && itemIconPropsAssets.length > 0 ? (
|
|
62
|
+
<ItemIcon {...iconBaseProps} asset={itemIconPropsAssets} />
|
|
63
|
+
) : null;
|
|
82
64
|
|
|
83
65
|
if (disabled) return null;
|
|
84
66
|
|
|
@@ -92,18 +74,23 @@ export function Button({
|
|
|
92
74
|
>
|
|
93
75
|
<Item {...itemProps} focused={focused} selected={selected}>
|
|
94
76
|
<View style={styles.label_icon_container}>
|
|
95
|
-
{
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
{itemLabelProps.label ? (
|
|
77
|
+
{iconPlacement === "left" && renderItemIcon}
|
|
78
|
+
|
|
79
|
+
{label ? (
|
|
99
80
|
<ItemLabel
|
|
100
|
-
{...
|
|
81
|
+
{...labelBaseProps}
|
|
82
|
+
label={label ?? null}
|
|
101
83
|
focused={focused}
|
|
102
84
|
selected={selected}
|
|
103
85
|
/>
|
|
104
86
|
) : null}
|
|
105
87
|
</View>
|
|
106
|
-
|
|
88
|
+
|
|
89
|
+
{selected ? (
|
|
90
|
+
<ItemIcon {...iconBaseProps} asset={selectedItemIconPropsAssets} />
|
|
91
|
+
) : (
|
|
92
|
+
iconPlacement === "right" && renderItemIcon
|
|
93
|
+
)}
|
|
107
94
|
</Item>
|
|
108
95
|
</TouchableOpacity>
|
|
109
96
|
</View>
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
2
|
-
import { PluginConfiguration } from "./
|
|
2
|
+
import { PluginConfiguration } from "./";
|
|
3
|
+
import { ItemIconProps } from "./Button/ItemIcon";
|
|
4
|
+
import { ItemLabelProps } from "./Button/ItemLabel";
|
|
5
|
+
import { ItemProps } from "./Button/Item";
|
|
3
6
|
|
|
4
7
|
export function defaultItemProps(
|
|
5
8
|
config: PluginConfiguration,
|
|
6
9
|
maxWidth: number
|
|
7
|
-
) {
|
|
10
|
+
): ItemProps {
|
|
8
11
|
const {
|
|
9
12
|
modal_bottom_sheet_item_background_color,
|
|
10
13
|
modal_bottom_sheet_item_focus_background_color,
|
|
11
14
|
modal_bottom_sheet_item_selected_background_color,
|
|
12
|
-
|
|
15
|
+
modal_bottom_sheet_item_focused_selected_background_color,
|
|
13
16
|
modal_bottom_sheet_item_corner_radius,
|
|
14
17
|
modal_bottom_sheet_item_margin_bottom,
|
|
15
18
|
modal_bottom_sheet_item_margin_left,
|
|
@@ -25,8 +28,8 @@ export function defaultItemProps(
|
|
|
25
28
|
backgroundColor: modal_bottom_sheet_item_background_color,
|
|
26
29
|
focusedBackgroundColor: modal_bottom_sheet_item_focus_background_color,
|
|
27
30
|
selectedBackgroundColor: modal_bottom_sheet_item_selected_background_color,
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
focusedSelectedBackgroundColor:
|
|
32
|
+
modal_bottom_sheet_item_focused_selected_background_color,
|
|
30
33
|
borderRadius: modal_bottom_sheet_item_corner_radius,
|
|
31
34
|
marginBottom: modal_bottom_sheet_item_margin_bottom,
|
|
32
35
|
marginTop: modal_bottom_sheet_item_margin_top,
|
|
@@ -43,7 +46,7 @@ export function defaultItemProps(
|
|
|
43
46
|
export function defaultItemLabelProps(
|
|
44
47
|
config: PluginConfiguration,
|
|
45
48
|
sheetWidth: number
|
|
46
|
-
) {
|
|
49
|
+
): ItemLabelProps {
|
|
47
50
|
const {
|
|
48
51
|
modal_bottom_sheet_item_label_android_letter_spacing,
|
|
49
52
|
modal_bottom_sheet_item_label_ios_letter_spacing,
|
|
@@ -103,7 +106,9 @@ export function defaultItemLabelProps(
|
|
|
103
106
|
};
|
|
104
107
|
}
|
|
105
108
|
|
|
106
|
-
export function defaultItemIconProps(
|
|
109
|
+
export function defaultItemIconProps(
|
|
110
|
+
config: PluginConfiguration
|
|
111
|
+
): ItemIconProps {
|
|
107
112
|
const {
|
|
108
113
|
modal_bottom_sheet_item_icon_height,
|
|
109
114
|
modal_bottom_sheet_item_icon_width,
|
|
@@ -124,3 +129,46 @@ export function defaultItemIconProps(config: PluginConfiguration) {
|
|
|
124
129
|
marginRight: modal_bottom_sheet_item_icon_margin_right,
|
|
125
130
|
};
|
|
126
131
|
}
|
|
132
|
+
|
|
133
|
+
export function getItemIconProps(
|
|
134
|
+
theme: PluginConfiguration,
|
|
135
|
+
iconProps?: ((theme: PluginConfiguration) => ItemIconProps) | ItemIconProps
|
|
136
|
+
) {
|
|
137
|
+
if (iconProps) {
|
|
138
|
+
return typeof iconProps === "function" ? iconProps(theme) : iconProps;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return defaultItemIconProps(theme);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function getItemLabelProps(
|
|
145
|
+
theme: PluginConfiguration,
|
|
146
|
+
width: number,
|
|
147
|
+
labelProps?:
|
|
148
|
+
| ((theme: PluginConfiguration, width: number) => ItemLabelProps)
|
|
149
|
+
| ItemLabelProps
|
|
150
|
+
) {
|
|
151
|
+
if (labelProps) {
|
|
152
|
+
return typeof labelProps === "function"
|
|
153
|
+
? labelProps(theme, width)
|
|
154
|
+
: labelProps;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return defaultItemLabelProps(theme, width);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function getItemProps(
|
|
161
|
+
theme: PluginConfiguration,
|
|
162
|
+
width: number,
|
|
163
|
+
itemProps?:
|
|
164
|
+
| ((theme: PluginConfiguration, width: number) => ItemProps)
|
|
165
|
+
| ItemProps
|
|
166
|
+
) {
|
|
167
|
+
if (itemProps) {
|
|
168
|
+
return typeof itemProps === "function"
|
|
169
|
+
? itemProps(theme, width)
|
|
170
|
+
: itemProps;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return defaultItemProps(theme, width);
|
|
174
|
+
}
|
|
@@ -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: {
|
|
@@ -648,7 +663,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
648
663
|
style={[
|
|
649
664
|
styles.playerWrapper,
|
|
650
665
|
// eslint-disable-next-line react-native/no-inline-styles, react-native/no-color-literals
|
|
651
|
-
|
|
666
|
+
withBorderHack(),
|
|
652
667
|
]}
|
|
653
668
|
testID={"player-wrapper"}
|
|
654
669
|
>
|
|
@@ -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
|
|
|
@@ -112,7 +113,7 @@ function RiverItemComponent(props: RiverItemType) {
|
|
|
112
113
|
jsOnly: true,
|
|
113
114
|
});
|
|
114
115
|
|
|
115
|
-
if (!CellRenderer && item
|
|
116
|
+
if (!CellRenderer && !isGroup(item)) {
|
|
116
117
|
riverLogger.warning({
|
|
117
118
|
message: "Cell Renderer is null - will fallback to default cell",
|
|
118
119
|
data: { item, CellRenderer },
|
|
@@ -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;
|
|
@@ -97,14 +100,16 @@ export const AnimationView = ({
|
|
|
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
|
+
inlineAudioPlayer,
|
|
111
|
+
tabletLandscapePlayerTopPosition,
|
|
112
|
+
});
|
|
108
113
|
|
|
109
114
|
const moveComponentHorizontalValue = additionalData.moveValue
|
|
110
115
|
? isRTL
|
|
@@ -119,7 +124,10 @@ export const AnimationView = ({
|
|
|
119
124
|
(animationType, state) => {
|
|
120
125
|
const defaultConfig = {
|
|
121
126
|
toValue: 0,
|
|
122
|
-
duration:
|
|
127
|
+
duration:
|
|
128
|
+
state === PlayerAnimationStateEnum.minimize
|
|
129
|
+
? DURATION_TO_MINIMIZE
|
|
130
|
+
: DEFAULT_DURATION_FOR_ANIMATION,
|
|
123
131
|
useNativeDriver: true,
|
|
124
132
|
};
|
|
125
133
|
|
|
@@ -440,6 +448,10 @@ export const AnimationComponent = (props: Props) => {
|
|
|
440
448
|
videoModalState: { visible },
|
|
441
449
|
} = useNavigation();
|
|
442
450
|
|
|
451
|
+
if (additionalData?.disableAnimatedComponent) {
|
|
452
|
+
return <>{props.children}</>;
|
|
453
|
+
}
|
|
454
|
+
|
|
443
455
|
const useAnimation =
|
|
444
456
|
visible && !additionalData.disableAnimatedComponent && !isTV();
|
|
445
457
|
|
|
@@ -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 {
|
|
@@ -95,6 +95,13 @@ const Provider = ({ children }: { children: React.ReactNode }) => {
|
|
|
95
95
|
setStartComponentsAnimation(false);
|
|
96
96
|
}, []);
|
|
97
97
|
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
// Reset player animation state when video modal is closed
|
|
100
|
+
if (!visible) {
|
|
101
|
+
resetPlayerAnimationState();
|
|
102
|
+
}
|
|
103
|
+
}, [visible, resetPlayerAnimationState]);
|
|
104
|
+
|
|
98
105
|
// Animated values
|
|
99
106
|
const lastScrollY = React.useRef(new Animated.Value(0)).current;
|
|
100
107
|
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,38 @@ 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
|
+
inlineAudioPlayer,
|
|
313
|
+
tabletLandscapePlayerTopPosition,
|
|
314
|
+
}) => {
|
|
315
|
+
if (additionalData.saveArea) {
|
|
316
|
+
return -insets.top + (isAudioItem ? 0 : progressBarHeight);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (isAudioItem) {
|
|
320
|
+
// for any layouts in audioPlayer
|
|
321
|
+
return -1 * toNumberWithDefaultZero(additionalData?.marginTop);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (isTablet) {
|
|
325
|
+
if (
|
|
326
|
+
isTabletLandscape &&
|
|
327
|
+
(!isAudioItem || (isAudioItem && inlineAudioPlayer))
|
|
328
|
+
) {
|
|
329
|
+
return -tabletLandscapePlayerTopPosition + progressBarHeight;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// for audioPlayer(tablet/isTabletPortrait) in docked mode
|
|
333
|
+
return -130;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// for audioPlayer(mobile) in docked mode
|
|
337
|
+
return -50 + progressBarHeight;
|
|
338
|
+
};
|
|
@@ -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
|
|
|
@@ -22,9 +23,9 @@ type Props = {
|
|
|
22
23
|
entry: ZappEntry;
|
|
23
24
|
style: StyleProp<ViewStyle>;
|
|
24
25
|
configuration: Configuration;
|
|
25
|
-
isTabletLandscape
|
|
26
|
+
isTabletLandscape?: boolean;
|
|
26
27
|
isAudioPlayer?: boolean;
|
|
27
|
-
isTablet
|
|
28
|
+
isTablet?: boolean;
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
const containerStyle = ({
|
|
@@ -39,9 +40,9 @@ export const PlayerDetails = ({
|
|
|
39
40
|
entry,
|
|
40
41
|
style,
|
|
41
42
|
configuration,
|
|
42
|
-
isTabletLandscape,
|
|
43
|
+
isTabletLandscape = false,
|
|
43
44
|
isAudioPlayer,
|
|
44
|
-
isTablet,
|
|
45
|
+
isTablet = false,
|
|
45
46
|
}: Props) => {
|
|
46
47
|
const screenData = useTargetScreenData(entry);
|
|
47
48
|
const insets = useSafeAreaInsets();
|
|
@@ -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={[
|
|
@@ -1,43 +1,5 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
-
exports[`PlayerDetails renders properly 1`] = `
|
|
4
|
-
<View
|
|
5
|
-
collapsable={false}
|
|
6
|
-
style={
|
|
7
|
-
{
|
|
8
|
-
"backgroundColor": "transparent",
|
|
9
|
-
"flex": 1,
|
|
10
|
-
"marginTop": -8,
|
|
11
|
-
"paddingTop": -8,
|
|
12
|
-
"width": 750,
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
>
|
|
16
|
-
<View
|
|
17
|
-
feed="test-source"
|
|
18
|
-
riverComponents={[]}
|
|
19
|
-
riverId="test-id"
|
|
20
|
-
/>
|
|
21
|
-
</View>
|
|
22
|
-
`;
|
|
3
|
+
exports[`PlayerDetails renders properly 1`] = `null`;
|
|
23
4
|
|
|
24
|
-
exports[`PlayerDetails renders properly on tablet in landscape orientation 1`] = `
|
|
25
|
-
<View
|
|
26
|
-
collapsable={false}
|
|
27
|
-
style={
|
|
28
|
-
{
|
|
29
|
-
"backgroundColor": "transparent",
|
|
30
|
-
"flex": 1,
|
|
31
|
-
"marginTop": -20,
|
|
32
|
-
"paddingTop": 40,
|
|
33
|
-
"width": 750,
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
>
|
|
37
|
-
<View
|
|
38
|
-
feed="test-source"
|
|
39
|
-
riverComponents={[]}
|
|
40
|
-
riverId="test-id"
|
|
41
|
-
/>
|
|
42
|
-
</View>
|
|
43
|
-
`;
|
|
5
|
+
exports[`PlayerDetails renders properly on tablet in landscape orientation 1`] = `null`;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { mergeRight } from "ramda";
|
|
3
2
|
import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
4
3
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
5
4
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
|
|
@@ -25,10 +24,10 @@ export const useConfiguration = () => {
|
|
|
25
24
|
|
|
26
25
|
const playerPluginConfig = playerManager.getPluginConfiguration();
|
|
27
26
|
|
|
28
|
-
const config =
|
|
27
|
+
const config = mergeRight(playerPluginConfig, {
|
|
28
|
+
...pluginConfiguration,
|
|
29
29
|
...targetScreenConfiguration?.general,
|
|
30
30
|
...targetScreenConfiguration?.styles,
|
|
31
|
-
...pluginConfiguration,
|
|
32
31
|
});
|
|
33
32
|
|
|
34
33
|
const {
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
|
|
9
9
|
import { Placeholder } from "./Placeholder";
|
|
10
10
|
import { useInitialLoading } from "./hooks";
|
|
11
|
-
import { useIsFocusable } from "@applicaster/zapp-react-native-utils/focusManager";
|
|
12
11
|
|
|
13
12
|
type ReactComponent = React.ComponentType<any>;
|
|
14
13
|
|
|
@@ -138,12 +137,13 @@ New signature: {Component, ErrorComponent, LoadingComponent, options}`
|
|
|
138
137
|
);
|
|
139
138
|
|
|
140
139
|
const componentProps = React.useMemo(
|
|
141
|
-
() => ({
|
|
140
|
+
() => ({
|
|
141
|
+
...props,
|
|
142
|
+
parent,
|
|
143
|
+
}),
|
|
142
144
|
[props, parent]
|
|
143
145
|
);
|
|
144
146
|
|
|
145
|
-
useIsFocusable(componentProps);
|
|
146
|
-
|
|
147
147
|
React.useEffect(() => {
|
|
148
148
|
if (!skipOnLoadFinished && !isLoading) {
|
|
149
149
|
onLoadFinished();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-ui-components",
|
|
3
|
-
"version": "13.0.0-alpha.
|
|
3
|
+
"version": "13.0.0-alpha.7620873141",
|
|
4
4
|
"description": "Applicaster Zapp React Native ui components for the Quick Brick App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"redux-mock-store": "^1.5.3"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@applicaster/applicaster-types": "13.0.0-alpha.
|
|
35
|
-
"@applicaster/zapp-react-native-bridge": "13.0.0-alpha.
|
|
36
|
-
"@applicaster/zapp-react-native-redux": "13.0.0-alpha.
|
|
37
|
-
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.
|
|
34
|
+
"@applicaster/applicaster-types": "13.0.0-alpha.7620873141",
|
|
35
|
+
"@applicaster/zapp-react-native-bridge": "13.0.0-alpha.7620873141",
|
|
36
|
+
"@applicaster/zapp-react-native-redux": "13.0.0-alpha.7620873141",
|
|
37
|
+
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.7620873141",
|
|
38
38
|
"promise": "^8.3.0",
|
|
39
39
|
"react-router-native": "^5.1.2",
|
|
40
40
|
"url": "^0.11.0",
|