@applicaster/zapp-react-native-ui-components 13.0.0-alpha.6525006318 → 13.0.0-alpha.6651373134

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 (198) hide show
  1. package/Components/AppContainer/__tests__/AppContainer.test.js +4 -6
  2. package/Components/AppContainer/__tests__/__snapshots__/AppContainer.test.js.snap +1 -1
  3. package/Components/AudioPlayer/AudioPlayer.tsx +7 -0
  4. package/Components/AudioPlayer/__tests__/Runtime.test.js +5 -8
  5. package/Components/AudioPlayer/__tests__/__snapshots__/Runtime.test.js.snap +4 -4
  6. package/Components/AudioPlayer/__tests__/__snapshots__/artWork.test.js.snap +3 -3
  7. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayer.test.js.snap +56 -113
  8. package/Components/AudioPlayer/__tests__/__snapshots__/audioPlayerLayout.test.js.snap +39 -23
  9. package/Components/AudioPlayer/__tests__/__snapshots__/channel.test.js.snap +3 -3
  10. package/Components/AudioPlayer/__tests__/__snapshots__/summary.test.js.snap +2 -2
  11. package/Components/AudioPlayer/__tests__/__snapshots__/title.test.js.snap +2 -2
  12. package/Components/AudioPlayer/__tests__/artWork.test.js +3 -5
  13. package/Components/AudioPlayer/__tests__/audioPlayer.test.js +3 -5
  14. package/Components/AudioPlayer/__tests__/audioPlayerLayout.test.js +7 -8
  15. package/Components/AudioPlayer/__tests__/channel.test.js +3 -5
  16. package/Components/AudioPlayer/__tests__/summary.test.js +3 -5
  17. package/Components/AudioPlayer/__tests__/title.test.js +3 -5
  18. package/Components/AudioPlayer/helpers.tsx +1 -0
  19. package/Components/BaseFocusable/index.ios.ts +1 -1
  20. package/Components/BaseFocusable/index.tsx +67 -31
  21. package/Components/Cell/Cell.tsx +18 -22
  22. package/Components/Cell/CellWithFocusable.tsx +49 -60
  23. package/Components/Cell/CellWrapper.ts +5 -0
  24. package/Components/Cell/TvOSCellComponent.tsx +23 -30
  25. package/Components/Cell/__tests__/CellWIthFocusable.test.js +13 -6
  26. package/Components/Cell/index.js +3 -1
  27. package/Components/Cell/styles.ts +17 -0
  28. package/Components/CellRendererResolver/__tests__/cellRendererResolver.test.js +50 -50
  29. package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +1 -42
  30. package/Components/ComponentResolver/__tests__/componentResolver.test.js +26 -30
  31. package/Components/ContentScreen/__tests__/contentScreen.test.js +3 -3
  32. package/Components/DisplayState/__tests__/__snapshots__/displayState.test.js.snap +2 -2
  33. package/Components/ErrorScreen/index.tsx +14 -6
  34. package/Components/Focusable/Focusable.tsx +1 -54
  35. package/Components/Focusable/FocusableTvOS.tsx +6 -2
  36. package/Components/Focusable/Touchable.tsx +19 -20
  37. package/Components/Focusable/index.android.tsx +10 -3
  38. package/Components/FocusableCell/index.tsx +1 -1
  39. package/Components/FocusableGroup/FocusableTvOS.tsx +34 -86
  40. package/Components/FocusableGroup/index.tsx +0 -3
  41. package/Components/FocusableList/index.tsx +26 -10
  42. package/Components/FocusableScrollView/index.tsx +43 -13
  43. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +76 -7
  44. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +53 -9
  45. package/Components/HandlePlayable/HandlePlayable.tsx +14 -27
  46. package/Components/Layout/TV/NavBarContainer.tsx +19 -23
  47. package/Components/Layout/TV/ScreenContainer.tsx +8 -1
  48. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +5 -0
  49. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +3 -1
  50. package/Components/Layout/TV/__tests__/__snapshots__/LayoutContainer.test.tsx.snap +1 -1
  51. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +6 -5
  52. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +12 -11
  53. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +1 -1
  54. package/Components/Layout/TV/__tests__/index.test.tsx +7 -3
  55. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -3
  56. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  57. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  58. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +10 -15
  59. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
  60. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  61. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +2 -2
  62. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +3 -3
  63. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  64. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  65. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/__snapshots__/index.test.tsx.snap +1 -1
  66. package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +2 -8
  67. package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +180 -180
  68. package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +11 -19
  69. package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +6 -235
  70. package/Components/MasterCell/__tests__/elementMapper.test.js +18 -5
  71. package/Components/MasterCell/__tests__/masterCell.test.js +26 -26
  72. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  73. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +2 -2
  74. package/Components/MasterCell/utils/behaviorProvider.ts +136 -0
  75. package/Components/MasterCell/utils/index.ts +9 -135
  76. package/Components/ModalComponent/Button/assets.ts +1 -1
  77. package/Components/ModalComponent/Button/index.tsx +6 -6
  78. package/Components/ModalComponent/Header/index.tsx +3 -3
  79. package/Components/NativeFocusables/{index.js → index.ts} +4 -2
  80. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +2 -2
  81. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +2 -2
  82. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -5
  83. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +7 -7
  84. package/Components/OfflineHandler/__tests__/index.test.tsx +28 -25
  85. package/Components/OfflineHandler/utils/index.ts +1 -1
  86. package/Components/PlayerContainer/PlayerContainer.tsx +22 -24
  87. package/Components/PlayerContainer/PlayerContainerContext.tsx +9 -0
  88. package/Components/PlayerContainer/ProgramInfo/index.tsx +2 -2
  89. package/Components/PlayerImageBackground/index.tsx +1 -1
  90. package/Components/River/ComponentsMap/ComponentsMap.tsx +42 -65
  91. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  92. package/Components/River/RefreshControl.tsx +1 -1
  93. package/Components/River/RiverFooter.tsx +39 -9
  94. package/Components/River/RiverItem.tsx +37 -2
  95. package/Components/River/TV/index.tsx +6 -1
  96. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +114 -45
  97. package/Components/River/__tests__/__snapshots__/river.test.js.snap +21 -83
  98. package/Components/River/__tests__/componentsMap.test.js +64 -17
  99. package/Components/River/__tests__/river.test.js +75 -40
  100. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +12 -5
  101. package/Components/RouteManager/__tests__/routeManager.test.js +29 -14
  102. package/Components/RouteManager/__tests__/testId.test.js +8 -6
  103. package/Components/Screen/TV/index.web.tsx +5 -6
  104. package/Components/Screen/__tests__/Screen.test.tsx +41 -27
  105. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -4
  106. package/Components/Screen/hooks.ts +53 -0
  107. package/Components/Screen/index.tsx +16 -42
  108. package/Components/ScreenResolver/__tests__/screenResolver.test.js +95 -70
  109. package/Components/Tabs/Tab.tsx +12 -9
  110. package/Components/TextInputTv/__tests__/TextInputTv.test.js +42 -42
  111. package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +7 -0
  112. package/Components/TextInputTv/index.tsx +6 -5
  113. package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +2 -2
  114. package/Components/TrackedView/index.tsx +1 -0
  115. package/Components/Transitioner/AnimationManager.js +15 -15
  116. package/Components/Transitioner/Scene.tsx +53 -24
  117. package/Components/Transitioner/Transitioner.tsx +3 -3
  118. package/Components/Transitioner/__tests__/Scene.test.js +25 -14
  119. package/Components/Transitioner/__tests__/__snapshots__/AnimationManager.test.js.snap +26 -26
  120. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +10 -50
  121. package/Components/Transitioner/__tests__/__snapshots__/config.test.js.snap +20 -20
  122. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +4 -4
  123. package/Components/Transitioner/__tests__/transitioner.test.js +13 -4
  124. package/Components/Transitioner/index.js +8 -4
  125. package/Components/VideoLive/LiveImageManager.ts +27 -1
  126. package/Components/VideoLive/PlayerLiveImageComponent.tsx +36 -24
  127. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +63 -8
  128. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +6 -10
  129. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
  130. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +49 -31
  131. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +8 -4
  132. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +32 -18
  133. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +8 -15
  134. package/Components/VideoModal/ModalAnimation/index.ts +2 -1
  135. package/Components/VideoModal/ModalAnimation/useModalAnimationContext.ts +6 -0
  136. package/Components/VideoModal/ModalAnimation/utils.ts +2 -2
  137. package/Components/VideoModal/OpaqueLayer.tsx +33 -0
  138. package/Components/VideoModal/PlayerDetails.tsx +9 -6
  139. package/Components/VideoModal/PlayerWrapper.tsx +43 -39
  140. package/Components/VideoModal/VideoModal.tsx +16 -25
  141. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -2
  142. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -10
  143. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +4 -4
  144. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +66 -156
  145. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
  146. package/Components/VideoModal/hooks/index.ts +7 -0
  147. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
  148. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
  149. package/Components/VideoModal/hooks/utils/index.ts +33 -0
  150. package/Components/VideoModal/utils.ts +3 -5
  151. package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +24 -36
  152. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -18
  153. package/Components/Viewport/ViewportTracker/__tests__/__snapshots__/viewportTracker.test.js.snap +1 -1
  154. package/Components/Viewport/__tests__/utils.test.js +5 -4
  155. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +1 -0
  156. package/Components/ZappUIComponent/Placeholder.tsx +3 -1
  157. package/Components/ZappUIComponent/__tests__/{ZappUIComponent.test.js → ZappUIComponent.test.tsx} +26 -10
  158. package/Components/ZappUIComponent/index.tsx +3 -16
  159. package/Components/default-cell-renderer/__tests__/defaultCellRenderer.test.tsx +20 -17
  160. package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/__tests__/DefaultCell.test.tsx +15 -11
  161. package/Contexts/ComponentsMapOffsetContext/index.tsx +49 -0
  162. package/Contexts/ConfigutaionContext/__tests__/__snapshots__/ConfigurationProvider.test.tsx.snap +1 -1
  163. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +12 -11
  164. package/Contexts/HeaderOffsetContext/index.tsx +4 -6
  165. package/Contexts/ScreenContext/index.tsx +6 -12
  166. package/Contexts/ScreenLayoutContext/index.tsx +5 -3
  167. package/Decorators/Analytics/{index.js → index.tsx} +11 -11
  168. package/Decorators/Navigator/__tests__/navigator.test.js +16 -16
  169. package/Decorators/Navigator/index.tsx +1 -1
  170. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +77 -77
  171. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +34 -39
  172. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -9
  173. package/Decorators/RiverFeedLoader/index.tsx +1 -1
  174. package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +39 -0
  175. package/Decorators/RiverFeedLoader/utils/index.ts +29 -0
  176. package/Decorators/RiverFeedLoader/utils/usePipesContexts.ts +40 -0
  177. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +27 -27
  178. package/Decorators/RiverResolver/index.tsx +6 -8
  179. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  180. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +29 -22
  181. package/Decorators/ZappPipesDataConnector/index.tsx +7 -3
  182. package/package.json +13 -11
  183. package/tsconfig.json +2 -3
  184. package/.babelrc +0 -8
  185. package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
  186. package/Components/Cell/CellStyles/Hero/index.js +0 -111
  187. package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
  188. package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
  189. package/Components/Cell/CellStyles/colors.js +0 -40
  190. package/Components/Cell/CellStyles/index.js +0 -15
  191. package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +0 -53
  192. package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +0 -17
  193. package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +0 -17
  194. package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +0 -91
  195. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +0 -338
  196. package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +0 -18
  197. package/Decorators/RiverFeedLoader/utils.ts +0 -100
  198. package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +0 -28
@@ -1,14 +1,14 @@
1
1
  import * as React from "react";
2
2
  import * as R from "ramda";
3
- import { ViewStyle } from "react-native";
4
3
  import {
5
4
  findPluginByType,
6
5
  findPluginByIdentifier,
7
6
  } from "@applicaster/zapp-react-native-utils/pluginUtils";
8
- import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
9
7
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
10
- import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
11
- import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
8
+ import {
9
+ useDimensions,
10
+ useNavigation,
11
+ } from "@applicaster/zapp-react-native-utils/reactHooks";
12
12
 
13
13
  import { BufferAnimation } from "../PlayerContainer/BufferAnimation";
14
14
  import { PlayerContainer } from "../PlayerContainer";
@@ -78,12 +78,6 @@ const getPlayer = (
78
78
  return getPlayerWithModuleProperties(PlayerModule);
79
79
  };
80
80
 
81
- const dimensionsContext: "window" | "screen" = platformSelect({
82
- android_tv: "window",
83
- amazon: "window",
84
- default: "screen",
85
- });
86
-
87
81
  type PlayableComponent = {
88
82
  Component: React.ComponentType<any>;
89
83
  };
@@ -91,16 +85,11 @@ type PlayableComponent = {
91
85
  export function HandlePlayable({
92
86
  item,
93
87
  isModal,
94
- modalHeight,
95
- modalWidth,
96
88
  mode,
97
89
  groupId,
98
90
  }: Props): React.ReactElement | null {
99
91
  const state = usePickFromState();
100
92
 
101
- const { width: screenWidth, height: screenHeight } =
102
- useDimensions(dimensionsContext);
103
-
104
93
  const { closeVideoModal } = useNavigation();
105
94
 
106
95
  const [Player, playerModuleProperties] = getPlayer(item, state);
@@ -118,9 +107,7 @@ export function HandlePlayable({
118
107
  if (!isModal) {
119
108
  closeVideoModal();
120
109
  }
121
- }, []);
122
110
 
123
- React.useEffect(() => {
124
111
  const castStateHandler = async () => {
125
112
  const castState = await CastPlugin?.getCastState();
126
113
  setCasting(castState === "Connected");
@@ -142,23 +129,23 @@ export function HandlePlayable({
142
129
  }, []);
143
130
 
144
131
  React.useEffect(() => {
145
- if (casting) {
146
- setPlayable({ Component: CastPlugin?.CastHandler });
147
- } else {
148
- setPlayable({ Component: PlayerContainer });
149
- }
132
+ setPlayable({
133
+ Component: casting ? CastPlugin?.CastHandler : PlayerContainer,
134
+ });
150
135
  }, [casting]);
151
136
 
152
- const Component = playable?.Component;
137
+ const { width: screenWidth, height: screenHeight } = useDimensions("window");
153
138
 
154
139
  const style = React.useMemo(
155
140
  () => ({
156
- width: isModal ? modalWidth : mode === "PIP" ? "100%" : screenWidth,
157
- height: isModal ? modalHeight : mode === "PIP" ? "100%" : screenHeight,
141
+ width: isModal ? "100%" : mode === "PIP" ? "100%" : screenWidth,
142
+ height: isModal ? "100%" : mode === "PIP" ? "100%" : screenHeight,
158
143
  }),
159
- [screenWidth, screenHeight, modalHeight, modalWidth, isModal, mode]
144
+ [screenWidth, screenHeight, isModal, mode]
160
145
  );
161
146
 
147
+ const Component = playable?.Component;
148
+
162
149
  if (Component) {
163
150
  return (
164
151
  <Component
@@ -174,5 +161,5 @@ export function HandlePlayable({
174
161
  );
175
162
  }
176
163
 
177
- return !isModal ? <BufferAnimation videoStyle={style as ViewStyle} /> : null;
164
+ return !isModal ? <BufferAnimation videoStyle={style} /> : null;
178
165
  }
@@ -1,9 +1,5 @@
1
1
  import * as React from "react";
2
- import { View, StyleSheet } from "react-native";
3
- import { ScreenLayoutContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenLayoutContext";
4
- import { ifEmptyUseFallback } from "@applicaster/zapp-react-native-utils/cellUtils";
5
- import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
6
- import { useScreenConfiguration } from "../../River/useScreenConfiguration";
2
+ import { StyleSheet, View } from "react-native";
7
3
 
8
4
  type Props = {
9
5
  children: React.ReactNode;
@@ -12,33 +8,33 @@ type Props = {
12
8
  };
13
9
 
14
10
  const styles = StyleSheet.create({
15
- container: { position: "absolute", top: 0, zIndex: 10, width: 1920 },
11
+ container: {
12
+ position: "absolute",
13
+ top: 0,
14
+ zIndex: 10,
15
+ flex: 1,
16
+ width: "100%",
17
+ },
18
+ themeStyles: {
19
+ // limits the height of the focusable container of the TopMenuBarTV component
20
+ // to prevent it from being overlapped by the screen content,
21
+ // as it makes TopMenuBarTV unfocusable on tvOS
22
+ maxHeight: 1,
23
+ },
16
24
  });
17
25
 
18
26
  export const NavBarContainer = ({ children, isVisible, onReady }: Props) => {
19
- const screenLayout = React.useContext(ScreenLayoutContext);
20
- const screenMarginTop = screenLayout?.screenMarginTop || 0;
21
- const screen = useCurrentScreenData();
22
- const screenConfig = useScreenConfiguration(screen?.id);
23
-
24
- const themeStyles = React.useMemo(
25
- () => ({
26
- // limits the height of the focusable container of the TopMenuBarTV component
27
- // to prevent it from being overlapped by the screen content,
28
- // as it makes TopMenuBarTV unfocusable on tvOS
29
- maxHeight: ifEmptyUseFallback(screenConfig?.marginTop, screenMarginTop),
30
- }),
31
- [screenLayout, screenConfig]
32
- );
33
-
34
27
  React.useEffect(() => {
35
28
  setTimeout(() => {
36
29
  onReady?.(true);
37
30
  }, 0);
38
- }, []);
31
+ }, [onReady]);
39
32
 
40
33
  return isVisible ? (
41
- <View testID="nav-bar-container" style={[styles.container, themeStyles]}>
34
+ <View
35
+ testID="nav-bar-container"
36
+ style={[styles.container, styles.themeStyles]}
37
+ >
42
38
  {children}
43
39
  </View>
44
40
  ) : null;
@@ -55,8 +55,11 @@ export const ScreenContainer = React.memo(function ScreenContainer({
55
55
  ComponentsExtraProps,
56
56
  NavBar,
57
57
  }: Props) {
58
- const { screenMarginBottom } = React.useContext(ScreenLayoutContext);
58
+ const { screenMarginBottom, resetScreenLayout } =
59
+ React.useContext(ScreenLayoutContext);
60
+
59
61
  const { currentRoute, screenData } = useNavigation();
62
+
60
63
  const screen = useCurrentScreenData();
61
64
 
62
65
  const { marginBottom, backgroundColor, paddingTop, paddingBottom } =
@@ -65,6 +68,10 @@ export const ScreenContainer = React.memo(function ScreenContainer({
65
68
  const theme = useTheme();
66
69
  const getThemeValue = React.useCallback(R.propOr(0, R.__, theme), [theme]);
67
70
 
71
+ React.useEffect(() => {
72
+ resetScreenLayout();
73
+ }, [currentRoute]);
74
+
68
75
  const fullscreen = React.useCallback(
69
76
  displayFullScreen({ currentRoute, screenData }),
70
77
  [currentRoute, screenData]
@@ -60,10 +60,15 @@ export function ScreenLayoutContextProvider(props: {
60
60
  initialState
61
61
  );
62
62
 
63
+ const resetScreenLayout = React.useCallback(() => {
64
+ setScreenLayout(initialState);
65
+ }, [initialState]);
66
+
63
67
  const screenLayoutValue = React.useMemo(
64
68
  () => ({
65
69
  ...screenLayout,
66
70
  setScreenLayout,
71
+ resetScreenLayout,
67
72
  }),
68
73
  [screenLayout]
69
74
  );
@@ -39,6 +39,7 @@ jest.mock(
39
39
  );
40
40
 
41
41
  jest.mock("@applicaster/zapp-react-native-utils/theme", () => ({
42
+ ...jest.requireActual<any>("@applicaster/zapp-react-native-utils/theme"),
42
43
  useTheme: () => ({}),
43
44
  }));
44
45
 
@@ -55,11 +56,12 @@ describe("ScreenContainer", () => {
55
56
  };
56
57
 
57
58
  const setScreenLayout = () => {};
59
+ const resetScreenLayout = () => {};
58
60
 
59
61
  const wrapper = ({ children }) => (
60
62
  <WrappedWithProviders>
61
63
  <ScreenLayoutContext.Provider
62
- value={{ ...screenLayout, setScreenLayout }}
64
+ value={{ ...screenLayout, setScreenLayout, resetScreenLayout }}
63
65
  >
64
66
  <ScreenContainer NavBar={View}>{children}</ScreenContainer>
65
67
  </ScreenLayoutContext.Provider>
@@ -3,7 +3,7 @@
3
3
  exports[`LayoutContainer renders 1`] = `
4
4
  <View
5
5
  style={
6
- Object {
6
+ {
7
7
  "flex": 1,
8
8
  "height": 1080,
9
9
  "width": 1920,
@@ -3,15 +3,16 @@
3
3
  exports[`NavBarContainer renders 1`] = `
4
4
  <View
5
5
  style={
6
- Array [
7
- Object {
6
+ [
7
+ {
8
+ "flex": 1,
8
9
  "position": "absolute",
9
10
  "top": 0,
10
- "width": 1920,
11
+ "width": "100%",
11
12
  "zIndex": 10,
12
13
  },
13
- Object {
14
- "maxHeight": 10,
14
+ {
15
+ "maxHeight": 1,
15
16
  },
16
17
  ]
17
18
  }
@@ -4,8 +4,8 @@ exports[`ScreenContainer renders 1`] = `
4
4
  <RNCSafeAreaProvider
5
5
  onInsetsChange={[Function]}
6
6
  style={
7
- Array [
8
- Object {
7
+ [
8
+ {
9
9
  "flex": 1,
10
10
  },
11
11
  undefined,
@@ -14,15 +14,16 @@ exports[`ScreenContainer renders 1`] = `
14
14
  >
15
15
  <View
16
16
  style={
17
- Array [
18
- Object {
17
+ [
18
+ {
19
+ "flex": 1,
19
20
  "position": "absolute",
20
21
  "top": 0,
21
- "width": 1920,
22
+ "width": "100%",
22
23
  "zIndex": 10,
23
24
  },
24
- Object {
25
- "maxHeight": 10,
25
+ {
26
+ "maxHeight": 1,
26
27
  },
27
28
  ]
28
29
  }
@@ -30,7 +31,7 @@ exports[`ScreenContainer renders 1`] = `
30
31
  >
31
32
  <View
32
33
  isVisible={true}
33
- menuPlugin={Object {}}
34
+ menuPlugin={{}}
34
35
  navigationProps={null}
35
36
  />
36
37
  </View>
@@ -38,13 +39,13 @@ exports[`ScreenContainer renders 1`] = `
38
39
  `;
39
40
 
40
41
  exports[`ScreenContainer sets margins provided by the theme 1`] = `
41
- Array [
42
- Object {
42
+ [
43
+ {
43
44
  "flex": 1,
44
45
  "height": "100%",
45
46
  "width": "100%",
46
47
  },
47
- Object {
48
+ {
48
49
  "backgroundColor": "transparent",
49
50
  "marginBottom": 10,
50
51
  "paddingBottom": 0,
@@ -8,7 +8,7 @@ exports[`Layout TV renders 1`] = `
8
8
  >
9
9
  <View
10
10
  Components={
11
- Object {
11
+ {
12
12
  "Background": [Function],
13
13
  "NavBar": [Function],
14
14
  }
@@ -8,9 +8,13 @@ import configureStore from "redux-mock-store";
8
8
 
9
9
  const withoutChildren = omit(["children"]);
10
10
 
11
- jest.mock("../../../Screen/TV/index.web", () => ({
12
- Screen: View,
13
- }));
11
+ jest.mock("../../../Screen/TV/index.web", () => {
12
+ const View = jest.requireActual("react-native").View;
13
+
14
+ return {
15
+ Screen: View,
16
+ };
17
+ });
14
18
 
15
19
  const Layout = require("../index.web").default;
16
20
 
@@ -4,7 +4,6 @@ import { TouchableOpacity, ViewStyle } from "react-native";
4
4
  import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
5
5
 
6
6
  import Image from "./Image";
7
-
8
7
  type Props = {
9
8
  item: ZappEntry | ZappFeed;
10
9
  flavour?: "flavour_1" | "flavour_2";
@@ -69,7 +68,7 @@ export function ActionButton(props: Props) {
69
68
  if (!((actionDisabled || !actionContext) && actionState !== null)) {
70
69
  setActionState(actionContext.initialEntryState(item));
71
70
  }
72
- }, [actionDisabled, item?.id, actionContext, action]);
71
+ }, [actionDisabled, item?.id, actionContext, action, setActionState]);
73
72
 
74
73
  const onPress = useCallback(() => {
75
74
  actionContext.invokeAction(item, {
@@ -85,7 +84,7 @@ export function ActionButton(props: Props) {
85
84
  setActionState(state);
86
85
  });
87
86
  }
88
- }, [item?.id]);
87
+ }, [item?.id, setActionState, actionContext]);
89
88
 
90
89
  if (actionDisabled || !actionContext) return null;
91
90
  const AssetComponent = actionState?.asset;
@@ -0,0 +1,66 @@
1
+ import {
2
+ BorderContainerView,
3
+ getBorderPadding, // Export for testing (using a double underscore prefix is a common convention)
4
+ } from "../index";
5
+ import * as React from "react";
6
+ import { render } from "@testing-library/react-native";
7
+ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
8
+ import { View } from "react-native";
9
+
10
+ jest.mock("@applicaster/zapp-react-native-utils/numberUtils", () => ({
11
+ toNumberWithDefaultZero: jest.fn((value) => Number(value) || 0),
12
+ }));
13
+
14
+ describe("BorderContainerView", () => {
15
+ describe("getBorderPadding", () => {
16
+ it("returns 0 for inside", () => {
17
+ expect(getBorderPadding("inside", 10)).toBe(0);
18
+ });
19
+
20
+ it("returns borderWidth / 2 for center", () => {
21
+ expect(getBorderPadding("center", 10)).toBe(5);
22
+ });
23
+
24
+ it("returns borderWidth for outside", () => {
25
+ expect(getBorderPadding("outside", 10)).toBe(10);
26
+ });
27
+
28
+ it("returns borderWidth for invalid position", () => {
29
+ // @ts-ignore
30
+ expect(getBorderPadding("other_value", 10)).toBe(10);
31
+ });
32
+ });
33
+
34
+ it("Border component renders null if no borderPosition", () => {
35
+ const style = { borderWidth: 5, borderRadius: 10, borderColor: "red" };
36
+
37
+ const padding = {
38
+ paddingTop: 2,
39
+ paddingRight: 3,
40
+ paddingBottom: 4,
41
+ paddingLeft: 5,
42
+ };
43
+
44
+ const borderPosition = null;
45
+
46
+ const { queryByTestId } = render(
47
+ <BorderContainerView
48
+ style={style}
49
+ testID="border-container"
50
+ borderPosition={borderPosition}
51
+ borderPaddingTop={toNumberWithDefaultZero(padding.paddingTop)}
52
+ borderPaddingRight={toNumberWithDefaultZero(padding.paddingRight)}
53
+ borderPaddingBottom={toNumberWithDefaultZero(padding.paddingBottom)}
54
+ borderPaddingLeft={toNumberWithDefaultZero(padding.paddingLeft)}
55
+ >
56
+ <View testID="child" />
57
+ </BorderContainerView>
58
+ );
59
+
60
+ const children = queryByTestId("border-container").children;
61
+
62
+ expect(children[1].props.testID).toBe("child");
63
+
64
+ expect(children[0].children.length).toBe(0);
65
+ });
66
+ });
@@ -28,7 +28,10 @@ const styles = StyleSheet.create({
28
28
  },
29
29
  });
30
30
 
31
- const getBorderPadding = (borderPosition: BorderPosition, borderWidth) => {
31
+ export const getBorderPadding = (
32
+ borderPosition: BorderPosition,
33
+ borderWidth: number
34
+ ) => {
32
35
  switch (borderPosition) {
33
36
  case "inside":
34
37
  return 0;
@@ -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,
@@ -38,23 +38,18 @@ function Image({
38
38
 
39
39
  const shouldRenderImg = source && !error;
40
40
 
41
- // Default placeholder image fallback is empty string because it won't rerender
42
- // in case of undefined or {uri: undefined} source
43
- // https://github.com/facebook/react-native/issues/9195
44
- const defaultPlaceHolderImage = React.useMemo(
45
- () => ({ uri: placeholderImage || "" }),
46
- [source, error]
47
- );
41
+ const _source = shouldRenderImg
42
+ ? withDimensions(source)
43
+ : { uri: placeholderImage };
48
44
 
49
45
  return (
50
- // @ts-ignore
51
46
  <MemoizedImage
47
+ key={_source?.uri || "no-image"}
52
48
  style={style as ImageStyle}
53
- onError={() => setErrorState(true)}
54
- source={
55
- shouldRenderImg ? withDimensions(source) : defaultPlaceHolderImage
56
- }
57
- {...R.omit(["source"], otherProps)}
49
+ onError={React.useCallback(() => setErrorState(true), [])}
50
+ // as we have defaults as "" for placeholder image, we need to pass undefined to source to not throw warnings
51
+ source={_source?.uri ? _source : undefined}
52
+ {...omit(["source"], otherProps)}
58
53
  />
59
54
  );
60
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,93 @@
1
+ import { ImageBorderContainer } from "../index";
2
+ import { getImageContainerMarginStyles } from "@applicaster/zapp-react-native-utils/cellUtils";
3
+
4
+ const mockValue = (key) => {
5
+ const values = {
6
+ cell_padding_top: 1,
7
+ cell_padding_left: 2,
8
+ cell_padding_right: 3,
9
+ cell_padding_bottom: 4,
10
+ image_border_size: 5,
11
+ image_focused_border_color: "red",
12
+ image_selected_border_color: "blue",
13
+ image_focused_selected_border_color: "green",
14
+ image_border_color: "black",
15
+ image_corner_radius: 10,
16
+ image_border_position: "outside",
17
+ image_border_padding_top: 6,
18
+ image_border_padding_right: 7,
19
+ image_border_padding_bottom: 8,
20
+ image_border_padding_left: 9,
21
+ image_margin_top: 11,
22
+ image_margin_left: 12,
23
+ image_margin_right: 13,
24
+ image_margin_bottom: 14,
25
+ };
26
+
27
+ return values[key] || 0;
28
+ };
29
+
30
+ describe("ImageBorderContainer", () => {
31
+ it("calculates style properties correctly", () => {
32
+ const marginStyles = getImageContainerMarginStyles({ value: mockValue });
33
+
34
+ expect(marginStyles.marginTop).toBe(11);
35
+ expect(marginStyles.marginLeft).toBe(12);
36
+ expect(marginStyles.marginRight).toBe(13);
37
+ expect(marginStyles.marginBottom).toBe(14);
38
+
39
+ const props = {
40
+ value: mockValue,
41
+ state: "default",
42
+ imageStyles: {},
43
+ };
44
+
45
+ const result = ImageBorderContainer(props);
46
+
47
+ expect(result.style.marginTop).toBe(12); // 11 + 1
48
+ expect(result.style.marginLeft).toBe(14); // 12 + 2
49
+ expect(result.style.marginRight).toBe(16); // 13 + 3
50
+ expect(result.style.marginBottom).toBe(18); // 14 + 4
51
+ expect(result.style.borderWidth).toBe(5);
52
+ expect(result.style.borderColor).toBe("black");
53
+ expect(result.style.borderRadius).toBe(10);
54
+ expect(result.additionalProps.borderPosition).toBe("outside");
55
+ expect(result.additionalProps.borderPaddingTop).toBe(6);
56
+ expect(result.additionalProps.borderPaddingRight).toBe(7);
57
+ expect(result.additionalProps.borderPaddingBottom).toBe(8);
58
+ expect(result.additionalProps.borderPaddingLeft).toBe(9);
59
+ });
60
+
61
+ it("handles focused state correctly", () => {
62
+ const props = {
63
+ value: mockValue,
64
+ state: "focused",
65
+ imageStyles: {},
66
+ };
67
+
68
+ const result = ImageBorderContainer(props);
69
+ expect(result.style.borderColor).toBe("red");
70
+ });
71
+
72
+ it("handles selected state correctly", () => {
73
+ const props = {
74
+ value: mockValue,
75
+ state: "selected",
76
+ imageStyles: {},
77
+ };
78
+
79
+ const result = ImageBorderContainer(props);
80
+ expect(result.style.borderColor).toBe("blue");
81
+ });
82
+
83
+ it("handles focused and selected state correctly", () => {
84
+ const props = {
85
+ value: mockValue,
86
+ state: "focused_selected",
87
+ imageStyles: {},
88
+ };
89
+
90
+ const result = ImageBorderContainer(props);
91
+ expect(result.style.borderColor).toBe("green");
92
+ });
93
+ });
@@ -244,7 +244,7 @@ const LiveImageComponent = (props: LiveImageProps) => {
244
244
  return (
245
245
  <>
246
246
  <Image {...props} applyMaxSize />
247
- {isShouldRender && (
247
+ {isShouldRender ? (
248
248
  <View style={[style, positionAbsolute]}>
249
249
  <PlayerLiveImage
250
250
  uri={props.uri}
@@ -257,7 +257,7 @@ const LiveImageComponent = (props: LiveImageProps) => {
257
257
  audioMutedByDefault={audio_muted_by_default}
258
258
  />
259
259
  </View>
260
- )}
260
+ ) : null}
261
261
  </>
262
262
  );
263
263
  };