@applicaster/zapp-react-native-ui-components 15.1.0-rc.9 → 16.0.0-alpha.1833861900

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 (155) hide show
  1. package/Components/BackgroundImage/BackgroundImage.tsx +42 -0
  2. package/Components/BackgroundImage/BackgroundImage.tv.android.tsx +28 -0
  3. package/Components/BackgroundImage/BackgroundImage.tv.ios.tsx +24 -0
  4. package/Components/BackgroundImage/index.ts +1 -0
  5. package/Components/BaseFocusable/index.ios.ts +12 -2
  6. package/Components/Cell/FocusableWrapper.tsx +3 -0
  7. package/Components/Cell/TvOSCellComponent.tsx +6 -3
  8. package/Components/Focusable/Focusable.tsx +4 -2
  9. package/Components/Focusable/FocusableTvOS.tsx +18 -1
  10. package/Components/Focusable/__tests__/__snapshots__/FocusableTvOS.test.tsx.snap +1 -0
  11. package/Components/FocusableGroup/FocusableTvOS.tsx +41 -8
  12. package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +1 -1
  13. package/Components/HandlePlayable/HandlePlayable.tsx +13 -8
  14. package/Components/Layout/TV/NavBarContainer.tsx +1 -10
  15. package/Components/Layout/TV/ScreenContainer.tsx +2 -6
  16. package/Components/Layout/TV/__tests__/__snapshots__/NavBarContainer.test.tsx.snap +7 -12
  17. package/Components/Layout/TV/__tests__/__snapshots__/ScreenContainer.test.tsx.snap +7 -12
  18. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +0 -1
  19. package/Components/Layout/TV/index.tsx +5 -7
  20. package/Components/Layout/TV/index.web.tsx +5 -7
  21. package/Components/LinkHandler/LinkHandler.tsx +2 -2
  22. package/Components/MasterCell/CONFIG_BUILDER_TO_REACT_COMPONENT.md +144 -0
  23. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +16 -5
  24. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/model.test.ts +80 -0
  25. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/placement.test.ts +187 -0
  26. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/selectors.test.ts +45 -0
  27. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/__tests__/style.test.ts +49 -0
  28. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/ActionButtonController.tsx +165 -0
  29. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/__tests__/ActionButtonController.test.tsx +405 -0
  30. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/components/index.ts +1 -0
  31. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/model.ts +47 -0
  32. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/placement.ts +170 -0
  33. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/selectors.ts +26 -0
  34. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/style.ts +29 -0
  35. package/Components/MasterCell/DefaultComponents/ActionButtonsCore/types.ts +37 -0
  36. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -10
  37. package/Components/MasterCell/DefaultComponents/Button.tsx +0 -15
  38. package/Components/MasterCell/DefaultComponents/ButtonContainerView/components/HorizontalSeparator.tsx +8 -0
  39. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tsx +15 -0
  40. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.tv.android.tsx +58 -0
  41. package/Components/MasterCell/DefaultComponents/{tv/ButtonContainerView/index.tsx → ButtonContainerView/index.tv.tsx} +3 -11
  42. package/Components/MasterCell/DefaultComponents/ButtonContainerView/index.web.ts +1 -0
  43. package/Components/MasterCell/DefaultComponents/ButtonContainerView/types.ts +40 -0
  44. package/Components/MasterCell/DefaultComponents/DataProvider/index.tsx +163 -0
  45. package/Components/MasterCell/DefaultComponents/FocusableView/index.android.tsx +2 -23
  46. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +4 -22
  47. package/Components/MasterCell/DefaultComponents/Image/Image.android.tsx +8 -2
  48. package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +11 -3
  49. package/Components/MasterCell/DefaultComponents/Image/Image.web.tsx +9 -1
  50. package/Components/MasterCell/DefaultComponents/Image/hooks/useImage.ts +15 -14
  51. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +1 -2
  52. package/Components/MasterCell/DefaultComponents/PressableView.tsx +34 -0
  53. package/Components/MasterCell/DefaultComponents/SecondaryImage/hooks/__tests__/useGetImageDimensions.test.ts +7 -6
  54. package/Components/MasterCell/DefaultComponents/Text/hooks/useText.ts +11 -0
  55. package/Components/MasterCell/DefaultComponents/__tests__/DataProvider.test.tsx +141 -0
  56. package/Components/MasterCell/DefaultComponents/index.ts +9 -3
  57. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/ActionButton.tsx +135 -0
  58. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Asset.ts +33 -0
  59. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/AssetComponent.tsx +22 -0
  60. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Button.ts +125 -0
  61. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/Spacer.ts +16 -0
  62. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabel.ts +67 -0
  63. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/TextLabelsContainer.ts +37 -0
  64. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/PressableView.test.tsx +393 -0
  65. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/builders.test.ts +141 -0
  66. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/__tests__/index.test.ts +343 -0
  67. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/helpers.ts +105 -0
  68. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/index.ts +122 -0
  69. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/__tests__/insertButtons.test.ts +118 -0
  70. package/Components/MasterCell/DefaultComponents/mobile/MobileActionButtons/utils/index.ts +238 -0
  71. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Asset.ts +4 -18
  72. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/Button.ts +24 -73
  73. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TextLabelsContainer.ts +37 -18
  74. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/TvActionButton.tsx +27 -0
  75. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/index.test.ts +89 -0
  76. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/__tests__/renderedTree.test.tsx +231 -0
  77. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/index.ts +47 -48
  78. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/__tests__/getPluginIdentifier.test.ts +115 -29
  79. package/Components/MasterCell/DefaultComponents/tv/TvActionButtons/utils/index.ts +101 -144
  80. package/Components/MasterCell/MappingFunctions/index.js +3 -2
  81. package/Components/MasterCell/README.md +4 -0
  82. package/Components/MasterCell/__tests__/__snapshots__/dataAdapter.test.js.snap +24 -0
  83. package/Components/MasterCell/__tests__/configInflater.test.js +1 -0
  84. package/Components/MasterCell/__tests__/elementMapper.test.js +46 -0
  85. package/Components/MasterCell/dataAdapter.ts +4 -1
  86. package/Components/MasterCell/elementMapper.tsx +52 -7
  87. package/Components/MasterCell/utils/__tests__/cloneChildrenWithIds.test.tsx +43 -0
  88. package/Components/MasterCell/utils/__tests__/useFilterChildren.test.tsx +80 -0
  89. package/Components/MasterCell/utils/index.ts +85 -15
  90. package/Components/OfflineHandler/NotificationView/NotificationView.tsx +2 -2
  91. package/Components/OfflineHandler/NotificationView/__tests__/index.test.tsx +17 -18
  92. package/Components/OfflineHandler/__tests__/index.test.tsx +27 -18
  93. package/Components/PlayerContainer/PlayerContainer.tsx +8 -5
  94. package/Components/PlayerContainer/__tests__/PlayerContainer.test.tsx +284 -0
  95. package/Components/River/ComponentsMap/ComponentsMap.tsx +6 -19
  96. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +1 -1
  97. package/Components/River/RefreshControl.tsx +19 -88
  98. package/Components/River/River.tsx +9 -82
  99. package/Components/River/TV/River.tsx +31 -14
  100. package/Components/River/TV/index.tsx +8 -4
  101. package/Components/River/TV/utils/__tests__/toStringOrEmpty.test.ts +30 -0
  102. package/Components/River/TV/utils/index.ts +4 -0
  103. package/Components/River/TV/withFocusableGroupForContent.tsx +71 -0
  104. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -0
  105. package/Components/River/__tests__/componentsMap.test.js +38 -0
  106. package/Components/River/hooks/__tests__/usePullToRefresh.test.ts +132 -0
  107. package/Components/River/hooks/index.ts +1 -0
  108. package/Components/River/hooks/usePullToRefresh.ts +51 -0
  109. package/Components/Screen/TV/index.web.tsx +4 -2
  110. package/Components/Screen/__tests__/Screen.test.tsx +65 -42
  111. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +68 -44
  112. package/Components/Screen/hooks.ts +2 -3
  113. package/Components/Screen/index.tsx +2 -3
  114. package/Components/Screen/orientationHandler.ts +3 -3
  115. package/Components/ScreenResolver/index.tsx +9 -5
  116. package/Components/ScreenRevealManager/Overlay.tsx +34 -0
  117. package/Components/ScreenRevealManager/ScreenRevealManager.ts +40 -8
  118. package/Components/ScreenRevealManager/__tests__/Overlay.test.tsx +88 -0
  119. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +86 -69
  120. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +9 -20
  121. package/Components/Tabs/TabContent.tsx +7 -4
  122. package/Components/TopCutoffOverlay/__tests__/TopCutoffOverlay.test.tsx +201 -0
  123. package/Components/TopCutoffOverlay/hooks/__tests__/useMarginTop.test.ts +130 -0
  124. package/Components/TopCutoffOverlay/hooks/index.ts +1 -0
  125. package/Components/TopCutoffOverlay/hooks/useMarginTop.ts +59 -0
  126. package/Components/TopCutoffOverlay/index.tsx +55 -0
  127. package/Components/Transitioner/index.js +3 -3
  128. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +5 -5
  129. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +15 -7
  130. package/Components/VideoModal/utils.ts +12 -10
  131. package/Components/Viewport/ViewportAware/__tests__/viewportAware.test.js +0 -2
  132. package/Components/Viewport/ViewportAware/index.tsx +16 -7
  133. package/Components/Viewport/ViewportEvents/__tests__/viewportEvents.test.js +1 -1
  134. package/Components/ZappFrameworkComponents/BarView/BarView.tsx +4 -6
  135. package/Components/ZappFrameworkComponents/BarView/__tests__/BarView.test.tsx +2 -2
  136. package/Components/default-cell-renderer/viewTrees/mobile/index.ts +0 -3
  137. package/Contexts/ScreenContext/index.tsx +25 -18
  138. package/Contexts/ScreenTrackedViewPositionsContext/__tests__/index.test.tsx +1 -1
  139. package/Decorators/Analytics/index.tsx +6 -5
  140. package/Decorators/ConfigurationWrapper/__tests__/__snapshots__/withConfigurationProvider.test.tsx.snap +1 -0
  141. package/Decorators/ConfigurationWrapper/const.ts +1 -0
  142. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +39 -21
  143. package/Decorators/ZappPipesDataConnector/__tests__/zappPipesDataConnector.test.js +1 -1
  144. package/Decorators/ZappPipesDataConnector/index.tsx +2 -2
  145. package/Decorators/ZappPipesDataConnector/resolvers/StaticFeedResolver.tsx +1 -1
  146. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +18 -7
  147. package/Helpers/DataSourceHelper/__tests__/itemLimitForData.test.ts +80 -0
  148. package/Helpers/DataSourceHelper/index.ts +19 -0
  149. package/Helpers/index.js +7 -1
  150. package/package.json +5 -5
  151. package/Components/Layout/TV/LayoutBackground.tsx +0 -28
  152. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/index.android.tsx +0 -135
  153. package/Components/MasterCell/DefaultComponents/tv/ButtonContainerView/types.ts +0 -25
  154. package/Components/River/TV/withTVEventHandler.tsx +0 -36
  155. package/Helpers/DataSourceHelper/index.js +0 -19
@@ -0,0 +1,284 @@
1
+ import * as React from "react";
2
+ import { render } from "@testing-library/react-native";
3
+
4
+ jest.mock(
5
+ "@applicaster/zapp-react-native-utils/appUtils/playerManager",
6
+ () => ({
7
+ playerManager: {
8
+ invokeHandler: jest.fn(),
9
+ getPluginConfiguration: jest.fn(() => ({})),
10
+ isRegistered: jest.fn(() => true),
11
+ on: jest.fn().mockReturnThis(),
12
+ removeHandler: jest.fn().mockReturnThis(),
13
+ getActivePlayer: jest.fn(() => null),
14
+ closeNativePlayer: jest.fn(),
15
+ },
16
+ })
17
+ );
18
+
19
+ jest.mock("@applicaster/zapp-react-native-utils/reactUtils", () => ({
20
+ isTV: jest.fn(() => false),
21
+ isAndroidTVPlatform: jest.fn(() => false),
22
+ isTvOSPlatform: jest.fn(() => false),
23
+ platformSelect: jest.fn(({ native }) => native),
24
+ }));
25
+
26
+ jest.mock("@applicaster/zapp-react-native-utils/playerUtils", () => ({
27
+ isAudioItem: jest.fn(() => false),
28
+ isInlineTV: jest.fn(() => false),
29
+ }));
30
+
31
+ jest.mock(
32
+ "@applicaster/zapp-react-native-tvos-ui-components/Components/TVEventHandlerComponent",
33
+ () => ({
34
+ TVEventHandlerComponent: ({ children }) => children,
35
+ })
36
+ );
37
+
38
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/utils", () => ({
39
+ usePrevious: jest.fn(),
40
+ }));
41
+
42
+ jest.mock("@applicaster/zapp-react-native-utils/reactHooks", () => {
43
+ const navigator = {
44
+ closeVideoModal: jest.fn(),
45
+ minimiseVideoModal: jest.fn(),
46
+ maximiseVideoModal: jest.fn(),
47
+ fullscreenVideoModal: jest.fn(),
48
+ isVideoModalDocked: jest.fn(() => false),
49
+ goBack: jest.fn(),
50
+ replaceTop: jest.fn(),
51
+ push: jest.fn(),
52
+ setPlayNextOverlay: jest.fn(),
53
+ currentRoute: "/playable/entry-1",
54
+ };
55
+
56
+ const backHandlerRef: { current: (() => boolean) | null } = {
57
+ current: null,
58
+ };
59
+
60
+ return {
61
+ useBackHandler: jest.fn((cb) => {
62
+ backHandlerRef.current = cb;
63
+ }),
64
+ useNavigation: jest.fn(() => navigator),
65
+ __navigator: navigator,
66
+ __backHandlerRef: backHandlerRef,
67
+ };
68
+ });
69
+
70
+ jest.mock("@applicaster/zapp-react-native-bridge/QuickBrick", () => ({
71
+ QUICK_BRICK_EVENTS: {
72
+ IDLE_TIMER_DISABLED: "IDLE_TIMER_DISABLED",
73
+ MOVE_APP_TO_BACKGROUND: "MOVE_APP_TO_BACKGROUND",
74
+ },
75
+ sendQuickBrickEvent: jest.fn(),
76
+ }));
77
+
78
+ jest.mock("../ProgramInfo", () => ({
79
+ ProgramInfo: () => null,
80
+ }));
81
+
82
+ jest.mock("../../AudioPlayer", () => ({
83
+ AudioPlayer: () => null,
84
+ }));
85
+
86
+ jest.mock("../logger", () => ({
87
+ log_debug: jest.fn(),
88
+ log_info: jest.fn(),
89
+ log_warning: jest.fn(),
90
+ playerContainerLogger: { error: jest.fn() },
91
+ }));
92
+
93
+ jest.mock(
94
+ "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer",
95
+ () => {
96
+ const player = {
97
+ addListener: jest.fn(),
98
+ removeListener: jest.fn(),
99
+ isPaused: jest.fn(() => false),
100
+ isAd: jest.fn(() => false),
101
+ seekTo: jest.fn(),
102
+ getPluginConfiguration: jest.fn(() => ({})),
103
+ getOverlayObservable: jest.fn(() => ({ getPlayNextEntry: () => null })),
104
+ };
105
+
106
+ return {
107
+ usePlayer: jest.fn(() => player),
108
+ __player: player,
109
+ };
110
+ }
111
+ );
112
+
113
+ jest.mock(
114
+ "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayNextOverlay",
115
+ () => ({
116
+ usePlayNextOverlay: jest.fn(() => null),
117
+ })
118
+ );
119
+
120
+ jest.mock(
121
+ "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerNativeCommand",
122
+ () => ({
123
+ PlayerNativeCommandTypes: { clearPlayerData: "clearPlayerData" },
124
+ PlayerNativeSendCommand: jest.fn(),
125
+ })
126
+ );
127
+
128
+ jest.mock(
129
+ "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext",
130
+ () => ({
131
+ useSetNavbarState: jest.fn(() => ({ setVisible: jest.fn() })),
132
+ })
133
+ );
134
+
135
+ jest.mock(
136
+ "@applicaster/zapp-react-native-utils/reactHooks/screen/useTargetScreenData",
137
+ () => ({
138
+ useTargetScreenData: jest.fn(() => ({ id: "screen-id", styles: {} })),
139
+ })
140
+ );
141
+
142
+ jest.mock("../PlayerContainerContext", () => {
143
+ const ReactActual = require("react");
144
+
145
+ return {
146
+ PlayerContainerContext: ReactActual.createContext({
147
+ isLanguageOverlayVisible: false,
148
+ bottomFocusableId: "bottom",
149
+ showComponentsContainer: false,
150
+ refs: null,
151
+ }),
152
+ PlayerContainerContextProvider: ({ children }) => children,
153
+ };
154
+ });
155
+
156
+ jest.mock(
157
+ "@applicaster/zapp-react-native-ui-components/Components/FocusableGroup",
158
+ () => ({
159
+ FocusableGroup: ({ children }) => children,
160
+ })
161
+ );
162
+
163
+ jest.mock("../WappersView/PlayerFocusableWrapperView", () => ({
164
+ PlayerFocusableWrapperView: ({ children }) => children,
165
+ }));
166
+
167
+ jest.mock("../WappersView/ComponentFocusableWrapperView", () => ({
168
+ ComponentFocusableWrapperView: () => null,
169
+ }));
170
+
171
+ jest.mock("../index", () => ({
172
+ FocusableGroupMainContainerId: "player-container-general",
173
+ }));
174
+
175
+ jest.mock(
176
+ "@applicaster/zapp-react-native-utils/navigationUtils/itemTypeMatchers",
177
+ () => ({
178
+ isPlayable: jest.fn(() => true),
179
+ })
180
+ );
181
+
182
+ jest.mock("../../GeneralContentScreen", () => ({
183
+ GeneralContentScreen: () => null,
184
+ }));
185
+
186
+ jest.mock("@applicaster/zapp-react-native-redux", () => ({
187
+ useAppData: jest.fn(() => ({ isTabletPortrait: false })),
188
+ }));
189
+
190
+ import { PlayerContainer, VideoModalMode } from "../PlayerContainer";
191
+
192
+ const { __navigator: mockNavigator, __backHandlerRef: mockBackHandlerRef } =
193
+ jest.requireMock("@applicaster/zapp-react-native-utils/reactHooks");
194
+
195
+ const { playerManager: mockPlayerManager } = jest.requireMock(
196
+ "@applicaster/zapp-react-native-utils/appUtils/playerManager"
197
+ );
198
+
199
+ const { __player: mockPlayer } = jest.requireMock(
200
+ "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer"
201
+ );
202
+
203
+ const Player = React.forwardRef(() => null);
204
+
205
+ const item = {
206
+ id: "entry-1",
207
+ title: "Test entry",
208
+ summary: "",
209
+ content: { src: "https://example.com/video.m3u8" },
210
+ extensions: {},
211
+ } as any;
212
+
213
+ const renderPlayerContainer = (props = {}) =>
214
+ render(
215
+ <PlayerContainer
216
+ Player={Player}
217
+ item={item}
218
+ style={{}}
219
+ loadPipesData={jest.fn()}
220
+ isModal={true}
221
+ mode={VideoModalMode.MAXIMIZED}
222
+ {...props}
223
+ />
224
+ );
225
+
226
+ const pressHardwareBack = () => {
227
+ if (!mockBackHandlerRef.current) {
228
+ throw new Error("back handler was not registered via useBackHandler");
229
+ }
230
+
231
+ return mockBackHandlerRef.current();
232
+ };
233
+
234
+ describe("PlayerContainer hardware back handling", () => {
235
+ beforeEach(() => {
236
+ jest.clearAllMocks();
237
+ mockBackHandlerRef.current = null;
238
+ mockPlayer.getPluginConfiguration.mockReturnValue({});
239
+ mockPlayer.isPaused.mockReturnValue(false);
240
+ mockPlayer.isAd.mockReturnValue(false);
241
+
242
+ mockPlayer.getOverlayObservable.mockReturnValue({
243
+ getPlayNextEntry: () => null,
244
+ });
245
+
246
+ mockPlayerManager.getPluginConfiguration.mockReturnValue({});
247
+ mockPlayerManager.on.mockReturnThis();
248
+ mockPlayerManager.removeHandler.mockReturnThis();
249
+ });
250
+
251
+ it("minimises the video modal on back press when mini player is enabled", () => {
252
+ renderPlayerContainer();
253
+
254
+ const handled = pressHardwareBack();
255
+
256
+ expect(mockNavigator.minimiseVideoModal).toHaveBeenCalled();
257
+ expect(mockNavigator.closeVideoModal).not.toHaveBeenCalled();
258
+ expect(handled).toBe(true);
259
+ });
260
+
261
+ it("closes the video modal on back press when mini player is disabled", () => {
262
+ mockPlayer.getPluginConfiguration.mockReturnValue({
263
+ disable_mini_player_when_inline: true,
264
+ });
265
+
266
+ renderPlayerContainer();
267
+
268
+ const handled = pressHardwareBack();
269
+
270
+ expect(mockNavigator.closeVideoModal).toHaveBeenCalled();
271
+ expect(mockNavigator.minimiseVideoModal).not.toHaveBeenCalled();
272
+ expect(handled).toBe(true);
273
+ });
274
+
275
+ it("does not handle back press when the player is already minimised", () => {
276
+ renderPlayerContainer({ mode: VideoModalMode.MINIMIZED });
277
+
278
+ const handled = pressHardwareBack();
279
+
280
+ expect(handled).toBe(false);
281
+ expect(mockNavigator.minimiseVideoModal).not.toHaveBeenCalled();
282
+ expect(mockNavigator.closeVideoModal).not.toHaveBeenCalled();
283
+ });
284
+ });
@@ -39,8 +39,6 @@ type Props = {
39
39
  scrollViewExtraProps?: {};
40
40
  riverId?: string;
41
41
  getStaticComponentFeed: any;
42
- pullToRefreshPipesV1RefreshingStateUpdater: () => boolean;
43
- refreshingPipesV1?: boolean;
44
42
  stickyHeaderIndices?: number[];
45
43
  };
46
44
 
@@ -65,10 +63,6 @@ function ComponentsMapComponent(props: Props) {
65
63
  groupId,
66
64
  riverId,
67
65
  getStaticComponentFeed,
68
- // Method added to keep pipes v1 logic up to date with the pullToRefresh state.
69
- // TODO: Remove when pipes v1 is deprecated.
70
- pullToRefreshPipesV1RefreshingStateUpdater,
71
- refreshingPipesV1,
72
66
  stickyHeaderIndices,
73
67
  } = props;
74
68
 
@@ -163,16 +157,8 @@ function ComponentsMapComponent(props: Props) {
163
157
  usePipesCacheReset(riverId, riverComponents);
164
158
 
165
159
  const refreshControl = React.useMemo(
166
- () =>
167
- pullToRefreshEnabled ? (
168
- <RefreshControl
169
- pullToRefreshPipesV1RefreshingStateUpdater={
170
- pullToRefreshPipesV1RefreshingStateUpdater
171
- }
172
- refreshingPipesV1={refreshingPipesV1}
173
- />
174
- ) : null,
175
- []
160
+ () => (pullToRefreshEnabled ? <RefreshControl /> : null),
161
+ [pullToRefreshEnabled]
176
162
  );
177
163
 
178
164
  const navBarStore = useScreenContextV2()._navBarStore;
@@ -281,6 +267,7 @@ function ComponentsMapComponent(props: Props) {
281
267
  >
282
268
  <ViewportTracker>
283
269
  <FlatList
270
+ testID="components-map-flat-list"
284
271
  ref={(ref) => {
285
272
  flatListRef.current = ref;
286
273
  }}
@@ -312,10 +299,10 @@ function ComponentsMapComponent(props: Props) {
312
299
  onScrollEndDrag={_onScrollEndDrag}
313
300
  scrollEventThrottle={16}
314
301
  {...scrollViewExtraProps}
315
- /* When wrapped in a parent ScrollView (e.g. tabs),
316
- this FlatList doesn't scroll so onEndReached can fire repeatedly;
317
- skip it here and let the parent ScrollView emit scroll-end instead. */
318
302
  onEndReached={
303
+ /* When wrapped in a parent ScrollView (e.g. tabs),
304
+ this FlatList doesn't scroll so onEndReached can fire repeatedly;
305
+ skip it here and let the parent ScrollView emit scroll-end instead. */
319
306
  isScreenWrappedInContainer
320
307
  ? undefined
321
308
  : () => {
@@ -1,4 +1,4 @@
1
- import { renderHook, act } from "@testing-library/react-hooks";
1
+ import { renderHook, act } from "@testing-library/react-native";
2
2
  import { BehaviorSubject } from "rxjs";
3
3
  import { useLoadingState } from "../useLoadingState";
4
4
 
@@ -4,9 +4,7 @@ import {
4
4
  RefreshControl as RNRefreshControl,
5
5
  StyleSheet,
6
6
  } from "react-native";
7
- import * as R from "ramda";
8
- import { path } from "@applicaster/zapp-react-native-utils/utils";
9
- import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
7
+ import { get } from "@applicaster/zapp-react-native-utils/utils";
10
8
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
11
9
  import { useLocalizedStrings } from "@applicaster/zapp-react-native-utils/localizationUtils";
12
10
  import { useAnalytics } from "@applicaster/zapp-react-native-utils/analyticsUtils";
@@ -15,7 +13,7 @@ import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/react
15
13
  import { useShallow } from "zustand/react/shallow";
16
14
  import { useScreenContextV2 } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
17
15
  import { useSafeAreaInsets } from "react-native-safe-area-context";
18
- import { useLoadPipesDataDispatch } from "@applicaster/zapp-react-native-utils/reactHooks";
16
+ import { usePullToRefresh } from "./hooks";
19
17
 
20
18
  const BRIGHTNESS_THRESHOLD = 160;
21
19
  const ABOVE_DEFAULT_COLOR = "gray";
@@ -55,66 +53,6 @@ const getBrightness = (RGBcolor) => {
55
53
  );
56
54
  };
57
55
 
58
- export const usePullToRefresh = (
59
- riverComponents,
60
- pullToRefreshPipesV1RefreshingStateUpdater,
61
- refreshingPipesV1
62
- ) => {
63
- const isPipesV1 = !!pullToRefreshPipesV1RefreshingStateUpdater;
64
-
65
- const [refreshing, setRefreshing] = React.useState(false);
66
-
67
- const feeds: string[] = React.useMemo(
68
- () =>
69
- (riverComponents || [])
70
- .map((riverComponent) => path(["data", "source"], riverComponent))
71
- .filter((feed) => !isNilOrEmpty(feed)),
72
- [riverComponents]
73
- );
74
-
75
- const feedsLength = feeds.length;
76
-
77
- const [requestsCompletedCounter, setRequestsCompletedCounter] =
78
- React.useState(0);
79
-
80
- const loadPipesDataDispatcher = useLoadPipesDataDispatch();
81
-
82
- React.useEffect(() => {
83
- // will not work for pipes v1 on 1st level screens
84
- if (refreshing && !isPipesV1) {
85
- feeds.forEach((feed) => {
86
- loadPipesDataDispatcher(feed, {
87
- silentRefresh: true,
88
- clearCache: true,
89
- callback: () => {
90
- setRequestsCompletedCounter(R.inc);
91
- },
92
- });
93
- });
94
- }
95
- }, [refreshing, isPipesV1, feeds, loadPipesDataDispatcher]);
96
-
97
- React.useEffect(() => {
98
- if (requestsCompletedCounter === feedsLength) {
99
- setRefreshing(false);
100
- }
101
- }, [requestsCompletedCounter, feedsLength]);
102
-
103
- const onRefresh = React.useCallback(() => {
104
- if (isPipesV1) {
105
- pullToRefreshPipesV1RefreshingStateUpdater(true);
106
- } else {
107
- setRefreshing(true);
108
- setRequestsCompletedCounter(0);
109
- }
110
- }, [isPipesV1]);
111
-
112
- return {
113
- refreshing: isPipesV1 ? refreshingPipesV1 : refreshing,
114
- onRefresh,
115
- };
116
- };
117
-
118
56
  /** Returns the offset for the progress view of the RefreshControl component
119
57
  * based on navbar content position */
120
58
  export const useGetProgressViewOffset = () => {
@@ -143,16 +81,12 @@ export const useGetProgressViewOffset = () => {
143
81
  }
144
82
  };
145
83
 
146
- export function RefreshControl(props: {
147
- pullToRefreshPipesV1RefreshingStateUpdater?: (refreshing: boolean) => void;
148
- refreshingPipesV1?: boolean;
149
- }) {
84
+ export function RefreshControl(props) {
150
85
  const screenData = useCurrentScreenData();
151
86
 
152
87
  const { refreshing, onRefresh } = usePullToRefresh(
153
- screenData.ui_components,
154
- props.pullToRefreshPipesV1RefreshingStateUpdater,
155
- props.refreshingPipesV1
88
+ screenData.id,
89
+ screenData.ui_components
156
90
  );
157
91
 
158
92
  const { app_background_color: themeBackgroundColor } = useTheme();
@@ -170,29 +104,26 @@ export function RefreshControl(props: {
170
104
  displayTitleIOS,
171
105
  } = React.useMemo(
172
106
  () => ({
173
- indicatorColor: R.prop(
174
- "pull_to_refresh_indicator_color",
175
- screenData.styles
176
- ),
177
- titleUnderIndicatorColor: R.prop(
178
- "pull_to_refresh_title_color_under_indicator",
179
- screenData.styles
107
+ indicatorColor: get(screenData.styles, "pull_to_refresh_indicator_color"),
108
+ titleUnderIndicatorColor: get(
109
+ screenData.styles,
110
+ "pull_to_refresh_title_color_under_indicator"
180
111
  ),
181
- indicatorBackgroundColor: R.prop(
182
- "pull_to_refresh_indicator_bg_color",
183
- screenData.styles
112
+ indicatorBackgroundColor: get(
113
+ screenData.styles,
114
+ "pull_to_refresh_indicator_bg_color"
184
115
  ),
185
116
  indicatorSize:
186
- R.prop("pull_to_refresh_indicator_size", screenData.styles) === "large"
117
+ get(screenData.styles, "pull_to_refresh_indicator_size") === "large"
187
118
  ? "large"
188
119
  : "default",
189
- generalContentBackgroungColor: R.prop(
190
- "screen_background_color",
191
- screenData.styles
120
+ generalContentBackgroungColor: get(
121
+ screenData.styles,
122
+ "screen_background_color"
192
123
  ),
193
- displayTitleIOS: R.prop(
194
- "pull_to_refresh_display_title_ios",
195
- screenData.styles
124
+ displayTitleIOS: get(
125
+ screenData.styles,
126
+ "pull_to_refresh_display_title_ios"
196
127
  ),
197
128
  }),
198
129
  [screenData]
@@ -2,7 +2,6 @@ import * as React from "react";
2
2
  import * as R from "ramda";
3
3
  import { GeneralContentScreen } from "@applicaster/zapp-react-native-ui-components/Components/GeneralContentScreen";
4
4
 
5
- import { FeedLoader } from "../FeedLoader";
6
5
  import { ScreenResolver } from "../ScreenResolver";
7
6
 
8
7
  type Props = ZappScreenProps & {
@@ -23,24 +22,13 @@ type Props = ZappScreenProps & {
23
22
  river: ZappRiver;
24
23
  };
25
24
 
26
- type State = {
27
- refreshing: boolean;
28
- };
29
-
30
- export class RiverComponent extends React.Component<Props, State> {
25
+ export class RiverComponent extends React.Component<Props> {
31
26
  private currentScreenTitle: string;
32
27
  private currentScreenSummary: string;
33
28
  constructor(props: Props) {
34
29
  super(props);
35
30
 
36
- this.state = {
37
- refreshing: false,
38
- };
39
-
40
31
  this.applyContexts();
41
-
42
- this.pullToRefreshPipesV1RefreshingStateUpdater =
43
- this.pullToRefreshPipesV1RefreshingStateUpdater.bind(this);
44
32
  }
45
33
 
46
34
  applyContexts() {
@@ -69,20 +57,9 @@ export class RiverComponent extends React.Component<Props, State> {
69
57
  }
70
58
  }
71
59
 
72
- usesPipesV1Layout() {
73
- return this.props?.appData?.layoutVersion === "v1";
74
- }
75
-
76
- // Method added to keep pipes v1 logic up to date with the pullToRefresh state.
77
- // TODO: Remove when pipes v1 is deprecated.
78
- pullToRefreshPipesV1RefreshingStateUpdater(refreshing) {
79
- this.setState({ refreshing });
80
- }
81
-
82
60
  render() {
83
61
  const {
84
62
  river,
85
- feedUrl,
86
63
  screenData,
87
64
  isInsideContainer,
88
65
  groupId,
@@ -91,22 +68,10 @@ export class RiverComponent extends React.Component<Props, State> {
91
68
 
92
69
  const { id, type } = river;
93
70
 
94
- const connectedFeedURL = R.path(["content", "src"], screenData);
95
- const _feedUrl = feedUrl || connectedFeedURL;
96
-
97
71
  if (type !== "general_content") {
98
- let riverWithConnectedDatasource;
99
-
100
- if (_feedUrl && this.usesPipesV1Layout()) {
101
- riverWithConnectedDatasource = {
102
- ...river,
103
- data: R.merge(river.data || {}, { source: _feedUrl }),
104
- };
105
- }
106
-
107
72
  return (
108
73
  <ScreenResolver
109
- screenData={R.mergeLeft(riverWithConnectedDatasource || river, {
74
+ screenData={R.mergeLeft(river, {
110
75
  groupId,
111
76
  ...screenData,
112
77
  })}
@@ -116,53 +81,15 @@ export class RiverComponent extends React.Component<Props, State> {
116
81
  );
117
82
  }
118
83
 
119
- if (!_feedUrl || !this.usesPipesV1Layout()) {
120
- this.currentScreenTitle = (screenData && screenData.title) || null;
121
-
122
- return (
123
- <GeneralContentScreen
124
- screenId={id}
125
- isScreenWrappedInContainer={isInsideContainer}
126
- groupId={groupId}
127
- scrollViewExtraProps={scrollViewExtraProps}
128
- />
129
- );
130
- }
84
+ this.currentScreenTitle = (screenData && screenData.title) || null;
131
85
 
132
86
  return (
133
- <FeedLoader
134
- feedUrl={_feedUrl}
135
- refreshing={this.state.refreshing}
136
- refreshCallback={() =>
137
- this.pullToRefreshPipesV1RefreshingStateUpdater(false)
138
- }
139
- >
140
- {(feed) => {
141
- if (!feed) {
142
- return null;
143
- }
144
-
145
- this.currentScreenSummary = (feed && feed.summary) || null;
146
-
147
- this.currentScreenTitle =
148
- (feed && feed.title) || (screenData && screenData.title) || null;
149
-
150
- return (
151
- <GeneralContentScreen
152
- screenId={id}
153
- groupId={groupId}
154
- feed={feed}
155
- isScreenWrappedInContainer={isInsideContainer}
156
- scrollViewExtraProps={scrollViewExtraProps}
157
- componentsMapExtraProps={{
158
- pullToRefreshPipesV1RefreshingStateUpdater:
159
- this.pullToRefreshPipesV1RefreshingStateUpdater,
160
- refreshingPipesV1: this.state.refreshing,
161
- }}
162
- />
163
- );
164
- }}
165
- </FeedLoader>
87
+ <GeneralContentScreen
88
+ screenId={id}
89
+ isScreenWrappedInContainer={isInsideContainer}
90
+ groupId={groupId}
91
+ scrollViewExtraProps={scrollViewExtraProps}
92
+ />
166
93
  );
167
94
  }
168
95
  }