@applicaster/zapp-react-native-ui-components 13.0.0-alpha.5928753399 → 13.0.0-alpha.5942605655
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/AudioPlayerLayout.tsx +8 -9
- package/Components/AudioPlayer/helpers.tsx +0 -2
- package/Components/Cell/Cell.tsx +3 -13
- package/Components/Cell/CellWithFocusable.tsx +20 -14
- package/Components/Cell/CellWrapper.tsx +18 -0
- package/Components/Cell/styles.ts +17 -0
- package/Components/CellRendererResolver/index.ts +2 -1
- package/Components/ErrorScreen/index.tsx +8 -0
- 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/HandlePlayable/HandlePlayable.tsx +10 -3
- 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/Image/Image.ios.tsx +4 -3
- package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
- 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 +66 -54
- package/Components/ModalComponent/Button/Item.tsx +6 -5
- package/Components/ModalComponent/Button/assets.ts +1 -1
- package/Components/ModalComponent/Button/index.tsx +45 -62
- package/Components/ModalComponent/Header/index.tsx +9 -8
- package/Components/ModalComponent/utils.ts +55 -7
- package/Components/PlayerContainer/PlayerContainer.tsx +46 -41
- package/Components/River/ComponentsMap/ComponentsMap.tsx +7 -3
- package/Components/River/RiverItem.tsx +10 -5
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -1
- package/Components/RouteManager/TestId.tsx +1 -5
- package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +0 -1
- package/Components/RouteManager/__tests__/testId.test.js +0 -4
- 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 +21 -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 +9 -4
- package/Components/VideoModal/PlayerWrapper.tsx +35 -22
- package/Components/VideoModal/VideoModal.tsx +19 -4
- package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +1 -1
- package/Components/VideoModal/utils.ts +3 -4
- package/Components/ZappUIComponent/index.tsx +4 -4
- package/package.json +5 -5
- package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
- package/Components/Cell/CellStyles/Hero/index.js +0 -111
- package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
- package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
- package/Components/Cell/CellStyles/colors.js +0 -40
- package/Components/Cell/CellStyles/index.js +0 -15
|
@@ -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]);
|
|
@@ -32,7 +32,7 @@ export function AudioPlayerLayout({ artwork, config, children, style }: Props) {
|
|
|
32
32
|
|
|
33
33
|
const { isRTL, backgroundColor, backgroundImage } = config;
|
|
34
34
|
|
|
35
|
-
const
|
|
35
|
+
const backgroundImageSource = { uri: backgroundImage };
|
|
36
36
|
|
|
37
37
|
const backgroundColorStyle = backgroundImage
|
|
38
38
|
? "transparent"
|
|
@@ -97,15 +97,14 @@ export function AudioPlayerLayout({ artwork, config, children, style }: Props) {
|
|
|
97
97
|
|
|
98
98
|
const backgroundImgStyles = platformSelect({
|
|
99
99
|
tvos: {
|
|
100
|
-
width:
|
|
101
|
-
height:
|
|
100
|
+
width: "100%",
|
|
101
|
+
height: "100%",
|
|
102
102
|
alignItems: "center",
|
|
103
103
|
justifyContent: "center",
|
|
104
104
|
},
|
|
105
105
|
android_tv: {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
height: 1080,
|
|
106
|
+
width: "100%",
|
|
107
|
+
height: "100%",
|
|
109
108
|
alignItems: "center",
|
|
110
109
|
justifyContent: "center",
|
|
111
110
|
},
|
|
@@ -146,9 +145,9 @@ export function AudioPlayerLayout({ artwork, config, children, style }: Props) {
|
|
|
146
145
|
},
|
|
147
146
|
});
|
|
148
147
|
|
|
149
|
-
const audioPlayerLayoutTV =
|
|
148
|
+
const audioPlayerLayoutTV = backgroundImageSource?.uri ? (
|
|
150
149
|
<ImageBackground
|
|
151
|
-
source={
|
|
150
|
+
source={backgroundImageSource}
|
|
152
151
|
style={backgroundImgStyles}
|
|
153
152
|
resizeMode="cover"
|
|
154
153
|
>
|
|
@@ -178,7 +177,7 @@ export function AudioPlayerLayout({ artwork, config, children, style }: Props) {
|
|
|
178
177
|
]}
|
|
179
178
|
>
|
|
180
179
|
<ImageBackground
|
|
181
|
-
source={
|
|
180
|
+
source={backgroundImageSource}
|
|
182
181
|
style={backgroundImgStyles}
|
|
183
182
|
resizeMode="cover"
|
|
184
183
|
>
|
package/Components/Cell/Cell.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
|
12
12
|
import { CellWithFocusable } from "./CellWithFocusable";
|
|
13
13
|
import { BaseFocusable } from "../BaseFocusable";
|
|
14
14
|
import { AccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager";
|
|
15
|
+
import { styles } from "./styles";
|
|
15
16
|
|
|
16
17
|
type Props = {
|
|
17
18
|
item: ZappEntry;
|
|
@@ -68,17 +69,6 @@ type State = {
|
|
|
68
69
|
hasFocusableInside: boolean;
|
|
69
70
|
};
|
|
70
71
|
|
|
71
|
-
const baseCellStyles = {
|
|
72
|
-
height: "100%",
|
|
73
|
-
display: "flex",
|
|
74
|
-
flex: 1,
|
|
75
|
-
} as const;
|
|
76
|
-
|
|
77
|
-
const touchableStyles = {
|
|
78
|
-
flex: 1,
|
|
79
|
-
height: "100%",
|
|
80
|
-
} as const;
|
|
81
|
-
|
|
82
72
|
export class CellComponent extends React.Component<Props, State> {
|
|
83
73
|
constructor(props) {
|
|
84
74
|
super(props);
|
|
@@ -252,7 +242,7 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
252
242
|
<View
|
|
253
243
|
testID={`${component?.id}-${id}`}
|
|
254
244
|
accessible={false}
|
|
255
|
-
style={
|
|
245
|
+
style={styles.touchableCell}
|
|
256
246
|
>
|
|
257
247
|
<Focusable
|
|
258
248
|
id={focusableId}
|
|
@@ -264,7 +254,7 @@ export class CellComponent extends React.Component<Props, State> {
|
|
|
264
254
|
hasReceivedFocus={hasReceivedFocus || this.hasReceivedFocus}
|
|
265
255
|
preferredFocus={preferredFocus}
|
|
266
256
|
offsetUpdater={offsetUpdater}
|
|
267
|
-
style={
|
|
257
|
+
style={styles.baseCell}
|
|
268
258
|
isFocusable={isFocusable}
|
|
269
259
|
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
270
260
|
>
|
|
@@ -5,6 +5,8 @@ import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/
|
|
|
5
5
|
|
|
6
6
|
import { useCellState } from "../MasterCell/utils";
|
|
7
7
|
import { FocusableGroup } from "../FocusableGroup";
|
|
8
|
+
import { CellWrapper } from "./CellWrapper";
|
|
9
|
+
import { styles } from "./styles";
|
|
8
10
|
|
|
9
11
|
type Props = {
|
|
10
12
|
item: ZappEntry;
|
|
@@ -21,6 +23,8 @@ type Props = {
|
|
|
21
23
|
focused?: boolean;
|
|
22
24
|
};
|
|
23
25
|
|
|
26
|
+
const addPrefix = (id: string) => `focusable-cell-wrapper-${id}`;
|
|
27
|
+
|
|
24
28
|
export function CellWithFocusable(props: Props) {
|
|
25
29
|
const {
|
|
26
30
|
index,
|
|
@@ -79,7 +83,7 @@ export function CellWithFocusable(props: Props) {
|
|
|
79
83
|
|
|
80
84
|
return (
|
|
81
85
|
<FocusableGroup
|
|
82
|
-
id={
|
|
86
|
+
id={addPrefix(id)}
|
|
83
87
|
testID={"cell-with-focusable-cell-renderer-focusable-group"}
|
|
84
88
|
groupId={groupId}
|
|
85
89
|
preferredFocus={preferredFocus}
|
|
@@ -88,19 +92,21 @@ export function CellWithFocusable(props: Props) {
|
|
|
88
92
|
onBlur={onGroupBlur}
|
|
89
93
|
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
90
94
|
>
|
|
91
|
-
<
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
95
|
+
<CellWrapper style={styles.cellWrapper}>
|
|
96
|
+
<CellRenderer
|
|
97
|
+
testID={"cell-with-focusable-cell-renderer"}
|
|
98
|
+
item={item}
|
|
99
|
+
groupId={addPrefix(id)}
|
|
100
|
+
onToggleFocus={handleToggleFocus}
|
|
101
|
+
state={state}
|
|
102
|
+
prefixId={id}
|
|
103
|
+
focusedButtonId={focusedButtonId}
|
|
104
|
+
preferredFocus={true}
|
|
105
|
+
skipFocusManagerRegistration={skipFocusManagerRegistration}
|
|
106
|
+
isFocusable={isFocusable}
|
|
107
|
+
focused={focused}
|
|
108
|
+
/>
|
|
109
|
+
</CellWrapper>
|
|
104
110
|
</FocusableGroup>
|
|
105
111
|
);
|
|
106
112
|
}
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StyleSheet } from "react-native";
|
|
2
|
+
|
|
3
|
+
export const styles = StyleSheet.create({
|
|
4
|
+
cellWrapper: {
|
|
5
|
+
flex: 0,
|
|
6
|
+
height: "100%",
|
|
7
|
+
},
|
|
8
|
+
baseCell: {
|
|
9
|
+
height: "100%",
|
|
10
|
+
display: "flex",
|
|
11
|
+
flex: 1,
|
|
12
|
+
},
|
|
13
|
+
touchableCell: {
|
|
14
|
+
flex: 1,
|
|
15
|
+
height: "100%",
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -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 },
|
|
@@ -105,6 +105,11 @@ const defaultProps = {
|
|
|
105
105
|
alignItems: "center",
|
|
106
106
|
justifyContent: "center",
|
|
107
107
|
},
|
|
108
|
+
focusedButton: {
|
|
109
|
+
backgroundColor: "#3a3a3a",
|
|
110
|
+
borderColor: "#ffffff",
|
|
111
|
+
borderWidth: 2,
|
|
112
|
+
},
|
|
108
113
|
buttonText: {
|
|
109
114
|
fontFamily: platformSelect({
|
|
110
115
|
ios: "SFProText-Medium",
|
|
@@ -116,6 +121,9 @@ const defaultProps = {
|
|
|
116
121
|
color: "rgba(255, 255, 255, 1)",
|
|
117
122
|
textTransform: "uppercase",
|
|
118
123
|
},
|
|
124
|
+
focusedText: {
|
|
125
|
+
color: "#ffffff",
|
|
126
|
+
},
|
|
119
127
|
},
|
|
120
128
|
};
|
|
121
129
|
|
|
@@ -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
|
+
};
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
|
|
13
13
|
import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
|
|
14
14
|
import { PlayerContainer } from "../PlayerContainer";
|
|
15
|
+
import { useModalSize } from "../VideoModal/hooks";
|
|
15
16
|
|
|
16
17
|
type Props = {
|
|
17
18
|
item: ZappEntry;
|
|
@@ -136,12 +137,18 @@ export function HandlePlayable({
|
|
|
136
137
|
|
|
137
138
|
const { width: screenWidth, height: screenHeight } = useDimensions("window");
|
|
138
139
|
|
|
140
|
+
const modalSize = useModalSize();
|
|
141
|
+
|
|
139
142
|
const style = React.useMemo(
|
|
140
143
|
() => ({
|
|
141
|
-
width: isModal ?
|
|
142
|
-
height: isModal
|
|
144
|
+
width: isModal ? modalSize.width : mode === "PIP" ? "100%" : screenWidth,
|
|
145
|
+
height: isModal
|
|
146
|
+
? modalSize.height
|
|
147
|
+
: mode === "PIP"
|
|
148
|
+
? "100%"
|
|
149
|
+
: screenHeight,
|
|
143
150
|
}),
|
|
144
|
-
[screenWidth, screenHeight, isModal, mode]
|
|
151
|
+
[screenWidth, screenHeight, modalSize, isModal, mode]
|
|
145
152
|
);
|
|
146
153
|
|
|
147
154
|
const Component = playable?.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,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Image as RnImage, ImageStyle } from "react-native";
|
|
3
|
-
import
|
|
3
|
+
import { equals, omit } from "ramda";
|
|
4
4
|
|
|
5
5
|
import { useImageSource } from "./hooks";
|
|
6
6
|
|
|
@@ -17,7 +17,7 @@ type Props = Record<string, any> & {
|
|
|
17
17
|
withDimensions: (source: Source) => Source;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
const MemoizedImage = React.memo(RnImage,
|
|
20
|
+
const MemoizedImage = React.memo(RnImage, equals);
|
|
21
21
|
|
|
22
22
|
function Image({
|
|
23
23
|
style,
|
|
@@ -44,11 +44,12 @@ function Image({
|
|
|
44
44
|
|
|
45
45
|
return (
|
|
46
46
|
<MemoizedImage
|
|
47
|
+
key={_source?.uri || "no-image"}
|
|
47
48
|
style={style as ImageStyle}
|
|
48
49
|
onError={React.useCallback(() => setErrorState(true), [])}
|
|
49
50
|
// as we have defaults as "" for placeholder image, we need to pass undefined to source to not throw warnings
|
|
50
51
|
source={_source?.uri ? _source : undefined}
|
|
51
|
-
{...
|
|
52
|
+
{...omit(["source"], otherProps)}
|
|
52
53
|
/>
|
|
53
54
|
);
|
|
54
55
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
2
|
+
import { path } from "ramda";
|
|
3
3
|
|
|
4
4
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
5
5
|
import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
|
|
@@ -7,9 +7,13 @@ import { extractAsset } from "./utils";
|
|
|
7
7
|
|
|
8
8
|
type Return = { uri: string } | null;
|
|
9
9
|
|
|
10
|
+
const getSourceContext = path(["source", "context"]);
|
|
11
|
+
const getSourceUri = path(["source", "uri"]);
|
|
12
|
+
const getState = path(["state"]);
|
|
13
|
+
|
|
10
14
|
export const useImageSource = ({ uri, entry, otherProps }): Return => {
|
|
11
|
-
const uriContext =
|
|
12
|
-
const uriState =
|
|
15
|
+
const uriContext = getSourceContext(otherProps);
|
|
16
|
+
const uriState = getState(otherProps);
|
|
13
17
|
|
|
14
18
|
const action = useActions(uriContext);
|
|
15
19
|
|
|
@@ -34,7 +38,7 @@ export const useImageSource = ({ uri, entry, otherProps }): Return => {
|
|
|
34
38
|
return { uri };
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
const uriFromSource =
|
|
41
|
+
const uriFromSource = getSourceUri(otherProps);
|
|
38
42
|
|
|
39
43
|
if (uriFromSource) {
|
|
40
44
|
return { uri: uriFromSource };
|
|
@@ -56,7 +60,7 @@ const getSource = (uri, showDefault, placeholderImage, otherProps) => {
|
|
|
56
60
|
return { uri };
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
const uriFromSource =
|
|
63
|
+
const uriFromSource = getSourceUri(otherProps);
|
|
60
64
|
|
|
61
65
|
if (uriFromSource) {
|
|
62
66
|
return { uri: uriFromSource };
|
|
@@ -72,8 +76,8 @@ export const useImageSourceWithDefault = ({
|
|
|
72
76
|
placeholderImage,
|
|
73
77
|
otherProps,
|
|
74
78
|
}): Return => {
|
|
75
|
-
const uriContext =
|
|
76
|
-
const uriState =
|
|
79
|
+
const uriContext = getSourceContext(otherProps);
|
|
80
|
+
const uriState = getState(otherProps);
|
|
77
81
|
|
|
78
82
|
const action = useActions(uriContext);
|
|
79
83
|
|