@applicaster/zapp-react-native-ui-components 14.0.0-alpha.5974411329 → 14.0.0-alpha.6000342231

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 (95) hide show
  1. package/Components/AnimatedInOut/index.tsx +69 -26
  2. package/Components/BaseFocusable/index.tsx +23 -12
  3. package/Components/Cell/Cell.tsx +91 -64
  4. package/Components/Cell/CellWithFocusable.tsx +3 -0
  5. package/Components/Cell/FocusableWrapper.tsx +44 -0
  6. package/Components/Cell/TvOSCellComponent.tsx +80 -14
  7. package/Components/Cell/__tests__/CellWIthFocusable.test.js +3 -2
  8. package/Components/FeedLoader/FeedLoader.tsx +7 -16
  9. package/Components/FeedLoader/FeedLoaderHOC.tsx +21 -0
  10. package/Components/FeedLoader/index.js +2 -8
  11. package/Components/Focusable/Focusable.tsx +10 -3
  12. package/Components/Focusable/FocusableTvOS.tsx +2 -2
  13. package/Components/Focusable/Touchable.tsx +5 -3
  14. package/Components/Focusable/index.android.tsx +8 -4
  15. package/Components/FocusableGroup/FocusableTvOS.tsx +1 -1
  16. package/Components/FocusableList/FocusableItem.tsx +4 -3
  17. package/Components/FocusableList/FocusableListItemWrapper.tsx +2 -1
  18. package/Components/FocusableList/hooks/useCellState.android.ts +13 -3
  19. package/Components/FocusableList/index.tsx +16 -9
  20. package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
  21. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +14 -17
  22. package/Components/HandlePlayable/HandlePlayable.tsx +14 -65
  23. package/Components/HandlePlayable/const.ts +3 -0
  24. package/Components/HandlePlayable/utils.ts +74 -0
  25. package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
  26. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +6 -2
  27. package/Components/MasterCell/DefaultComponents/FocusableView/index.tsx +0 -12
  28. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +65 -17
  29. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +21 -3
  30. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +6 -3
  31. package/Components/MasterCell/DefaultComponents/Text/index.tsx +26 -6
  32. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +10 -10
  33. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +18 -18
  34. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +10 -10
  35. package/Components/MasterCell/utils/behaviorProvider.ts +2 -2
  36. package/Components/MasterCell/utils/index.ts +1 -19
  37. package/Components/OfflineHandler/__tests__/index.test.tsx +6 -13
  38. package/Components/PlayerContainer/PlayerContainer.tsx +5 -17
  39. package/Components/PlayerImageBackground/index.tsx +3 -22
  40. package/Components/River/ComponentsMap/ComponentsMap.tsx +49 -42
  41. package/Components/River/ComponentsMap/ContextProviders/ComponentsMapHeightContext.ts +8 -0
  42. package/Components/River/ComponentsMap/ContextProviders/ComponentsMapRefContext.ts +8 -0
  43. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +0 -1
  44. package/Components/River/RefreshControl.tsx +11 -19
  45. package/Components/River/__tests__/river.test.js +12 -26
  46. package/Components/Screen/TV/hooks/useInitialFocus.ts +14 -4
  47. package/Components/Screen/__tests__/Screen.test.tsx +5 -17
  48. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +2 -0
  49. package/Components/Screen/__tests__/navigationHandler.test.ts +133 -22
  50. package/Components/Screen/index.tsx +22 -5
  51. package/Components/Screen/navigationHandler.ts +20 -2
  52. package/Components/ScreenRevealManager/__tests__/ScreenRevealManager.test.ts +2 -2
  53. package/Components/ScreenRevealManager/utils/index.ts +23 -0
  54. package/Components/ScreenRevealManager/withScreenRevealManager.tsx +54 -24
  55. package/Components/Tabs/TV/Tabs.android.tsx +1 -1
  56. package/Components/Tabs/Tabs.tsx +2 -3
  57. package/Components/TextInputTv/__tests__/__snapshots__/TextInputTv.test.js.snap +13 -0
  58. package/Components/TextInputTv/index.tsx +11 -0
  59. package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
  60. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +1 -0
  61. package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +117 -157
  62. package/Components/VideoModal/ModalAnimation/index.ts +2 -13
  63. package/Components/VideoModal/ModalAnimation/utils.ts +1 -327
  64. package/Components/VideoModal/PlayerDetails.tsx +5 -5
  65. package/Components/VideoModal/PlayerWrapper.tsx +14 -88
  66. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
  67. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -0
  68. package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +9 -1
  69. package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +40 -15
  70. package/Components/VideoModal/hooks/useModalSize.ts +10 -5
  71. package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +2 -2
  72. package/Components/VideoModal/hooks/utils/index.ts +4 -0
  73. package/Components/VideoModal/playerWrapperStyle.ts +70 -0
  74. package/Components/VideoModal/playerWrapperUtils.ts +91 -0
  75. package/Contexts/CellFocusedStateContext/index.tsx +27 -0
  76. package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
  77. package/Contexts/ScreenContext/index.tsx +28 -32
  78. package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
  79. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +221 -209
  80. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +14 -16
  81. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -20
  82. package/Decorators/RiverFeedLoader/index.tsx +21 -13
  83. package/Decorators/RiverFeedLoader/utils/getDatasourceUrl.ts +6 -10
  84. package/Decorators/RiverFeedLoader/utils/index.ts +0 -35
  85. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +27 -27
  86. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +3 -5
  87. package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +68 -76
  88. package/events/index.ts +3 -0
  89. package/package.json +5 -5
  90. package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
  91. package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +0 -60
  92. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +0 -421
  93. package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +0 -176
  94. package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +0 -500
  95. package/Components/VideoModal/ModalAnimation/__tests__/getMoveUpValue.test.ts +0 -108
@@ -1,12 +1,12 @@
1
1
  import * as React from "react";
2
2
  import { View } from "react-native";
3
- import ReactTestRenderer from "react-test-renderer";
3
+ import { render } from "@testing-library/react-native";
4
4
 
5
5
  import { CollapsibleTextContainer } from "../CollapsibleTextContainer";
6
6
 
7
7
  describe("CollapsibleTextContainer", () => {
8
8
  it("render container+children when label is presented", () => {
9
- const renderer = ReactTestRenderer.create(
9
+ const { toJSON } = render(
10
10
  <CollapsibleTextContainer
11
11
  backgroundColor="#000000"
12
12
  label={"label"}
@@ -16,36 +16,36 @@ describe("CollapsibleTextContainer", () => {
16
16
  </CollapsibleTextContainer>
17
17
  );
18
18
 
19
- const result = renderer.toJSON();
19
+ const result = toJSON();
20
20
 
21
21
  expect(result).not.toBeNull();
22
- expect(renderer.toJSON()).toMatchSnapshot();
22
+ expect(toJSON()).toMatchSnapshot();
23
23
  });
24
24
 
25
25
  it("render nothing when label is empty", () => {
26
- const renderer = ReactTestRenderer.create(
26
+ const { toJSON } = render(
27
27
  <CollapsibleTextContainer backgroundColor="#000000" label={""} style={{}}>
28
28
  <View />
29
29
  </CollapsibleTextContainer>
30
30
  );
31
31
 
32
- const result = renderer.toJSON();
32
+ const result = toJSON();
33
33
  expect(result).toBeNull();
34
34
  });
35
35
 
36
36
  it("render nothing when label is not passed", () => {
37
- const renderer = ReactTestRenderer.create(
37
+ const { toJSON } = render(
38
38
  <CollapsibleTextContainer backgroundColor="#000000" label={""} style={{}}>
39
39
  <View />
40
40
  </CollapsibleTextContainer>
41
41
  );
42
42
 
43
- const result = renderer.toJSON();
43
+ const result = toJSON();
44
44
  expect(result).toBeNull();
45
45
  });
46
46
 
47
47
  it("render nothing when label is undefined", () => {
48
- const renderer = ReactTestRenderer.create(
48
+ const { toJSON } = render(
49
49
  <CollapsibleTextContainer
50
50
  backgroundColor="#000000"
51
51
  label={undefined}
@@ -55,7 +55,7 @@ describe("CollapsibleTextContainer", () => {
55
55
  </CollapsibleTextContainer>
56
56
  );
57
57
 
58
- const result = renderer.toJSON();
58
+ const result = toJSON();
59
59
  expect(result).toBeNull();
60
60
  });
61
61
  });
@@ -24,7 +24,7 @@ const parseContextKey = (
24
24
  const getDataSourceProvider = (
25
25
  behavior: Behavior,
26
26
  screenRoute: string,
27
- screenStateStore: ScreenStateStore
27
+ screenStateStore: ReturnType<typeof useScreenStateStore>
28
28
  ): BehaviorSubject<string[] | string> | null => {
29
29
  if (!behavior) return null;
30
30
 
@@ -116,7 +116,7 @@ export const isCellSelected = ({
116
116
  }: {
117
117
  item: ZappEntry;
118
118
  screenRoute: string;
119
- screenStateStore: ScreenStateStore;
119
+ screenStateStore: ReturnType<typeof useScreenStateStore>;
120
120
  behavior?: Behavior;
121
121
  }): boolean => {
122
122
  if (!behavior) return false;
@@ -192,20 +192,6 @@ export const getFocusedButtonId = (focusable) => {
192
192
  });
193
193
  };
194
194
 
195
- export const isSelected = ({
196
- item,
197
- screenRoute,
198
- screenStateStore,
199
- behavior,
200
- }: {
201
- item: ZappEntry;
202
- screenRoute: string;
203
- screenStateStore: ScreenStateStore;
204
- behavior?: Behavior;
205
- }) => {
206
- return isCellSelected({ item, screenRoute, screenStateStore, behavior });
207
- };
208
-
209
195
  export const useCellState = ({
210
196
  item,
211
197
  behavior,
@@ -217,15 +203,11 @@ export const useCellState = ({
217
203
  }): CellState => {
218
204
  const lastUpdate = useBehaviorUpdate(behavior);
219
205
  const router = useRoute();
220
- /** Could be replaced with existing store from useScreenContextV2
221
- * const screenContextV2 = useScreenContextV2();
222
- const screenStateStore = screenContextV2._stateStore();
223
- */
224
206
  const screenStateStore = useScreenStateStore();
225
207
 
226
208
  const _isSelected = useMemo(
227
209
  () =>
228
- isSelected({
210
+ isCellSelected({
229
211
  item,
230
212
  screenRoute: router?.pathname,
231
213
  screenStateStore,
@@ -1,6 +1,5 @@
1
1
  import React from "react";
2
-
3
- import renderer, { act } from "react-test-renderer";
2
+ import { render } from "@testing-library/react-native";
4
3
 
5
4
  jest.useFakeTimers({ legacyFakeTimers: true });
6
5
 
@@ -49,24 +48,18 @@ describe("OfflineHandler", () => {
49
48
  const { OfflineHandler, NotificationView } = require("../");
50
49
 
51
50
  it("renders", () => {
52
- const instance = renderer.create(<OfflineHandler />);
53
- expect(instance.toJSON()).toMatchSnapshot();
51
+ const { toJSON } = render(<OfflineHandler />);
52
+ expect(toJSON()).toMatchSnapshot();
54
53
  });
55
54
 
56
55
  it("renders Notification mode if component was rendered while online", () => {
57
56
  mockConnectionStatus = true;
58
57
 
59
- let instance;
60
-
61
- act(() => {
62
- instance = renderer.create(<OfflineHandler />);
63
- });
58
+ const { rerender, UNSAFE_getByType } = render(<OfflineHandler />);
64
59
 
65
- act(() => {
66
- instance.update(<OfflineHandler />);
67
- });
60
+ rerender(<OfflineHandler />);
68
61
 
69
- const notificationsView = instance.root.findByType(NotificationView);
62
+ const notificationsView = UNSAFE_getByType(NotificationView);
70
63
  expect(notificationsView).toBeDefined();
71
64
  });
72
65
  });
@@ -56,11 +56,6 @@ import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
56
56
  import { usePlayNextOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayNextOverlay";
57
57
  import { PlayNextState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/OverlayObserver/OverlaysObserver";
58
58
 
59
- import {
60
- PlayerAnimationStateEnum,
61
- useModalAnimationContext,
62
- } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
63
-
64
59
  import {
65
60
  PlayerNativeCommandTypes,
66
61
  PlayerNativeSendCommand,
@@ -248,9 +243,6 @@ const PlayerContainerComponent = (props: Props) => {
248
243
  const screenData = useTargetScreenData(item);
249
244
  const { setVisible: showNavBar } = useSetNavbarState();
250
245
 
251
- const { isActiveGesture, startComponentsAnimation, setPlayerAnimationState } =
252
- useModalAnimationContext();
253
-
254
246
  const playerEvent = (event, ...args) => {
255
247
  playerManager.invokeHandler(event, ...args);
256
248
  };
@@ -423,7 +415,10 @@ const PlayerContainerComponent = (props: Props) => {
423
415
  id: playerContainerId,
424
416
  listener: {
425
417
  onVideoEnd,
426
- onError,
418
+ onError: (err: Error) => {
419
+ // Adapt Error to the expected shape for onError
420
+ onError({ error: err });
421
+ },
427
422
  onLoad,
428
423
  onPlayerClose: close,
429
424
  onPlayerDetached: close,
@@ -479,8 +474,6 @@ const PlayerContainerComponent = (props: Props) => {
479
474
  if (isModal && mode === VideoModalMode.MAXIMIZED) {
480
475
  if (disableMiniPlayer) {
481
476
  navigator.closeVideoModal();
482
- } else {
483
- setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
484
477
  }
485
478
  }
486
479
 
@@ -677,11 +670,7 @@ const PlayerContainerComponent = (props: Props) => {
677
670
  autoplay={true}
678
671
  controls={false}
679
672
  disableCastAction={disableCastAction}
680
- docked={
681
- navigator.isVideoModalDocked() &&
682
- !startComponentsAnimation &&
683
- !isActiveGesture
684
- }
673
+ docked={navigator.isVideoModalDocked()}
685
674
  entry={item}
686
675
  fullscreen={mode === VideoModalMode.FULLSCREEN}
687
676
  inline={inline}
@@ -699,7 +688,6 @@ const PlayerContainerComponent = (props: Props) => {
699
688
  setNextVideoPreloadThresholdPercentage={
700
689
  setNextVideoPreloadThresholdPercentage
701
690
  }
702
- startComponentsAnimation={startComponentsAnimation}
703
691
  >
704
692
  {renderApplePlayer(applePlayerProps)}
705
693
  </Player>
@@ -2,12 +2,6 @@ import React, { PropsWithChildren } from "react";
2
2
  import { ImageBackground, View } from "react-native";
3
3
 
4
4
  import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
5
- import {
6
- AnimationComponent,
7
- ComponentAnimationType,
8
- useModalAnimationContext,
9
- PlayerAnimationStateEnum,
10
- } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
11
5
 
12
6
  type Props = PropsWithChildren<{
13
7
  entry: ZappEntry;
@@ -25,30 +19,17 @@ const PlayerImageBackgroundComponent = ({
25
19
  style,
26
20
  imageStyle,
27
21
  imageKey,
28
- defaultImageDimensions,
29
22
  }: Props) => {
30
23
  const source = React.useMemo(
31
24
  () => ({ uri: imageSrcFromMediaItem(entry, [imageKey]) }),
32
25
  [imageKey, entry]
33
26
  );
34
27
 
35
- const { playerAnimationState } = useModalAnimationContext();
36
-
37
28
  if (!source) return <>{children}</>;
38
29
 
39
30
  return (
40
- <View
41
- style={
42
- playerAnimationState === PlayerAnimationStateEnum.maximize
43
- ? defaultImageDimensions
44
- : style
45
- }
46
- >
47
- <AnimationComponent
48
- style={style}
49
- animationType={ComponentAnimationType.player}
50
- additionalData={defaultImageDimensions}
51
- >
31
+ <View style={style}>
32
+ <View style={style}>
52
33
  <ImageBackground
53
34
  resizeMode="cover"
54
35
  style={imageSize}
@@ -57,7 +38,7 @@ const PlayerImageBackgroundComponent = ({
57
38
  >
58
39
  {children}
59
40
  </ImageBackground>
60
- </AnimationComponent>
41
+ </View>
61
42
  </View>
62
43
  );
63
44
  };
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import * as R from "ramda";
3
- import { View, StyleSheet, FlatList } from "react-native";
3
+ import { FlatList, StyleSheet, View } from "react-native";
4
4
  import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
5
5
  import { RiverItem } from "../RiverItem";
6
6
  import { RiverFooter } from "../RiverFooter";
@@ -9,8 +9,8 @@ import { useScreenConfiguration } from "../useScreenConfiguration";
9
9
  import { RefreshControl } from "../RefreshControl";
10
10
  import { ifEmptyUseFallback } from "@applicaster/zapp-react-native-utils/cellUtils";
11
11
  import {
12
- useProfilerLogging,
13
12
  usePipesCacheReset,
13
+ useProfilerLogging,
14
14
  } from "@applicaster/zapp-react-native-utils/reactHooks";
15
15
  import { useLoadingState } from "./hooks/useLoadingState";
16
16
  import { ViewportTracker } from "../../Viewport";
@@ -25,6 +25,8 @@ import { useScreenContextV2 } from "@applicaster/zapp-react-native-utils/reactHo
25
25
  import { useShallow } from "zustand/react/shallow";
26
26
 
27
27
  import { isAndroidPlatform } from "@applicaster/zapp-react-native-utils/reactUtils";
28
+ import { ComponentsMapHeightContext } from "./ContextProviders/ComponentsMapHeightContext";
29
+ import { ComponentsMapRefContext } from "./ContextProviders/ComponentsMapRefContext";
28
30
 
29
31
  const isAndroid = isAndroidPlatform();
30
32
 
@@ -70,6 +72,7 @@ function ComponentsMapComponent(props: Props) {
70
72
  } = props;
71
73
 
72
74
  const flatListRef = React.useRef<FlatList | null>(null);
75
+ const flatListWrapperRef = React.useRef<View | null>(null);
73
76
  const screenConfig = useScreenConfiguration(riverId);
74
77
  const screenData = useScreenData(riverId);
75
78
  const pullToRefreshEnabled = screenData?.rules?.pull_to_refresh_enabled;
@@ -265,47 +268,51 @@ function ComponentsMapComponent(props: Props) {
265
268
  // The Screen Picker in Mobile is completly different than the TV
266
269
  // so the various offsets / margins in TV do not apply here.
267
270
  return (
268
- <View style={styles.container}>
269
- <ScreenLoadingMeasurements
270
- riverId={riverId}
271
- numberOfComponents={riverComponents.length}
272
- >
273
- <ViewportTracker>
274
- <FlatList
275
- ref={(ref) => {
276
- flatListRef.current = ref;
277
- }}
278
- // Fix for WebView rerender crashes on Android API 28+
279
- // https://github.com/react-native-webview/react-native-webview/issues/1915#issuecomment-964035468
280
- overScrollMode={isAndroid ? "never" : "auto"}
281
- scrollIndicatorInsets={scrollIndicatorInsets}
282
- extraData={feed}
283
- stickyHeaderIndices={stickyHeaderIndices}
284
- removeClippedSubviews={isAndroid}
285
- onLayout={handleOnLayout}
286
- initialNumToRender={3}
287
- maxToRenderPerBatch={10}
288
- windowSize={12}
289
- keyExtractor={keyExtractor}
290
- renderItem={renderRiverItem}
291
- data={riverComponents}
292
- contentContainerStyle={contentContainerStyle}
293
- ListFooterComponent={
294
- <RiverFooter
295
- flatListHeight={flatListHeight}
296
- loadingState={loadingState}
271
+ <View style={styles.container} ref={flatListWrapperRef}>
272
+ <ComponentsMapHeightContext.Provider value={flatListHeight}>
273
+ <ComponentsMapRefContext.Provider value={flatListWrapperRef}>
274
+ <ScreenLoadingMeasurements
275
+ riverId={riverId}
276
+ numberOfComponents={riverComponents.length}
277
+ >
278
+ <ViewportTracker>
279
+ <FlatList
280
+ ref={(ref) => {
281
+ flatListRef.current = ref;
282
+ }}
283
+ // Fix for WebView rerender crashes on Android API 28+
284
+ // https://github.com/react-native-webview/react-native-webview/issues/1915#issuecomment-964035468
285
+ overScrollMode={isAndroid ? "never" : "auto"}
286
+ scrollIndicatorInsets={scrollIndicatorInsets}
287
+ extraData={feed}
288
+ stickyHeaderIndices={stickyHeaderIndices}
289
+ removeClippedSubviews={isAndroid}
290
+ onLayout={handleOnLayout}
291
+ initialNumToRender={3}
292
+ maxToRenderPerBatch={10}
293
+ windowSize={12}
294
+ keyExtractor={keyExtractor}
295
+ renderItem={renderRiverItem}
296
+ data={riverComponents}
297
+ contentContainerStyle={contentContainerStyle}
298
+ ListFooterComponent={
299
+ <RiverFooter
300
+ flatListHeight={flatListHeight}
301
+ loadingState={loadingState}
302
+ />
303
+ }
304
+ refreshControl={refreshControl}
305
+ onScrollBeginDrag={onScrollBeginDrag}
306
+ onScroll={onScroll}
307
+ onMomentumScrollEnd={_onMomentumScrollEnd}
308
+ onScrollEndDrag={_onScrollEndDrag}
309
+ scrollEventThrottle={16}
310
+ {...scrollViewExtraProps}
297
311
  />
298
- }
299
- refreshControl={refreshControl}
300
- onScrollBeginDrag={onScrollBeginDrag}
301
- onScroll={onScroll}
302
- onMomentumScrollEnd={_onMomentumScrollEnd}
303
- onScrollEndDrag={_onScrollEndDrag}
304
- scrollEventThrottle={16}
305
- {...scrollViewExtraProps}
306
- />
307
- </ViewportTracker>
308
- </ScreenLoadingMeasurements>
312
+ </ViewportTracker>
313
+ </ScreenLoadingMeasurements>
314
+ </ComponentsMapRefContext.Provider>
315
+ </ComponentsMapHeightContext.Provider>
309
316
  </View>
310
317
  );
311
318
  }
@@ -0,0 +1,8 @@
1
+ import * as React from "react";
2
+
3
+ export const ComponentsMapHeightContext = React.createContext<number | null>(
4
+ null
5
+ );
6
+
7
+ export const useComponentsMapHeight = () =>
8
+ React.useContext(ComponentsMapHeightContext);
@@ -0,0 +1,8 @@
1
+ import * as React from "react";
2
+ import { View } from "react-native";
3
+
4
+ export const ComponentsMapRefContext =
5
+ React.createContext<React.RefObject<View | null> | null>(null);
6
+
7
+ export const useComponentsMapRef = () =>
8
+ React.useContext(ComponentsMapRefContext);
@@ -2,7 +2,6 @@ import { renderHook, act } from "@testing-library/react-hooks";
2
2
  import { BehaviorSubject } from "rxjs";
3
3
  import { useLoadingState } from "../useLoadingState";
4
4
 
5
- // Mock the useRefWithInitialValue hook
6
5
  jest.mock(
7
6
  "@applicaster/zapp-react-native-utils/reactHooks/state/useRefWithInitialValue",
8
7
  () => ({
@@ -13,10 +13,7 @@ import { useCurrentScreenData } from "@applicaster/zapp-react-native-utils/react
13
13
  import { useShallow } from "zustand/react/shallow";
14
14
  import { useScreenContextV2 } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
15
15
  import { useSafeAreaInsets } from "react-native-safe-area-context";
16
- import {
17
- ZappPipes,
18
- useAppDispatch,
19
- } from "@applicaster/zapp-react-native-redux";
16
+ import { useLoadPipesDataDispatch } from "@applicaster/zapp-react-native-utils/reactHooks";
20
17
 
21
18
  const BRIGHTNESS_THRESHOLD = 160;
22
19
  const ABOVE_DEFAULT_COLOR = "gray";
@@ -63,38 +60,33 @@ export const usePullToRefresh = (
63
60
  ) => {
64
61
  const isPipesV1 = !!pullToRefreshPipesV1RefreshingStateUpdater;
65
62
 
66
- const dispatch = useAppDispatch();
67
-
68
63
  const [refreshing, setRefreshing] = React.useState(false);
69
64
 
70
65
  const feeds: string[] =
71
66
  riverComponents?.map(R.path(["data", "source"])).filter((feed) => !!feed) ??
72
67
  [];
73
68
 
74
- const screenData = useCurrentScreenData();
75
-
76
69
  const feedsLength = feeds.length;
77
70
 
78
71
  const [requestsCompletedCounter, setRequestsCompletedCounter] =
79
72
  React.useState(0);
80
73
 
74
+ const loadPipesDataDispatcher = useLoadPipesDataDispatch();
75
+
81
76
  React.useEffect(() => {
82
77
  // will not work for pipes v1 on 1st level screens
83
78
  if (refreshing && !isPipesV1) {
84
79
  feeds.forEach((feed) => {
85
- dispatch(
86
- ZappPipes.loadPipesData(feed, {
87
- silentRefresh: true,
88
- clearCache: true,
89
- callback: () => {
90
- setRequestsCompletedCounter(R.inc);
91
- },
92
- riverId: screenData.id,
93
- })
94
- );
80
+ loadPipesDataDispatcher(feed, {
81
+ silentRefresh: true,
82
+ clearCache: true,
83
+ callback: () => {
84
+ setRequestsCompletedCounter(R.inc);
85
+ },
86
+ });
95
87
  });
96
88
  }
97
- }, [refreshing, isPipesV1]);
89
+ }, [refreshing, isPipesV1, feeds, loadPipesDataDispatcher]);
98
90
 
99
91
  React.useEffect(() => {
100
92
  if (requestsCompletedCounter === feedsLength) {
@@ -1,20 +1,10 @@
1
1
  import React from "react";
2
- import { render, screen } from "@testing-library/react-native";
3
- import configureStore from "redux-mock-store";
2
+ import { screen } from "@testing-library/react-native";
4
3
  import { renderWithProviders } from "@applicaster/zapp-react-native-utils/testUtils";
5
- import { Provider } from "react-redux";
6
4
 
7
- import { River } from "../";
8
5
  import { ScreenResolver } from "../../ScreenResolver";
9
6
  import { RiverComponent } from "../River";
10
7
 
11
- jest.mock(
12
- "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
13
- () => ({
14
- useIsScreenActive: jest.fn(() => true),
15
- })
16
- );
17
-
18
8
  jest.mock(
19
9
  "@applicaster/zapp-react-native-ui-components/Components/GeneralContentScreen",
20
10
  () => {
@@ -46,6 +36,13 @@ jest.mock(
46
36
  })
47
37
  );
48
38
 
39
+ jest.mock(
40
+ "@applicaster/zapp-react-native-utils/reactHooks/navigation/useIsScreenActive",
41
+ () => ({
42
+ useIsScreenActive: jest.fn(() => true),
43
+ })
44
+ );
45
+
49
46
  const river = {
50
47
  home: true,
51
48
  id: "A1234",
@@ -89,28 +86,17 @@ const riverProps = {
89
86
 
90
87
  const appData = { layoutVersion: "v1" };
91
88
 
92
- const store = configureStore()({ rivers, appData });
89
+ const store = { rivers, appData };
93
90
 
94
91
  describe("When River has a general_content type", () => {
95
92
  it("renders GeneralContentScreen correctly", () => {
96
- const { getByTestId } = render(
97
- <Provider store={store}>
98
- <RiverComponent {...riverProps} />
99
- </Provider>
93
+ const { getByTestId } = renderWithProviders(
94
+ <RiverComponent {...riverProps} />,
95
+ store
100
96
  );
101
97
 
102
98
  expect(getByTestId("general-content-screen")).toBeTruthy();
103
99
  });
104
-
105
- it("renders River component correctly", () => {
106
- const wrapper = render(
107
- <Provider store={store}>
108
- <River screenId="A1234" />
109
- </Provider>
110
- );
111
-
112
- expect(wrapper.toJSON()).toMatchSnapshot();
113
- });
114
100
  });
115
101
 
116
102
  describe("When River has any other type other than general_content", () => {
@@ -10,6 +10,8 @@ import {
10
10
  setFocusOnMenu,
11
11
  } from "@applicaster/zapp-react-native-utils/appUtils/focusManagerAux";
12
12
 
13
+ import { waitUntilScreenRevealManagerIsReady } from "@applicaster/zapp-react-native-ui-components/Components/ScreenRevealManager/utils";
14
+
13
15
  type Return =
14
16
  | {
15
17
  onContent: true;
@@ -57,14 +59,22 @@ export const useInitialFocus = (): void => {
57
59
  React.useEffect(() => {
58
60
  const initialFocus = getInitialFocus(focusOnContent, isNavBarVisible);
59
61
 
60
- if (initialFocus.onContent) {
61
- setFocusOnContent(currentRoute);
62
+ if (initialFocus.onMenu) {
63
+ setFocusOnMenu(currentRoute);
62
64
 
63
65
  return;
64
66
  }
65
67
 
66
- if (initialFocus.onMenu) {
67
- setFocusOnMenu(currentRoute);
68
+ if (initialFocus.onContent) {
69
+ const subscription = waitUntilScreenRevealManagerIsReady().subscribe(
70
+ () => {
71
+ setFocusOnContent(currentRoute);
72
+ }
73
+ );
74
+
75
+ return () => {
76
+ subscription.unsubscribe();
77
+ };
68
78
  }
69
79
  }, []);
70
80
  };
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { View } from "react-native";
3
- import { act, create } from "react-test-renderer";
3
+ import { render } from "@testing-library/react-native";
4
4
 
5
5
  const Mocked_RouteManager = jest.fn((props) => (
6
6
  <View testID="routeManager" {...props} />
@@ -152,8 +152,6 @@ const screenProps = {
152
152
  const { Screen } = require("..");
153
153
 
154
154
  describe("<Screen Component />", () => {
155
- let wrapper;
156
-
157
155
  beforeEach(() => {
158
156
  allowedOrientationsForScreen.mockClear();
159
157
  getOrientation.mockClear();
@@ -161,26 +159,16 @@ describe("<Screen Component />", () => {
161
159
  });
162
160
 
163
161
  describe("when the navbar should show", () => {
164
- act(() => {
165
- wrapper = create(<Screen {...screenProps} />);
166
- });
167
-
168
162
  it("renders correctly", () => {
169
- expect(wrapper.toJSON()).toMatchSnapshot();
163
+ const { toJSON } = render(<Screen {...screenProps} />);
164
+ expect(toJSON()).toMatchSnapshot();
170
165
  });
171
166
  });
172
167
 
173
168
  describe("when the navbar should be hidden", () => {
174
- beforeEach(() => {
175
- wrapper = create(<Screen {...screenProps} />);
176
- });
177
-
178
169
  it("renders correctly", () => {
179
- act(() => {
180
- wrapper = create(<Screen {...screenProps} />);
181
- });
182
-
183
- expect(wrapper.toJSON()).toMatchSnapshot();
170
+ const { toJSON } = render(<Screen {...screenProps} />);
171
+ expect(toJSON()).toMatchSnapshot();
184
172
  });
185
173
  });
186
174
  });
@@ -2,6 +2,7 @@
2
2
 
3
3
  exports[`<Screen Component /> when the navbar should be hidden renders correctly 1`] = `
4
4
  <View
5
+ importantForAccessibility="yes"
5
6
  style={
6
7
  {
7
8
  "backgroundColor": "blue",
@@ -34,6 +35,7 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
34
35
 
35
36
  exports[`<Screen Component /> when the navbar should show renders correctly 1`] = `
36
37
  <View
38
+ importantForAccessibility="yes"
37
39
  style={
38
40
  {
39
41
  "backgroundColor": "blue",