@applicaster/zapp-react-native-ui-components 13.0.0-rc.11 → 13.0.0-rc.110

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 (212) 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 +51 -60
  23. package/Components/Cell/CellWrapper.tsx +18 -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/CellRendererResolver/index.ts +2 -1
  30. package/Components/ComponentResolver/__tests__/__snapshots__/componentResolver.test.js.snap +1 -42
  31. package/Components/ComponentResolver/__tests__/componentResolver.test.js +26 -30
  32. package/Components/ContentScreen/__tests__/contentScreen.test.js +3 -3
  33. package/Components/DisplayState/__tests__/__snapshots__/displayState.test.js.snap +2 -2
  34. package/Components/ErrorScreen/index.tsx +14 -6
  35. package/Components/Focusable/Focusable.tsx +1 -54
  36. package/Components/Focusable/FocusableTvOS.tsx +6 -2
  37. package/Components/Focusable/Touchable.tsx +19 -20
  38. package/Components/Focusable/index.android.tsx +10 -3
  39. package/Components/FocusableCell/index.tsx +1 -1
  40. package/Components/FocusableGroup/FocusableTvOS.tsx +34 -86
  41. package/Components/FocusableGroup/index.tsx +0 -3
  42. package/Components/FocusableList/index.tsx +26 -10
  43. package/Components/FocusableScrollView/index.tsx +43 -13
  44. package/Components/GeneralContentScreen/GeneralContentScreen.tsx +3 -0
  45. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +9 -0
  46. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
  47. package/Components/GeneralContentScreen/utils/useEventAlerts.ts +30 -0
  48. package/Components/HandlePlayable/HandlePlayable.tsx +21 -27
  49. package/Components/Layout/TV/LayoutBackground.tsx +28 -0
  50. package/Components/Layout/TV/NavBarContainer.tsx +19 -23
  51. package/Components/Layout/TV/ScreenContainer.tsx +8 -2
  52. package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +5 -0
  53. package/Components/Layout/TV/__tests__/ScreenContainer.test.tsx +3 -1
  54. package/Components/Layout/TV/__tests__/__snapshots__/LayoutContainer.test.tsx.snap +1 -1
  55. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +6 -5
  56. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +12 -11
  57. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +15 -10
  58. package/Components/Layout/TV/__tests__/index.test.tsx +14 -4
  59. package/Components/Layout/TV/index.tsx +6 -20
  60. package/Components/Layout/TV/index.web.tsx +4 -1
  61. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +2 -3
  62. package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
  63. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
  64. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +10 -15
  65. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +11 -7
  66. package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
  67. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +2 -2
  68. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +3 -3
  69. package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
  70. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
  71. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/const.ts +3 -0
  72. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +6 -6
  73. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/__snapshots__/index.test.tsx.snap +1 -1
  74. package/Components/MasterCell/SharedUI/ProgressBar/hooks/useFillInPercent.ts +2 -8
  75. package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +180 -180
  76. package/Components/MasterCell/__tests__/__snapshots__/elementMapper.test.js.snap +11 -19
  77. package/Components/MasterCell/__tests__/__snapshots__/masterCell.test.js.snap +6 -235
  78. package/Components/MasterCell/__tests__/elementMapper.test.js +18 -5
  79. package/Components/MasterCell/__tests__/masterCell.test.js +26 -26
  80. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
  81. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +2 -2
  82. package/Components/MasterCell/utils/behaviorProvider.ts +136 -0
  83. package/Components/MasterCell/utils/index.ts +9 -135
  84. package/Components/ModalComponent/BottomSheetModalContent.tsx +45 -19
  85. package/Components/ModalComponent/Button/Item.tsx +6 -5
  86. package/Components/ModalComponent/Button/assets.ts +1 -1
  87. package/Components/ModalComponent/Button/index.tsx +30 -43
  88. package/Components/ModalComponent/Header/index.tsx +3 -3
  89. package/Components/ModalComponent/utils.ts +55 -7
  90. package/Components/NativeFocusables/{index.js → index.ts} +4 -2
  91. package/Components/OfflineHandler/NotificationView/NotificationView.lg.tsx +2 -2
  92. package/Components/OfflineHandler/NotificationView/NotificationView.samsung.tsx +2 -2
  93. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +0 -5
  94. package/Components/OfflineHandler/__tests__/__snapshots__/index.test.tsx.snap +7 -7
  95. package/Components/OfflineHandler/__tests__/index.test.tsx +28 -25
  96. package/Components/OfflineHandler/utils/index.ts +1 -1
  97. package/Components/PlayerContainer/PlayerContainer.tsx +45 -25
  98. package/Components/PlayerContainer/PlayerContainerContext.tsx +9 -0
  99. package/Components/PlayerContainer/ProgramInfo/index.tsx +2 -2
  100. package/Components/PlayerImageBackground/index.tsx +1 -1
  101. package/Components/River/ComponentsMap/ComponentsMap.tsx +42 -65
  102. package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
  103. package/Components/River/RefreshControl.tsx +1 -1
  104. package/Components/River/RiverFooter.tsx +39 -9
  105. package/Components/River/RiverItem.tsx +39 -3
  106. package/Components/River/TV/index.tsx +6 -1
  107. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +114 -45
  108. package/Components/River/__tests__/__snapshots__/river.test.js.snap +21 -83
  109. package/Components/River/__tests__/componentsMap.test.js +64 -17
  110. package/Components/River/__tests__/river.test.js +75 -40
  111. package/Components/RouteManager/__tests__/__snapshots__/routeManager.test.js.snap +12 -5
  112. package/Components/RouteManager/__tests__/routeManager.test.js +29 -14
  113. package/Components/RouteManager/__tests__/testId.test.js +8 -6
  114. package/Components/Screen/TV/__tests__/index.web.test.tsx +26 -0
  115. package/Components/Screen/TV/index.web.tsx +5 -6
  116. package/Components/Screen/__tests__/Screen.test.tsx +53 -31
  117. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +6 -6
  118. package/Components/Screen/hooks.ts +53 -0
  119. package/Components/Screen/index.tsx +16 -42
  120. package/Components/ScreenResolver/__tests__/screenResolver.test.js +95 -70
  121. package/Components/Tabs/Tab.tsx +12 -9
  122. package/Components/TextInputTv/__tests__/TextInputTv.test.js +42 -42
  123. package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +7 -0
  124. package/Components/TextInputTv/index.tsx +6 -5
  125. package/Components/TopMarginApplicator/TopMarginApplicator.tsx +2 -3
  126. package/Components/Touchable/__tests__/__snapshots__/touchable.test.tsx.snap +2 -2
  127. package/Components/TrackedView/index.tsx +1 -0
  128. package/Components/Transitioner/AnimationManager.js +15 -15
  129. package/Components/Transitioner/Scene.tsx +53 -24
  130. package/Components/Transitioner/Transitioner.tsx +3 -3
  131. package/Components/Transitioner/__tests__/Scene.test.js +25 -14
  132. package/Components/Transitioner/__tests__/__snapshots__/AnimationManager.test.js.snap +26 -26
  133. package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +10 -50
  134. package/Components/Transitioner/__tests__/__snapshots__/config.test.js.snap +20 -20
  135. package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +4 -4
  136. package/Components/Transitioner/__tests__/transitioner.test.js +13 -4
  137. package/Components/Transitioner/index.js +8 -4
  138. package/Components/VideoLive/LiveImageManager.ts +27 -1
  139. package/Components/VideoLive/PlayerLiveImageComponent.tsx +36 -24
  140. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +63 -8
  141. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +6 -10
  142. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +1 -1
  143. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +51 -31
  144. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +8 -4
  145. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +48 -22
  146. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +15 -15
  147. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +108 -0
  148. package/Components/VideoModal/ModalAnimation/const.ts +5 -0
  149. package/Components/VideoModal/ModalAnimation/index.ts +4 -1
  150. package/Components/VideoModal/ModalAnimation/useModalAnimationContext.ts +6 -0
  151. package/Components/VideoModal/ModalAnimation/utils.ts +38 -2
  152. package/Components/VideoModal/OpaqueLayer.tsx +33 -0
  153. package/Components/VideoModal/PlayerDetails.tsx +18 -10
  154. package/Components/VideoModal/PlayerWrapper.tsx +43 -39
  155. package/Components/VideoModal/VideoModal.tsx +17 -11
  156. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -2
  157. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +13 -10
  158. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +2 -40
  159. package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +66 -156
  160. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
  161. package/Components/VideoModal/hooks/index.ts +7 -0
  162. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
  163. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
  164. package/Components/VideoModal/hooks/utils/index.ts +33 -0
  165. package/Components/VideoModal/utils.ts +6 -9
  166. package/Components/Viewport/ViewportAware/__tests__/__snapshots__/viewportAware.test.js.snap +24 -36
  167. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +12 -18
  168. package/Components/Viewport/ViewportTracker/__tests__/__snapshots__/viewportTracker.test.js.snap +1 -1
  169. package/Components/Viewport/__tests__/utils.test.js +5 -4
  170. package/Components/ZappUIComponent/Placeholder.tsx +3 -1
  171. package/Components/ZappUIComponent/__tests__/{ZappUIComponent.test.js → ZappUIComponent.test.tsx} +26 -10
  172. package/Components/ZappUIComponent/index.tsx +4 -17
  173. package/Components/default-cell-renderer/__tests__/defaultCellRenderer.test.tsx +20 -17
  174. package/Components/default-cell-renderer/viewTrees/tv/DefaultCell/__tests__/DefaultCell.test.tsx +15 -11
  175. package/Contexts/ComponentsMapOffsetContext/index.tsx +49 -0
  176. package/Contexts/ConfigutaionContext/__tests__/__snapshots__/ConfigurationProvider.test.tsx.snap +1 -1
  177. package/Contexts/FocusableGroupContext/withFocusableContext.tsx +4 -10
  178. package/Contexts/HeaderOffsetContext/index.tsx +4 -6
  179. package/Contexts/ScreenContext/index.tsx +6 -12
  180. package/Contexts/ScreenLayoutContext/index.tsx +5 -3
  181. package/Decorators/Analytics/{index.js → index.tsx} +11 -11
  182. package/Decorators/Navigator/__tests__/navigator.test.js +16 -16
  183. package/Decorators/Navigator/index.tsx +1 -1
  184. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +77 -77
  185. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +34 -39
  186. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -9
  187. package/Decorators/RiverFeedLoader/index.tsx +1 -1
  188. package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +39 -0
  189. package/Decorators/RiverFeedLoader/utils/index.ts +29 -0
  190. package/Decorators/RiverFeedLoader/utils/usePipesContexts.ts +40 -0
  191. package/Decorators/RiverResolver/__tests__/riverResolver.test.tsx +27 -27
  192. package/Decorators/RiverResolver/index.tsx +6 -8
  193. package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
  194. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +29 -22
  195. package/Decorators/ZappPipesDataConnector/index.tsx +7 -3
  196. package/package.json +13 -11
  197. package/tsconfig.json +2 -3
  198. package/.babelrc +0 -8
  199. package/Components/Cell/CellStyles/FallbackCellStyle/index.js +0 -157
  200. package/Components/Cell/CellStyles/Hero/index.js +0 -111
  201. package/Components/Cell/CellStyles/ScreenSelector/index.js +0 -68
  202. package/Components/Cell/CellStyles/cellStylesResolver.ts +0 -19
  203. package/Components/Cell/CellStyles/colors.js +0 -40
  204. package/Components/Cell/CellStyles/index.js +0 -15
  205. package/Components/CellRendererResolver/__tests__/__snapshots__/cellRendererResolver.test.js.snap +0 -53
  206. package/Components/RouteManager/__tests__/__snapshots__/testId.test.js.snap +0 -17
  207. package/Components/ScreenResolver/__tests__/__snapshots__/screenResolver.test.js.snap +0 -17
  208. package/Components/ZappUIComponent/__tests__/__snapshots__/ZappUIComponent.test.js.snap +0 -91
  209. package/Components/default-cell-renderer/__tests__/__snapshots__/defaultCellRenderer.test.tsx.snap +0 -338
  210. package/Decorators/Navigator/__tests__/__snapshots__/navigator.test.js.snap +0 -18
  211. package/Decorators/RiverFeedLoader/utils.ts +0 -100
  212. package/Decorators/RiverResolver/__tests__/__snapshots__/riverResolver.test.tsx.snap +0 -28
@@ -1,50 +1,86 @@
1
1
  import * as React from "react";
2
- import * as R from "ramda";
3
-
4
- const allTrue = R.all(R.equals(true));
5
- const anyFalse = R.any(R.equals(false));
6
- const anyTrue = R.any(R.equals(true));
2
+ import { isNil, set, lensIndex, T, slice } from "ramda";
3
+ import { BehaviorSubject } from "rxjs";
4
+ import { useRefWithInitialValue } from "@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue";
7
5
 
8
6
  const reducer = (state, { payload }) => {
9
- if (!R.isNil(payload) && !state[payload]) {
10
- return R.set(R.lensIndex(payload), true)(state);
7
+ if (!isNil(payload) && !state[payload]) {
8
+ return set(lensIndex(payload), true)(state);
11
9
  }
12
10
 
13
11
  return state;
14
12
  };
15
13
 
16
- type Return = {
17
- isAnyLoading: boolean;
18
- isAllLoaded: boolean;
14
+ type LoadingState = {
15
+ index: number;
16
+ done: boolean;
19
17
  waitForAllComponents: boolean;
18
+ };
19
+
20
+ type Return = {
21
+ loadingState: BehaviorSubject<LoadingState>;
20
22
  onLoadFinished: (index: number) => void;
21
23
  onLoadFailed: ({ error, index }: { error: Error; index: number }) => void;
22
24
  shouldShowLoadingError: boolean;
23
- isAnyLoaded: boolean;
24
25
  arePreviousComponentsLoaded: (index: number) => boolean;
25
26
  };
26
27
 
27
- type Action = { payload: { index: number } };
28
-
29
- type Loaded = true;
30
- type Loading = false;
31
-
32
- type LoadingState = Array<Loaded | Loading>;
33
-
34
28
  // TODO: Take this value from Zapp configuration, when feature is added to GeneralScreen
35
29
  const SHOULD_FAIL_ON_COMPONENT_LOADING = false;
36
30
 
37
- export const useLoadingState = (count: number): Return => {
31
+ const createLoadingStateObservable = (count: number) =>
32
+ new BehaviorSubject<LoadingState>({
33
+ index: -1,
34
+ done: count === 0,
35
+ waitForAllComponents: SHOULD_FAIL_ON_COMPONENT_LOADING,
36
+ });
37
+
38
+ export const useLoadingState = (
39
+ count: number,
40
+ onLoadDone: () => void
41
+ ): Return => {
42
+ const componentStateRef = React.useRef(new Array(count).fill(false));
38
43
  const [loadingError, setLoadingError] = React.useState(null);
39
44
 
40
- const [componentsState, dispatch] = React.useReducer<
41
- React.Reducer<LoadingState, Action>
42
- >(reducer, new Array(count).fill(false));
45
+ const loadingState = useRefWithInitialValue<BehaviorSubject<LoadingState>>(
46
+ () => createLoadingStateObservable(count)
47
+ );
48
+
49
+ const arePreviousComponentsLoaded = React.useCallback((index) => {
50
+ if (index === 0) {
51
+ return true;
52
+ }
43
53
 
44
- const handleComponentLoaded = React.useCallback((index) => {
45
- dispatch({ payload: index });
54
+ const componentsBefore = slice(0, index, componentStateRef.current);
55
+
56
+ return componentsBefore.every(T);
46
57
  }, []);
47
58
 
59
+ const dispatch = React.useCallback(({ payload }) => {
60
+ const newState = reducer(componentStateRef.current, { payload });
61
+ componentStateRef.current = newState;
62
+ const isDone = arePreviousComponentsLoaded(count - 1);
63
+
64
+ const state = loadingState.current.getValue();
65
+
66
+ const newLoadingState = {
67
+ ...state,
68
+ index: state.index < payload ? payload : state.index,
69
+ done: isDone,
70
+ };
71
+
72
+ loadingState.current.next(newLoadingState);
73
+
74
+ if (isDone) {
75
+ onLoadDone();
76
+ }
77
+ }, []);
78
+
79
+ const handleComponentLoaded = React.useCallback(
80
+ (index) => dispatch({ payload: index }),
81
+ []
82
+ );
83
+
48
84
  const handleComponentLoadErrorWhenNeedToFail = React.useCallback(
49
85
  ({ error }) => {
50
86
  if (error !== loadingError) {
@@ -55,35 +91,26 @@ export const useLoadingState = (count: number): Return => {
55
91
  );
56
92
 
57
93
  const handleComponentLoadErrorWhenNoNeedToFail = React.useCallback(
58
- ({ index }) => {
59
- handleComponentLoaded(index);
60
- },
94
+ ({ index }) => handleComponentLoaded(index),
61
95
  []
62
96
  );
63
97
 
64
- const arePreviousComponentsLoaded = React.useCallback(
65
- (index) => {
66
- if (index === 0) {
67
- return true;
68
- }
69
-
70
- const componentsBefore = R.slice(0, index, componentsState);
71
-
72
- return allTrue(componentsBefore);
73
- },
74
- [componentsState]
98
+ return React.useMemo(
99
+ () => ({
100
+ loadingState: loadingState.current,
101
+ onLoadFinished: handleComponentLoaded,
102
+ onLoadFailed: SHOULD_FAIL_ON_COMPONENT_LOADING
103
+ ? handleComponentLoadErrorWhenNeedToFail
104
+ : handleComponentLoadErrorWhenNoNeedToFail,
105
+ shouldShowLoadingError: SHOULD_FAIL_ON_COMPONENT_LOADING && loadingError,
106
+ arePreviousComponentsLoaded,
107
+ }),
108
+ [
109
+ loadingError,
110
+ handleComponentLoaded,
111
+ handleComponentLoadErrorWhenNeedToFail,
112
+ handleComponentLoadErrorWhenNoNeedToFail,
113
+ arePreviousComponentsLoaded,
114
+ ]
75
115
  );
76
-
77
- return {
78
- isAnyLoading: anyFalse(componentsState),
79
- isAllLoaded: allTrue(componentsState),
80
- onLoadFinished: handleComponentLoaded,
81
- onLoadFailed: SHOULD_FAIL_ON_COMPONENT_LOADING
82
- ? handleComponentLoadErrorWhenNeedToFail
83
- : handleComponentLoadErrorWhenNoNeedToFail,
84
- shouldShowLoadingError: SHOULD_FAIL_ON_COMPONENT_LOADING && loadingError,
85
- isAnyLoaded: anyTrue(componentsState),
86
- waitForAllComponents: SHOULD_FAIL_ON_COMPONENT_LOADING,
87
- arePreviousComponentsLoaded,
88
- };
89
116
  };
@@ -9,7 +9,7 @@ import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
9
9
  import { useLocalizedStrings } from "@applicaster/zapp-react-native-utils/localizationUtils";
10
10
  import { useAnalytics } from "@applicaster/zapp-react-native-utils/analyticsUtils";
11
11
  import { useSendAnalyticsEventWithFunction } from "@applicaster/zapp-react-native-utils/analyticsUtils/helpers/hooks";
12
- import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
12
+ import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useCurrentScreenData";
13
13
  import { loadPipesData } from "@applicaster/zapp-react-native-redux/ZappPipes";
14
14
  import { useDispatch } from "react-redux";
15
15
  import { useShallow } from "zustand/react/shallow";
@@ -1,11 +1,23 @@
1
- import React from "react";
1
+ import React, { useCallback } from "react";
2
2
  import { StyleSheet, View } from "react-native";
3
3
  import { Spinner } from "@applicaster/zapp-react-native-ui-components/Components/Spinner";
4
+ import type { Subject } from "rxjs";
5
+ import { useStateFromSubscribe } from "@applicaster/zapp-react-native-utils/reactHooks/state/useStateFromSubscribe";
6
+
7
+ type LoadingState = {
8
+ waitForAllComponents: boolean;
9
+ index: number;
10
+ done: boolean;
11
+ };
12
+
13
+ type State = {
14
+ visible: boolean;
15
+ isAnyLoaded: boolean;
16
+ };
4
17
 
5
18
  type Props = {
6
- visible?: boolean;
7
19
  flatListHeight?: number;
8
- isAnyLoaded: boolean;
20
+ loadingState: Subject<LoadingState>;
9
21
  };
10
22
 
11
23
  const FOOTER_COMPONENT_HEIGHT = 200;
@@ -19,17 +31,35 @@ const footerStyles = StyleSheet.create({
19
31
  });
20
32
 
21
33
  function RiverFooterComponent(props: Props) {
22
- const { visible = true, flatListHeight, isAnyLoaded } = props;
34
+ const { flatListHeight, loadingState } = props;
35
+
36
+ const { visible, isAnyLoaded } = useStateFromSubscribe<LoadingState, State>(
37
+ loadingState,
38
+ useCallback(
39
+ ({ index, done, waitForAllComponents }, setState) =>
40
+ setState(() => ({
41
+ visible: !done,
42
+ isAnyLoaded: index >= 0 || waitForAllComponents,
43
+ })),
44
+ []
45
+ ),
46
+ {
47
+ visible: true,
48
+ isAnyLoaded: false,
49
+ }
50
+ );
23
51
 
24
52
  if (!visible) return null;
25
53
 
26
54
  return (
27
55
  <View
28
- renderToHardwareTextureAndroid={true}
29
- style={{
30
- ...footerStyles.container,
31
- height: isAnyLoaded ? FOOTER_COMPONENT_HEIGHT : flatListHeight,
32
- }}
56
+ renderToHardwareTextureAndroid
57
+ style={[
58
+ footerStyles.container,
59
+ {
60
+ height: isAnyLoaded ? FOOTER_COMPONENT_HEIGHT : flatListHeight,
61
+ },
62
+ ]}
33
63
  >
34
64
  <Spinner size={isAnyLoaded ? "small" : "large"} />
35
65
  </View>
@@ -1,5 +1,6 @@
1
- import React from "react";
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
 
@@ -11,6 +12,7 @@ import {
11
12
  import { riverLogger } from "./logger";
12
13
  import { tvPluginsWithCellRenderer } from "../../const";
13
14
  import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
15
+ import type { BehaviorSubject } from "rxjs";
14
16
 
15
17
  export type RiverItemType = {
16
18
  item: ZappUIComponent;
@@ -24,6 +26,7 @@ export type RiverItemType = {
24
26
  getStaticComponentFeed: GeneralContentScreenProps["getStaticComponentFeed"];
25
27
  readyToBeDisplayed?: boolean;
26
28
  isLast: boolean;
29
+ loadingState: BehaviorSubject<{ index: number }>;
27
30
  };
28
31
 
29
32
  function getFeedUrl(feed: ZappFeed, index: number) {
@@ -36,6 +39,33 @@ function getFeedUrl(feed: ZappFeed, index: number) {
36
39
  }
37
40
  }
38
41
 
42
+ /**
43
+ * useLoadingState for RiverItemComponent
44
+ * takes currentIndex and loadingState as arguments
45
+ **/
46
+ const useLoadingState = (
47
+ currentIndex: number,
48
+ loadingState: RiverItemType["loadingState"]
49
+ ) => {
50
+ const [readyToBeDisplayed, setReadyToBeDisplayed] = React.useState(
51
+ loadingState.getValue().index + 1 === currentIndex
52
+ );
53
+
54
+ useEffect(() => {
55
+ const subscription = loadingState.subscribe(({ index }) => {
56
+ if (index + 1 === currentIndex) {
57
+ setReadyToBeDisplayed(true);
58
+ }
59
+ });
60
+
61
+ return () => {
62
+ subscription.unsubscribe();
63
+ };
64
+ }, [loadingState, currentIndex]);
65
+
66
+ return readyToBeDisplayed;
67
+ };
68
+
39
69
  function RiverItemComponent(props: RiverItemType) {
40
70
  const {
41
71
  item,
@@ -47,10 +77,12 @@ function RiverItemComponent(props: RiverItemType) {
47
77
  onLoadFinished,
48
78
  onLoadFailed,
49
79
  getStaticComponentFeed,
50
- readyToBeDisplayed,
51
80
  isLast,
81
+ loadingState,
52
82
  } = props;
53
83
 
84
+ const readyToBeDisplayed = useLoadingState(index, loadingState);
85
+
54
86
  const feedUrl = getFeedUrl(feed, index);
55
87
 
56
88
  const Component = useComponentResolver(
@@ -81,7 +113,7 @@ function RiverItemComponent(props: RiverItemType) {
81
113
  jsOnly: true,
82
114
  });
83
115
 
84
- if (!CellRenderer && item.component_type !== "group-qb") {
116
+ if (!CellRenderer && !isGroup(item)) {
85
117
  riverLogger.warning({
86
118
  message: "Cell Renderer is null - will fallback to default cell",
87
119
  data: { item, CellRenderer },
@@ -90,6 +122,10 @@ function RiverItemComponent(props: RiverItemType) {
90
122
  }
91
123
  }, []);
92
124
 
125
+ if (!readyToBeDisplayed) {
126
+ return null;
127
+ }
128
+
93
129
  if (Component === null || typeof Component === "undefined") {
94
130
  riverLogger.warning({
95
131
  message: `Component ${item.component_type} is null - skipping rendering`,
@@ -1,4 +1,9 @@
1
+ import { compose } from "ramda";
1
2
  import { River as RiverComponent } from "./River";
2
3
  import { withTvEventHandler } from "./withTVEventHandler";
4
+ import { withComponentsMapOffsetContext } from "../../../Contexts/ComponentsMapOffsetContext";
3
5
 
4
- export const River = withTvEventHandler(RiverComponent);
6
+ export const River = compose(
7
+ withTvEventHandler,
8
+ withComponentsMapOffsetContext
9
+ )(RiverComponent);
@@ -3,7 +3,7 @@
3
3
  exports[`componentsMap renders renders components map correctly 1`] = `
4
4
  <View
5
5
  style={
6
- Object {
6
+ {
7
7
  "flex": 1,
8
8
  }
9
9
  }
@@ -11,15 +11,98 @@ exports[`componentsMap renders renders components map correctly 1`] = `
11
11
  <View
12
12
  onLayout={[Function]}
13
13
  style={
14
- Object {
14
+ {
15
15
  "flex": 1,
16
16
  }
17
17
  }
18
18
  >
19
19
  <RCTScrollView
20
- ListFooterComponent={[Function]}
20
+ ListFooterComponent={
21
+ <Memo(RiverFooterComponent)
22
+ flatListHeight={null}
23
+ loadingState={
24
+ BehaviorSubject {
25
+ "_value": {
26
+ "done": false,
27
+ "index": -1,
28
+ "waitForAllComponents": false,
29
+ },
30
+ "closed": false,
31
+ "currentObservers": null,
32
+ "hasError": false,
33
+ "isStopped": false,
34
+ "observers": [
35
+ SafeSubscriber {
36
+ "_finalizers": [
37
+ Subscription {
38
+ "_finalizers": null,
39
+ "_parentage": [Circular],
40
+ "closed": false,
41
+ "initialTeardown": [Function],
42
+ },
43
+ ],
44
+ "_parentage": null,
45
+ "closed": false,
46
+ "destination": ConsumerObserver {
47
+ "partialObserver": {
48
+ "complete": undefined,
49
+ "error": undefined,
50
+ "next": [Function],
51
+ },
52
+ },
53
+ "initialTeardown": undefined,
54
+ "isStopped": false,
55
+ },
56
+ SafeSubscriber {
57
+ "_finalizers": [
58
+ Subscription {
59
+ "_finalizers": null,
60
+ "_parentage": [Circular],
61
+ "closed": false,
62
+ "initialTeardown": [Function],
63
+ },
64
+ ],
65
+ "_parentage": null,
66
+ "closed": false,
67
+ "destination": ConsumerObserver {
68
+ "partialObserver": {
69
+ "complete": undefined,
70
+ "error": undefined,
71
+ "next": [Function],
72
+ },
73
+ },
74
+ "initialTeardown": undefined,
75
+ "isStopped": false,
76
+ },
77
+ SafeSubscriber {
78
+ "_finalizers": [
79
+ Subscription {
80
+ "_finalizers": null,
81
+ "_parentage": [Circular],
82
+ "closed": false,
83
+ "initialTeardown": [Function],
84
+ },
85
+ ],
86
+ "_parentage": null,
87
+ "closed": false,
88
+ "destination": ConsumerObserver {
89
+ "partialObserver": {
90
+ "complete": undefined,
91
+ "error": undefined,
92
+ "next": [Function],
93
+ },
94
+ },
95
+ "initialTeardown": undefined,
96
+ "isStopped": false,
97
+ },
98
+ ],
99
+ "thrownError": null,
100
+ }
101
+ }
102
+ />
103
+ }
21
104
  contentContainerStyle={
22
- Object {
105
+ {
23
106
  "paddingBottom": undefined,
24
107
  "paddingLeft": undefined,
25
108
  "paddingRight": undefined,
@@ -27,22 +110,22 @@ exports[`componentsMap renders renders components map correctly 1`] = `
27
110
  }
28
111
  }
29
112
  data={
30
- Array [
31
- Object {
113
+ [
114
+ {
32
115
  "component_type": "hero",
33
116
  "id": "A1",
34
- "styles": Object {
35
- "cell_styles": Array [
117
+ "styles": {
118
+ "cell_styles": [
36
119
  "some",
37
120
  "obsolete",
38
121
  "ids",
39
122
  ],
40
123
  },
41
124
  },
42
- Object {
125
+ {
43
126
  "component_type": "grid",
44
127
  "id": "A2",
45
- "styles": Object {
128
+ "styles": {
46
129
  "master_cell_id": "uuid-5678-B",
47
130
  },
48
131
  },
@@ -66,12 +149,12 @@ exports[`componentsMap renders renders components map correctly 1`] = `
66
149
  renderItem={[Function]}
67
150
  scrollEventThrottle={16}
68
151
  scrollIndicatorInsets={
69
- Object {
152
+ {
70
153
  "right": 1,
71
154
  }
72
155
  }
73
- stickyHeaderIndices={Array []}
74
- viewabilityConfigCallbackPairs={Array []}
156
+ stickyHeaderIndices={[]}
157
+ viewabilityConfigCallbackPairs={[]}
75
158
  windowSize={12}
76
159
  >
77
160
  <View>
@@ -80,22 +163,14 @@ exports[`componentsMap renders renders components map correctly 1`] = `
80
163
  style={null}
81
164
  >
82
165
  <View
166
+ onLayout={[Function]}
83
167
  style={
84
- Object {
85
- "display": "flex",
168
+ {
169
+ "flex": 1,
86
170
  }
87
171
  }
88
172
  >
89
- <View
90
- onLayout={[Function]}
91
- style={
92
- Object {
93
- "flex": 1,
94
- }
95
- }
96
- >
97
- <View />
98
- </View>
173
+ <View />
99
174
  </View>
100
175
  </View>
101
176
  <View
@@ -103,23 +178,13 @@ exports[`componentsMap renders renders components map correctly 1`] = `
103
178
  style={null}
104
179
  >
105
180
  <View
181
+ onLayout={[Function]}
106
182
  style={
107
- Object {
108
- "display": "none",
183
+ {
184
+ "flex": 1,
109
185
  }
110
186
  }
111
- >
112
- <View
113
- onLayout={[Function]}
114
- style={
115
- Object {
116
- "flex": 1,
117
- }
118
- }
119
- >
120
- <View />
121
- </View>
122
- </View>
187
+ />
123
188
  </View>
124
189
  <View
125
190
  onLayout={[Function]}
@@ -127,12 +192,16 @@ exports[`componentsMap renders renders components map correctly 1`] = `
127
192
  <View
128
193
  renderToHardwareTextureAndroid={true}
129
194
  style={
130
- Object {
131
- "alignItems": "center",
132
- "height": null,
133
- "justifyContent": "center",
134
- "width": "100%",
135
- }
195
+ [
196
+ {
197
+ "alignItems": "center",
198
+ "justifyContent": "center",
199
+ "width": "100%",
200
+ },
201
+ {
202
+ "height": null,
203
+ },
204
+ ]
136
205
  }
137
206
  >
138
207
  <ActivityIndicator
@@ -1,89 +1,27 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`When River has a general_content type <River /> renders correctly 1`] = `
4
- <ContextProvider
5
- value={null}
6
- >
7
- <RiverWithData
8
- appData={
9
- Object {
10
- "layoutVersion": "v1",
11
- }
12
- }
13
- dispatch={[Function]}
14
- rivers={
15
- Object {
16
- "A1234": Object {
17
- "home": true,
18
- "id": "A1234",
19
- "name": "foo",
20
- "type": "general_content",
21
- "ui_components": Array [
22
- Object {
23
- "component_type": "hero",
24
- },
25
- Object {
26
- "component_type": "grid",
27
- },
28
- ],
29
- },
30
- "B4567": Object {
31
- "id": "B4567",
32
- },
33
- "C0987": Object {
34
- "home": false,
35
- "id": "C0987",
36
- "name": "Some-Screen-Plugin",
37
- "type": "some-screen-plugin",
38
- "ui_components": Array [],
39
- },
40
- }
41
- }
42
- screenId="A1234"
43
- store={
44
- Object {
45
- "clearActions": [Function],
46
- "dispatch": [Function],
47
- "getActions": [Function],
48
- "getState": [Function],
49
- "replaceReducer": [Function],
50
- "subscribe": [Function],
51
- }
52
- }
53
- />
54
- </ContextProvider>
55
- `;
56
-
57
- exports[`When River has a general_content type <RiverComponent /> renders correctly 1`] = `
58
- <GeneralContentScreen
59
- groupId="ZF-C4"
60
- screenId="A1234"
61
- />
62
- `;
63
-
64
- exports[`When River has any other type other than general_content <RiverComponent /> renders correctly 1`] = `
65
- <WithProvider
66
- screenData={
67
- Object {
68
- "groupId": undefined,
69
- "home": false,
70
- "id": "C0987",
71
- "name": "Some-Screen-Plugin",
72
- "type": "some-screen-plugin",
73
- "ui_components": Array [],
3
+ exports[`When River has a general_content type renders River component correctly 1`] = `
4
+ <View
5
+ onLayout={[Function]}
6
+ style={
7
+ {
8
+ "flex": 1,
74
9
  }
75
10
  }
76
- screenId="C0987"
77
- screenType="some-screen-plugin"
78
- />
79
- `;
80
-
81
- exports[`When River has feed url <RiverComponent /> renders correctly 1`] = `
82
- <Connect(FeedLoaderComponent)
83
- feedUrl="https://some-feed-url.net"
84
- refreshCallback={[Function]}
85
- refreshing={false}
11
+ testID="on-layout-view"
86
12
  >
87
- <Component />
88
- </Connect(FeedLoaderComponent)>
13
+ <View
14
+ style={
15
+ {
16
+ "display": "none",
17
+ "flex": 1,
18
+ }
19
+ }
20
+ >
21
+ <View
22
+ screenId="A1234"
23
+ testID="general-content-screen"
24
+ />
25
+ </View>
26
+ </View>
89
27
  `;