@applicaster/zapp-react-native-ui-components 13.0.0-alpha.2957047383 → 13.0.0-alpha.3013095924
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/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/ModalComponent/BottomSheetModalContent.tsx +9 -27
- package/Components/ModalComponent/Button/index.tsx +25 -29
- package/Components/ModalComponent/Header/index.tsx +9 -8
- package/Components/PlayerContainer/PlayerContainer.tsx +2 -1
- package/Components/River/RiverItem.tsx +2 -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 +1 -1
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +1 -2
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +8 -1
- package/Components/VideoModal/ModalAnimation/utils.ts +3 -9
- 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/package.json +5 -5
|
@@ -22,8 +22,6 @@ type Props = {
|
|
|
22
22
|
audio_player_title_color?: string;
|
|
23
23
|
audio_player_summary_color?: string;
|
|
24
24
|
audio_player_rtl?: boolean;
|
|
25
|
-
magic_background?: boolean;
|
|
26
|
-
audio_player_background_image_query?: string;
|
|
27
25
|
audio_player_background_image_default_color?: string;
|
|
28
26
|
start_time?: string;
|
|
29
27
|
end_time?: string;
|
|
@@ -34,8 +32,6 @@ type Props = {
|
|
|
34
32
|
audio_player_title_color?: string;
|
|
35
33
|
audio_player_summary_color?: string;
|
|
36
34
|
audio_player_rtl?: string;
|
|
37
|
-
magic_background?: string;
|
|
38
|
-
audio_player_background_image_query?: string;
|
|
39
35
|
audio_player_background_image_default_color?: string;
|
|
40
36
|
audio_player_background_image?: string;
|
|
41
37
|
audio_player_artwork_aspect_ratio?: string;
|
|
@@ -76,11 +72,6 @@ export function AudioPlayer(props: Props) {
|
|
|
76
72
|
const artworkAspectRatio = getProp("audio_player_artwork_aspect_ratio");
|
|
77
73
|
const channelIcon = getProp("audio_player_channel_icon");
|
|
78
74
|
const rtlFlag = getProp("audio_player_rtl");
|
|
79
|
-
const magicBackground = getProp("magic_background");
|
|
80
|
-
|
|
81
|
-
const audioPlayerBackgroundImageQuery = getProp(
|
|
82
|
-
"audio_player_background_image_query"
|
|
83
|
-
);
|
|
84
75
|
|
|
85
76
|
const audioPlayerBackgroundImageDefaultColor = getProp(
|
|
86
77
|
"audio_player_background_image_default_color"
|
|
@@ -162,8 +153,6 @@ export function AudioPlayer(props: Props) {
|
|
|
162
153
|
runTimeFontSize,
|
|
163
154
|
artworkAspectRatio,
|
|
164
155
|
channelIcon,
|
|
165
|
-
magicBackground,
|
|
166
|
-
audioPlayerBackgroundImageQuery,
|
|
167
156
|
audioPlayerBackgroundImageDefaultColor,
|
|
168
157
|
};
|
|
169
158
|
}, [getProp]);
|
|
@@ -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 },
|
|
@@ -11,6 +11,7 @@ import { allSettled } from "promise";
|
|
|
11
11
|
import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
|
|
12
12
|
import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
|
|
13
13
|
import { ScreenTrackedViewPositionsContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenTrackedViewPositionsContext";
|
|
14
|
+
import { useEventAlerts } from "./utils/useEventAlerts";
|
|
14
15
|
|
|
15
16
|
const { log_info } = createLogger({
|
|
16
17
|
category: "ScreenContainer",
|
|
@@ -103,6 +104,8 @@ export const GeneralContentScreen = ({
|
|
|
103
104
|
[typeof cellTapAction === "function" ? cellTapAction : onCellTapAction]
|
|
104
105
|
);
|
|
105
106
|
|
|
107
|
+
useEventAlerts(screenData);
|
|
108
|
+
|
|
106
109
|
if (!isReady || isNilOrEmpty(components || uiComponents)) return null;
|
|
107
110
|
|
|
108
111
|
return (
|
|
@@ -3,8 +3,10 @@ import { all, equals, path, prop, isEmpty, pluck, values } from "ramda";
|
|
|
3
3
|
import { useEffect, useMemo } from "react";
|
|
4
4
|
import { useDispatch } from "react-redux";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
useLayoutPresets,
|
|
8
|
+
useZappPipesFeeds,
|
|
9
|
+
} from "@applicaster/zapp-react-native-redux/hooks";
|
|
8
10
|
import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
|
|
9
11
|
import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";
|
|
10
12
|
import { Categories } from "./logger";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { showAlertDialog } from "@applicaster/zapp-react-native-utils/alertUtils";
|
|
3
|
+
import { TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT } from "@applicaster/zapp-react-native-utils/actionsExecutor/consts";
|
|
4
|
+
import { useLocalizedStrings } from "@applicaster/zapp-react-native-utils/localizationUtils";
|
|
5
|
+
import { useIsScreenActive } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
6
|
+
import { useSubscriberFor } from "@applicaster/zapp-react-native-utils/reactHooks/useSubscriberFor";
|
|
7
|
+
|
|
8
|
+
export const useEventAlerts = (screenData: ZappRiver) => {
|
|
9
|
+
const localizations = useLocalizedStrings({
|
|
10
|
+
localizations: screenData?.localizations || {},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const isActive = useIsScreenActive();
|
|
14
|
+
|
|
15
|
+
const onMaxTagsReached = React.useCallback(() => {
|
|
16
|
+
// We can't skip subscribe hook call, so we have to check.
|
|
17
|
+
if (!isActive || !localizations?.msg_maximum_selection_reached_message) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
showAlertDialog({
|
|
22
|
+
title: "",
|
|
23
|
+
message: localizations.msg_maximum_selection_reached_message,
|
|
24
|
+
okButtonText:
|
|
25
|
+
localizations.msg_maximum_selection_reached_message_ok_button || "OK",
|
|
26
|
+
});
|
|
27
|
+
}, [localizations, isActive]);
|
|
28
|
+
|
|
29
|
+
useSubscriberFor(TOGGLE_FLAG_MAX_ITEMS_REACHED_EVENT, onMaxTagsReached);
|
|
30
|
+
};
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
|
|
3
|
-
useEffect,
|
|
4
|
-
useMemo,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
} from "react";
|
|
8
|
-
import { View, LayoutChangeEvent, ScrollView } from "react-native";
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
|
+
import { View, ScrollView, Platform } from "react-native";
|
|
9
3
|
import { Button } from "./Button";
|
|
10
4
|
import { ItemIconProps } from "./Button/ItemIcon";
|
|
11
5
|
import { ItemProps } from "./Button/Item";
|
|
@@ -16,6 +10,7 @@ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
|
16
10
|
import type { PluginConfiguration } from "./";
|
|
17
11
|
|
|
18
12
|
import { ModalHeader } from "./Header";
|
|
13
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
19
14
|
|
|
20
15
|
type ModalComponentProps = {
|
|
21
16
|
items: any[];
|
|
@@ -48,7 +43,6 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
48
43
|
const {
|
|
49
44
|
items,
|
|
50
45
|
currentRoute,
|
|
51
|
-
maxHeight,
|
|
52
46
|
current_selection = null,
|
|
53
47
|
onPress,
|
|
54
48
|
dismiss,
|
|
@@ -61,20 +55,11 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
61
55
|
iconPlacement,
|
|
62
56
|
} = props;
|
|
63
57
|
|
|
64
|
-
const [headerHeight, setHeaderHeight] = useState(0);
|
|
65
58
|
const route = useRef(currentRoute);
|
|
66
59
|
const theme = useTheme<BaseThemePropertiesMobile>();
|
|
67
60
|
const paddingTop = Number(theme.modal_bottom_sheet_padding_top);
|
|
68
61
|
const paddingBottom = Number(theme.modal_bottom_sheet_padding_bottom);
|
|
69
62
|
|
|
70
|
-
const maxContentHeight = maxHeight
|
|
71
|
-
? maxHeight - headerHeight - paddingTop
|
|
72
|
-
: undefined;
|
|
73
|
-
|
|
74
|
-
const onHeaderLayout = useCallback((event: LayoutChangeEvent) => {
|
|
75
|
-
setHeaderHeight(event.nativeEvent.layout.height);
|
|
76
|
-
}, []);
|
|
77
|
-
|
|
78
63
|
useEffect(() => {
|
|
79
64
|
if (currentRoute !== route.current) {
|
|
80
65
|
props.dismiss();
|
|
@@ -101,33 +86,30 @@ export function BottomSheetModalContent(props: ModalComponentProps) {
|
|
|
101
86
|
[onPress, dismiss]
|
|
102
87
|
);
|
|
103
88
|
|
|
89
|
+
const bottomInset = useSafeAreaInsets().bottom;
|
|
90
|
+
|
|
104
91
|
return (
|
|
105
92
|
<View
|
|
106
93
|
style={{
|
|
107
|
-
|
|
108
|
-
paddingTop,
|
|
94
|
+
maxHeight: props.maxHeight,
|
|
95
|
+
paddingTop: paddingTop,
|
|
109
96
|
}}
|
|
110
97
|
>
|
|
111
98
|
<ModalHeader
|
|
112
|
-
width={props.width}
|
|
113
99
|
dismiss={dismiss}
|
|
114
100
|
configuration={theme}
|
|
115
|
-
onLayout={onHeaderLayout}
|
|
116
101
|
summary={summary}
|
|
117
102
|
title={title}
|
|
118
103
|
/>
|
|
119
104
|
<ScrollView
|
|
120
|
-
bounces={false}
|
|
121
|
-
style={{ maxHeight: maxContentHeight }}
|
|
122
105
|
contentContainerStyle={{
|
|
123
|
-
paddingBottom
|
|
124
|
-
|
|
106
|
+
paddingBottom:
|
|
107
|
+
paddingBottom + (Platform.OS === "ios" ? bottomInset : 0),
|
|
125
108
|
}}
|
|
126
109
|
>
|
|
127
110
|
{items.map((item, index) => (
|
|
128
111
|
<ButtonComponent
|
|
129
112
|
key={index}
|
|
130
|
-
width={props.width}
|
|
131
113
|
configuration={theme}
|
|
132
114
|
selectedItem={current_selection}
|
|
133
115
|
item={item}
|
|
@@ -7,7 +7,6 @@ import { defaultSelectedAsset } from "./assets";
|
|
|
7
7
|
|
|
8
8
|
type ButtonProps = {
|
|
9
9
|
configuration: any;
|
|
10
|
-
width: number;
|
|
11
10
|
selectedItem?: any;
|
|
12
11
|
item: any; // Adjust type as needed
|
|
13
12
|
onPress: (item: any) => void; // Adjust type as needed
|
|
@@ -33,7 +32,6 @@ export function Button({
|
|
|
33
32
|
item,
|
|
34
33
|
onPress,
|
|
35
34
|
configuration,
|
|
36
|
-
width,
|
|
37
35
|
iconBaseProps,
|
|
38
36
|
itemBaseProps: itemProps,
|
|
39
37
|
labelBaseProps,
|
|
@@ -65,34 +63,32 @@ export function Button({
|
|
|
65
63
|
if (disabled) return null;
|
|
66
64
|
|
|
67
65
|
return (
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
>
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
{iconPlacement === "left" && renderItemIcon}
|
|
66
|
+
<TouchableOpacity
|
|
67
|
+
activeOpacity={1}
|
|
68
|
+
onPress={() => onPress(item)}
|
|
69
|
+
onPressIn={() => setFocused(true)}
|
|
70
|
+
onPressOut={() => setFocused(false)}
|
|
71
|
+
>
|
|
72
|
+
<Item {...itemProps} focused={focused} selected={selected}>
|
|
73
|
+
<View style={styles.label_icon_container}>
|
|
74
|
+
{iconPlacement === "left" && renderItemIcon}
|
|
78
75
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
76
|
+
{label ? (
|
|
77
|
+
<ItemLabel
|
|
78
|
+
{...labelBaseProps}
|
|
79
|
+
label={label ?? null}
|
|
80
|
+
focused={focused}
|
|
81
|
+
selected={selected}
|
|
82
|
+
/>
|
|
83
|
+
) : null}
|
|
84
|
+
</View>
|
|
88
85
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
</View>
|
|
86
|
+
{selected ? (
|
|
87
|
+
<ItemIcon {...iconBaseProps} asset={selectedItemIconPropsAssets} />
|
|
88
|
+
) : (
|
|
89
|
+
iconPlacement === "right" && renderItemIcon
|
|
90
|
+
)}
|
|
91
|
+
</Item>
|
|
92
|
+
</TouchableOpacity>
|
|
97
93
|
);
|
|
98
94
|
}
|
|
@@ -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>
|
|
@@ -597,7 +597,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
597
597
|
);
|
|
598
598
|
}
|
|
599
599
|
|
|
600
|
-
if (screen_background_color) {
|
|
600
|
+
if (screen_background_color && mode !== VideoModalMode.FULLSCREEN) {
|
|
601
601
|
updatedStyles.playerScreen.backgroundColor = screen_background_color;
|
|
602
602
|
}
|
|
603
603
|
|
|
@@ -615,6 +615,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
615
615
|
tv_component_container_height,
|
|
616
616
|
screen_background_color,
|
|
617
617
|
isInlineTV,
|
|
618
|
+
mode,
|
|
618
619
|
]);
|
|
619
620
|
|
|
620
621
|
const applePlayerProps = {
|
|
@@ -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 },
|
|
@@ -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
|
|
|
@@ -144,7 +144,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
|
|
|
144
144
|
|
|
145
145
|
setLastSnap(destSnapPoint);
|
|
146
146
|
|
|
147
|
-
if (destSnapPoint === modalSnapPoints[0]
|
|
147
|
+
if (destSnapPoint === modalSnapPoints[0]) {
|
|
148
148
|
translateYOffset.extractOffset();
|
|
149
149
|
translateYOffset.setValue(preparedTranslationY);
|
|
150
150
|
translateYOffset.flattenOffset();
|
|
@@ -94,7 +94,7 @@ export const AnimationView = ({
|
|
|
94
94
|
const isAudioItem = React.useMemo(
|
|
95
95
|
() =>
|
|
96
96
|
videoModalItem?.content?.type?.includes?.("audio") ||
|
|
97
|
-
videoModalItem?.type?.value
|
|
97
|
+
videoModalItem?.type?.value?.includes?.("audio"),
|
|
98
98
|
[videoModalItem]
|
|
99
99
|
);
|
|
100
100
|
|
|
@@ -107,7 +107,6 @@ export const AnimationView = ({
|
|
|
107
107
|
progressBarHeight,
|
|
108
108
|
isTablet,
|
|
109
109
|
isTabletLandscape,
|
|
110
|
-
inlineAudioPlayer,
|
|
111
110
|
tabletLandscapePlayerTopPosition,
|
|
112
111
|
});
|
|
113
112
|
|
|
@@ -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;
|
|
@@ -309,7 +309,6 @@ export const getMoveUpValue = ({
|
|
|
309
309
|
progressBarHeight,
|
|
310
310
|
isTablet,
|
|
311
311
|
isTabletLandscape,
|
|
312
|
-
inlineAudioPlayer,
|
|
313
312
|
tabletLandscapePlayerTopPosition,
|
|
314
313
|
}) => {
|
|
315
314
|
if (additionalData.saveArea) {
|
|
@@ -322,17 +321,12 @@ export const getMoveUpValue = ({
|
|
|
322
321
|
}
|
|
323
322
|
|
|
324
323
|
if (isTablet) {
|
|
325
|
-
if (
|
|
326
|
-
isTabletLandscape &&
|
|
327
|
-
(!isAudioItem || (isAudioItem && inlineAudioPlayer))
|
|
328
|
-
) {
|
|
324
|
+
if (isTabletLandscape) {
|
|
329
325
|
return -tabletLandscapePlayerTopPosition + progressBarHeight;
|
|
326
|
+
} else {
|
|
327
|
+
return -130;
|
|
330
328
|
}
|
|
331
|
-
|
|
332
|
-
// for audioPlayer(tablet/isTabletPortrait) in docked mode
|
|
333
|
-
return -130;
|
|
334
329
|
}
|
|
335
330
|
|
|
336
|
-
// for audioPlayer(mobile) in docked mode
|
|
337
331
|
return -50 + progressBarHeight;
|
|
338
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={[
|
|
@@ -74,20 +74,6 @@ const getScreenAspectRatio = () => {
|
|
|
74
74
|
return longEdge / shortEdge;
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
-
const safeAreaStyles = (
|
|
78
|
-
configuration: Configuration,
|
|
79
|
-
isTablet: boolean
|
|
80
|
-
): ViewStyle => {
|
|
81
|
-
const tablet_landscape_player_container_background_color =
|
|
82
|
-
configuration?.tablet_landscape_player_container_background_color;
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
backgroundColor: isTablet
|
|
86
|
-
? tablet_landscape_player_container_background_color
|
|
87
|
-
: "transparent",
|
|
88
|
-
};
|
|
89
|
-
};
|
|
90
|
-
|
|
91
77
|
const getEdges = (isTablet: boolean, isInlineModal: boolean) => {
|
|
92
78
|
if (isTablet) {
|
|
93
79
|
return ["top"];
|
|
@@ -156,6 +142,7 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
156
142
|
children,
|
|
157
143
|
isTabletPortrait,
|
|
158
144
|
configuration,
|
|
145
|
+
fullscreen,
|
|
159
146
|
pip,
|
|
160
147
|
} = props;
|
|
161
148
|
|
|
@@ -211,14 +198,17 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
211
198
|
[containerDimensions, playerDimensionsHack]
|
|
212
199
|
);
|
|
213
200
|
|
|
201
|
+
const wrapperViewStyle: ViewStyle = {
|
|
202
|
+
backgroundColor:
|
|
203
|
+
isTablet && !fullscreen
|
|
204
|
+
? configuration?.tablet_landscape_player_container_background_color
|
|
205
|
+
: "transparent",
|
|
206
|
+
};
|
|
207
|
+
|
|
214
208
|
return (
|
|
215
209
|
<WrapperView
|
|
216
210
|
edges={getEdges(isTablet, isInlineModal) as readonly Edge[]}
|
|
217
|
-
style={[
|
|
218
|
-
safeAreaStyles(configuration, isTablet),
|
|
219
|
-
style,
|
|
220
|
-
playerDimensionsHack,
|
|
221
|
-
]}
|
|
211
|
+
style={[wrapperViewStyle, style, playerDimensionsHack]}
|
|
222
212
|
>
|
|
223
213
|
<AnimationComponent
|
|
224
214
|
animationType={ComponentAnimationType.moveUpComponent}
|
|
@@ -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`;
|
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.3013095924",
|
|
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.3013095924",
|
|
35
|
+
"@applicaster/zapp-react-native-bridge": "13.0.0-alpha.3013095924",
|
|
36
|
+
"@applicaster/zapp-react-native-redux": "13.0.0-alpha.3013095924",
|
|
37
|
+
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.3013095924",
|
|
38
38
|
"promise": "^8.3.0",
|
|
39
39
|
"react-router-native": "^5.1.2",
|
|
40
40
|
"url": "^0.11.0",
|