@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.
Files changed (61) hide show
  1. package/Components/AudioPlayer/AudioPlayer.tsx +0 -11
  2. package/Components/AudioPlayer/AudioPlayerLayout.tsx +8 -9
  3. package/Components/AudioPlayer/helpers.tsx +0 -2
  4. package/Components/Cell/Cell.tsx +3 -13
  5. package/Components/Cell/CellWithFocusable.tsx +20 -14
  6. package/Components/Cell/CellWrapper.tsx +18 -0
  7. package/Components/Cell/styles.ts +17 -0
  8. package/Components/CellRendererResolver/index.ts +2 -1
  9. package/Components/ErrorScreen/index.tsx +8 -0
  10. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +3 -0
  11. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +4 -2
  12. package/Components/GeneralContentScreen/utils/useEventAlerts.ts +30 -0
  13. package/Components/HandlePlayable/HandlePlayable.tsx +10 -3
  14. package/Components/Layout/TV/LayoutBackground.tsx +28 -0
  15. package/Components/Layout/TV/ScreenContainer.tsx +0 -1
  16. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +15 -10
  17. package/Components/Layout/TV/__tests__/index.test.tsx +8 -2
  18. package/Components/Layout/TV/index.tsx +6 -20
  19. package/Components/Layout/TV/index.web.tsx +4 -1
  20. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +4 -3
  21. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
  22. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
  23. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
  24. package/Components/ModalComponent/BottomSheetModalContent.tsx +66 -54
  25. package/Components/ModalComponent/Button/Item.tsx +6 -5
  26. package/Components/ModalComponent/Button/assets.ts +1 -1
  27. package/Components/ModalComponent/Button/index.tsx +45 -62
  28. package/Components/ModalComponent/Header/index.tsx +9 -8
  29. package/Components/ModalComponent/utils.ts +55 -7
  30. package/Components/PlayerContainer/PlayerContainer.tsx +46 -41
  31. package/Components/River/ComponentsMap/ComponentsMap.tsx +7 -3
  32. package/Components/River/RiverItem.tsx +10 -5
  33. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -1
  34. package/Components/RouteManager/TestId.tsx +1 -5
  35. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +0 -1
  36. package/Components/RouteManager/__tests__/testId.test.js +0 -4
  37. package/Components/Screen/TV/__tests__/index.web.test.tsx +26 -0
  38. package/Components/Screen/__tests__/Screen.test.tsx +22 -14
  39. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -2
  40. package/Components/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
  41. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +4 -2
  42. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +21 -10
  43. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +9 -1
  44. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
  45. package/Components/VideoModal/ModalAnimation/const.ts +5 -0
  46. package/Components/VideoModal/ModalAnimation/index.ts +2 -0
  47. package/Components/VideoModal/ModalAnimation/utils.ts +30 -0
  48. package/Components/VideoModal/PlayerDetails.tsx +9 -4
  49. package/Components/VideoModal/PlayerWrapper.tsx +35 -22
  50. package/Components/VideoModal/VideoModal.tsx +19 -4
  51. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
  52. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +1 -1
  53. package/Components/VideoModal/utils.ts +3 -4
  54. package/Components/ZappUIComponent/index.tsx +4 -4
  55. package/package.json +5 -5
  56. package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
  57. package/Components/Cell/CellStyles/Hero/index.js +0 -111
  58. package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
  59. package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
  60. package/Components/Cell/CellStyles/colors.js +0 -40
  61. 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 backgroundImg = { uri: backgroundImage };
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: 1920,
101
- height: 1080,
100
+ width: "100%",
101
+ height: "100%",
102
102
  alignItems: "center",
103
103
  justifyContent: "center",
104
104
  },
105
105
  android_tv: {
106
- position: "absolute",
107
- width: 1920,
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 = backgroundImg?.uri ? (
148
+ const audioPlayerLayoutTV = backgroundImageSource?.uri ? (
150
149
  <ImageBackground
151
- source={backgroundImg}
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={backgroundImg}
180
+ source={backgroundImageSource}
182
181
  style={backgroundImgStyles}
183
182
  resizeMode="cover"
184
183
  >
@@ -4,8 +4,6 @@ const defaults = {
4
4
  audio_player_background_color: "black",
5
5
  audio_player_artwork_aspect_ratio: "1:1",
6
6
  audio_player_rtl: false,
7
- magic_background: false,
8
- audio_player_background_image_query: "",
9
7
  audio_player_background_image_default_color: "",
10
8
  };
11
9
 
@@ -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={touchableStyles}
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={baseCellStyles}
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={`focusable-cell-wrapper-${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
- <CellRenderer
92
- testID={"cell-with-focusable-cell-renderer"}
93
- item={item}
94
- groupId={`focusable-cell-wrapper-${id}`}
95
- onToggleFocus={handleToggleFocus}
96
- state={state}
97
- prefixId={id}
98
- focusedButtonId={focusedButtonId}
99
- preferredFocus={true}
100
- skipFocusManagerRegistration={skipFocusManagerRegistration}
101
- isFocusable={isFocusable}
102
- focused={focused}
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.component_type !== "group-qb") {
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 { useLayoutPresets } from "@applicaster/zapp-react-native-redux/hooks/useLayoutPresets";
7
- import { useZappPipesFeeds } from "@applicaster/zapp-react-native-redux/hooks/useZappPipesFeeds";
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 ? "100%" : mode === "PIP" ? "100%" : screenWidth,
142
- height: isModal ? "100%" : mode === "PIP" ? "100%" : screenHeight,
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
+ };
@@ -22,7 +22,6 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
22
22
  import { NavBarContainer } from "./NavBarContainer";
23
23
 
24
24
  type ComponentsExtraProps = {
25
- Background?: Record<string, any>;
26
25
  NavBar?: Record<string, any>;
27
26
  };
28
27
 
@@ -2,18 +2,23 @@
2
2
 
3
3
  exports[`Layout TV renders 1`] = `
4
4
  <View
5
- excludeFromFocusSearching={true}
6
- id="/river/A1234"
7
- preferredFocus={true}
5
+ backgroundColor="#000000"
6
+ testID="background-component"
8
7
  >
9
8
  <View
10
- Components={
11
- {
12
- "Background": [Function],
13
- "NavBar": [Function],
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
- route="/river/A1234"
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 } = {}, remoteConfigurations } =
37
- usePickFromState(["appState", "remoteConfigurations", "plugins"]);
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
- </Components.Background>
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
- <StackNavigator Components={Components} />
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 * as R from "ramda";
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, R.equals);
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
- {...R.omit(["source"], otherProps)}
52
+ {...omit(["source"], otherProps)}
52
53
  />
53
54
  );
54
55
  }
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import * as R from "ramda";
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 = R.path(["source", "context"], otherProps);
12
- const uriState = R.path(["state"], otherProps);
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 = R.path(["source", "uri"], otherProps);
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 = R.path(["source", "uri"], otherProps);
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 = R.path(["source", "context"], otherProps);
76
- const uriState = R.path(["state"], otherProps);
79
+ const uriContext = getSourceContext(otherProps);
80
+ const uriState = getState(otherProps);
77
81
 
78
82
  const action = useActions(uriContext);
79
83
 
@@ -0,0 +1,3 @@
1
+ export const PREFIX = "tv_buttons";
2
+
3
+ export const BUTTON_PREFIX = `${PREFIX}_button`;