@applicaster/zapp-react-native-ui-components 11.0.0-rc.99 → 12.0.0-rc.1

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 (53) hide show
  1. package/Components/BaseFocusable/index.ios.ts +1 -1
  2. package/Components/Cell/Cell.tsx +5 -13
  3. package/Components/Cell/{CellWithFocusable.js → CellWithFocusable.tsx} +13 -11
  4. package/Components/Cell/TvOSCellComponent.tsx +12 -10
  5. package/Components/FastImage/index.ios.js +3 -0
  6. package/Components/Focusable/FocusableTvOS.tsx +4 -1
  7. package/Components/FocusableCell/{index.js → index.tsx} +8 -5
  8. package/Components/FocusableGroup/FocusableTvOS.tsx +2 -2
  9. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +13 -8
  10. package/Components/HandlePlayable/HandlePlayable.tsx +2 -2
  11. package/Components/HookRenderer/HookRenderer.tsx +9 -6
  12. package/Components/Layout/TV/__tests__/__snapshots__/index.test.tsx.snap +1 -1
  13. package/Components/Layout/TV/index.tsx +9 -13
  14. package/Components/Layout/index.tsx +9 -1
  15. package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +3 -1
  16. package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +22 -19
  17. package/Components/MasterCell/DefaultComponents/SecondaryImage/Image.tsx +1 -0
  18. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/Image.test.tsx +4 -1
  19. package/Components/MasterCell/DefaultComponents/SecondaryImage/__tests__/__snapshots__/Image.test.tsx.snap +2 -0
  20. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/CollapsibleTextContainer.tsx +9 -3
  21. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/__snapshots__/index.test.tsx.snap +7 -1
  22. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +12 -4
  23. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/index.ts +23 -9
  24. package/Components/MasterCell/hoc/withAsyncRender.tsx +8 -4
  25. package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +12 -6
  26. package/Components/MasterCell/hooks/useAsyncRendering/__tests__/MasterCellAsyncRenderManager.test.ts +21 -0
  27. package/Components/MasterCell/hooks/useAsyncRendering/index.ts +15 -13
  28. package/Components/MasterCell/utils/index.ts +143 -19
  29. package/Components/PlayerContainer/PlayerContainer.tsx +10 -6
  30. package/Components/River/ComponentsMap/ComponentsMap.tsx +4 -1
  31. package/Components/River/River.tsx +3 -4
  32. package/Components/River/TV/River.tsx +9 -4
  33. package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +1 -0
  34. package/Components/River/index.tsx +3 -1
  35. package/Components/Screen/__tests__/Screen.test.tsx +6 -3
  36. package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
  37. package/Components/Screen/index.tsx +12 -44
  38. package/Components/Screen/navigationHandler.ts +1 -1
  39. package/Components/Spinner/SpinnerComponent.tsx +6 -2
  40. package/Components/VideoLive/LiveImageManager.ts +24 -9
  41. package/Components/VideoLive/PlayerLiveImageComponent.tsx +23 -1
  42. package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +74 -0
  43. package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +47 -0
  44. package/Components/VideoLive/__tests__/utils.test.ts +109 -0
  45. package/Components/VideoLive/utils.ts +40 -0
  46. package/Components/VideoModal/PlayerDetails.tsx +42 -6
  47. package/Components/VideoModal/PlayerWrapper.tsx +32 -29
  48. package/Components/VideoModal/VideoModal.tsx +20 -17
  49. package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +21 -9
  50. package/Components/VideoModal/__tests__/__snapshots__/PlayerDetails.test.tsx.snap +14 -24
  51. package/Contexts/InteractionManagerContext/index.ts +0 -2
  52. package/Contexts/ScreenContext/index.tsx +118 -0
  53. package/package.json +5 -5
@@ -7,7 +7,11 @@ import { CollapsibleTextContainer } from "../CollapsibleTextContainer";
7
7
  describe("CollapsibleTextContainer", () => {
8
8
  it("render container+children when label is presented", () => {
9
9
  const renderer = ReactTestRenderer.create(
10
- <CollapsibleTextContainer label={"label"}>
10
+ <CollapsibleTextContainer
11
+ backgroundColor="#000000"
12
+ label={"label"}
13
+ style={{}}
14
+ >
11
15
  <View />
12
16
  </CollapsibleTextContainer>
13
17
  );
@@ -20,7 +24,7 @@ describe("CollapsibleTextContainer", () => {
20
24
 
21
25
  it("render nothing when label is empty", () => {
22
26
  const renderer = ReactTestRenderer.create(
23
- <CollapsibleTextContainer label={""}>
27
+ <CollapsibleTextContainer backgroundColor="#000000" label={""} style={{}}>
24
28
  <View />
25
29
  </CollapsibleTextContainer>
26
30
  );
@@ -31,7 +35,7 @@ describe("CollapsibleTextContainer", () => {
31
35
 
32
36
  it("render nothing when label is not passed", () => {
33
37
  const renderer = ReactTestRenderer.create(
34
- <CollapsibleTextContainer>
38
+ <CollapsibleTextContainer backgroundColor="#000000" label={""} style={{}}>
35
39
  <View />
36
40
  </CollapsibleTextContainer>
37
41
  );
@@ -42,7 +46,11 @@ describe("CollapsibleTextContainer", () => {
42
46
 
43
47
  it("render nothing when label is undefined", () => {
44
48
  const renderer = ReactTestRenderer.create(
45
- <CollapsibleTextContainer label={undefined}>
49
+ <CollapsibleTextContainer
50
+ backgroundColor="#000000"
51
+ label={undefined}
52
+ style={{}}
53
+ >
46
54
  <View />
47
55
  </CollapsibleTextContainer>
48
56
  );
@@ -1,4 +1,4 @@
1
- import { path } from "ramda";
1
+ import { path, pathOr } from "ramda";
2
2
  import { isNilOrEmpty } from "@applicaster/zapp-react-native-utils/reactUtils/helpers";
3
3
  import {
4
4
  getKeyForLabel,
@@ -34,17 +34,31 @@ export const CollapsibleTextContainer = ({
34
34
  borderRadius: toNumberWithDefaultZero(getValue("corner_radius")),
35
35
  ...additionalStyles,
36
36
  },
37
- data: customData || [
37
+ data: [
38
+ ...(customData || [
39
+ {
40
+ func: (data, args) =>
41
+ isNilOrEmpty(args) ? undefined : path(args, data),
42
+ args: getKeyForLabel(
43
+ getValue("data_key"),
44
+ getValue("custom_data_key")
45
+ ),
46
+ propName: "label",
47
+ },
48
+ ]),
38
49
  {
39
- func: (data, args) => {
40
- if (isNilOrEmpty(args)) {
41
- return undefined;
42
- }
50
+ func: (data) => {
51
+ const value = getValue("background_color");
43
52
 
44
- return path(args, data);
53
+ // check if value is a reference to an extension
54
+ if (value.startsWith("extensions")) {
55
+ return pathOr(value, value.split("."), data);
56
+ } else {
57
+ // return default value
58
+ return additionalStyles.backgroundColor;
59
+ }
45
60
  },
46
- args: getKeyForLabel(getValue("data_key"), getValue("custom_data_key")),
47
- propName: "label",
61
+ propName: "backgroundColor",
48
62
  },
49
63
  ],
50
64
  elements,
@@ -2,7 +2,7 @@ import * as React from "react";
2
2
  import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
3
3
 
4
4
  type withAsyncRenderHOCProps = {
5
- emitAsyncElementRegistrate?: () => void;
5
+ emitAsyncElementRegistrate?: () => (() => void) | void;
6
6
  emitAsyncElementLayout?: () => void;
7
7
  };
8
8
 
@@ -15,12 +15,16 @@ export const withAsyncRenderHOC: withAsyncRenderHOCT = (Component) => {
15
15
  const { emitAsyncElementRegistrate = noop, emitAsyncElementLayout = noop } =
16
16
  props;
17
17
 
18
- React.useLayoutEffect(() => {
19
- emitAsyncElementRegistrate();
18
+ React.useEffect(() => {
19
+ if (props.emitAsyncElementRegistrate) {
20
+ return emitAsyncElementRegistrate();
21
+ }
20
22
  }, []);
21
23
 
22
24
  const onAsyncRender = React.useCallback(() => {
23
- emitAsyncElementLayout();
25
+ if (props.emitAsyncElementLayout) {
26
+ emitAsyncElementLayout();
27
+ }
24
28
  }, [emitAsyncElementLayout]);
25
29
 
26
30
  return <Component {...props} onAsyncRender={onAsyncRender} />;
@@ -1,17 +1,15 @@
1
1
  import { ReplaySubject } from "rxjs";
2
2
  import { map } from "rxjs/operators";
3
3
 
4
- const subjectBuilder = () => new ReplaySubject();
5
-
6
4
  export class MasterCellAsyncRenderManager {
7
- readonly asyncElementRegistrate$: ReturnType<typeof subjectBuilder>;
8
- readonly asyncElementLayout$: ReturnType<typeof subjectBuilder>;
5
+ readonly asyncElementRegistrate$: ReplaySubject<any>;
6
+ readonly asyncElementLayout$: ReplaySubject<any>;
9
7
  private asyncElementRegistrationCount: number;
10
8
  readonly notifyAllAsyncElementsRendered: () => void;
11
9
 
12
10
  constructor(notifyAllAsyncElementsRendered: () => void) {
13
- this.asyncElementRegistrate$ = subjectBuilder();
14
- this.asyncElementLayout$ = subjectBuilder();
11
+ this.asyncElementRegistrate$ = new ReplaySubject();
12
+ this.asyncElementLayout$ = new ReplaySubject();
15
13
  this.asyncElementRegistrationCount = 0;
16
14
 
17
15
  this.notifyAllAsyncElementsRendered = notifyAllAsyncElementsRendered;
@@ -19,12 +17,20 @@ export class MasterCellAsyncRenderManager {
19
17
 
20
18
  public emitAsyncElementRegistrate = () => {
21
19
  this.asyncElementRegistrate$.next();
20
+
21
+ return this.decrementAsyncElementRegistrationCount;
22
22
  };
23
23
 
24
24
  public emitAsyncElementLayout = () => {
25
25
  this.asyncElementLayout$.next();
26
26
  };
27
27
 
28
+ public decrementAsyncElementRegistrationCount = () => {
29
+ if (this.asyncElementRegistrationCount > 0) {
30
+ this.asyncElementRegistrationCount -= 1;
31
+ }
32
+ };
33
+
28
34
  public onCellLayout = () => {
29
35
  if (this.asyncElementRegistrationCount === 0) {
30
36
  // cell was rendered but no async registrations were occured
@@ -55,4 +55,25 @@ describe("MasterCellAsyncRenderManager", () => {
55
55
 
56
56
  expect(callback).toBeCalled();
57
57
  });
58
+
59
+ it("should return decrementAsyncElementRegistrationCount, call decrementAsyncElementRegistrationCount should decrement count", () => {
60
+ // setup
61
+ const callback = jest.fn();
62
+ const manager = new MasterCellAsyncRenderManager(callback);
63
+
64
+ // run
65
+ manager.start();
66
+
67
+ // verify
68
+ expect(callback).not.toBeCalled();
69
+
70
+ const unsubscribe = manager.emitAsyncElementRegistrate();
71
+
72
+ expect(manager.asyncElementRegistrationCount).toBe(1);
73
+ expect(unsubscribe).toBe(manager.decrementAsyncElementRegistrationCount);
74
+
75
+ unsubscribe();
76
+
77
+ expect(manager.asyncElementRegistrationCount).toBe(0);
78
+ });
58
79
  });
@@ -48,18 +48,16 @@ const initialDimensions = () => ({
48
48
  export const useAsyncRendering = (viewRef: React.RefObject<View>): Return => {
49
49
  const [dimensions, setDimensions] = React.useState(initialDimensions());
50
50
 
51
- const managerRef = React.useRef(null);
52
-
53
- if (!managerRef.current) {
54
- managerRef.current = new MasterCellAsyncRenderManager(() => {
51
+ const managerRef = React.useRef(
52
+ new MasterCellAsyncRenderManager(() => {
55
53
  measure(viewRef?.current, ({ width, height }) => {
56
54
  setDimensions({
57
55
  width,
58
56
  height,
59
57
  });
60
58
  });
61
- });
62
- }
59
+ })
60
+ );
63
61
 
64
62
  React.useEffect(() => {
65
63
  return managerRef.current.start();
@@ -69,11 +67,15 @@ export const useAsyncRendering = (viewRef: React.RefObject<View>): Return => {
69
67
  setDimensions(initialDimensions());
70
68
  }, []);
71
69
 
72
- return {
73
- emitAsyncElementRegistrate: managerRef.current.emitAsyncElementRegistrate,
74
- emitAsyncElementLayout: managerRef.current.emitAsyncElementLayout,
75
- dimensions,
76
- onCellLayout: managerRef.current.onCellLayout,
77
- resetDimensions,
78
- };
70
+ return React.useMemo(
71
+ () => ({
72
+ emitAsyncElementRegistrate:
73
+ managerRef.current?.emitAsyncElementRegistrate,
74
+ emitAsyncElementLayout: managerRef.current.emitAsyncElementLayout,
75
+ dimensions,
76
+ onCellLayout: managerRef.current.onCellLayout,
77
+ resetDimensions,
78
+ }),
79
+ [dimensions, resetDimensions]
80
+ );
79
81
  };
@@ -1,9 +1,14 @@
1
- import React, { useMemo } from "react";
1
+ import React, { useEffect, useMemo } from "react";
2
2
  import * as R from "ramda";
3
3
  import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils";
4
4
  import { useActions } from "@applicaster/zapp-react-native-utils/reactHooks/actions";
5
5
 
6
6
  import { masterCellLogger } from "../logger";
7
+ import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
8
+ import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
9
+ import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
10
+ import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
11
+ import { getCellState } from "../../Cell/utils";
7
12
 
8
13
  const hasElementSpecificViewType = (viewType) => (element) => {
9
14
  if (R.isNil(element)) {
@@ -192,30 +197,149 @@ export const getFocusedButtonId = (focusable) => {
192
197
  };
193
198
 
194
199
  export const isSelected = (id: string | number, behavior?: Behavior) => {
195
- if (behavior && behavior?.select_mode === "single") {
200
+ if (!behavior) {
201
+ return false;
202
+ }
203
+
204
+ if (behavior?.selection_source === "now_playing") {
205
+ const player = playerManager.getActivePlayer();
206
+
207
+ if (player?.entry?.id === id) {
208
+ return true;
209
+ }
210
+ }
211
+
212
+ if (behavior?.select_mode === "single") {
196
213
  return behavior.current_selection === id;
197
214
  }
198
215
 
199
- // TODO: Multi select mode
216
+ if (behavior?.select_mode === "multi") {
217
+ // TODO: Use generic resolver source
218
+
219
+ if (behavior.selection_source === "@{push/topics}") {
220
+ const tags = PushTopicManager.getInstance().getRegisteredTags();
221
+
222
+ return tags.includes(String(id));
223
+ }
224
+
225
+ if (Array.isArray(behavior.current_selection)) {
226
+ return behavior.current_selection.includes(id);
227
+ }
228
+
229
+ const currentSelection = String(behavior.current_selection);
230
+
231
+ if (currentSelection?.startsWith("@{ctx/")) {
232
+ const keyWithoutCtx = currentSelection.substring(
233
+ "@{ctx/".length,
234
+ currentSelection.length - 1
235
+ );
236
+
237
+ const selectedItems =
238
+ StorageMultiSelectProvider.getProvider(
239
+ keyWithoutCtx
240
+ )?.getSelectedItems();
241
+
242
+ return selectedItems?.includes(String(id));
243
+ }
244
+ }
245
+
200
246
  return false;
201
247
  };
202
248
 
203
- export const useCellState = (
204
- id: string | number,
205
- behavior: Behavior,
206
- focused: boolean
207
- ): CellState => {
208
- const selected = useMemo(() => isSelected(id, behavior), [behavior, id]);
209
-
210
- const cellState = selected
211
- ? focused
212
- ? "focused_selected"
213
- : "selected"
214
- : focused
215
- ? "focused"
216
- : "default";
217
-
218
- return cellState;
249
+ export const useBehaviorUpdate = (behavior: Behavior) => {
250
+ const [lastUpdate, setLastUpdate] = React.useState(null);
251
+
252
+ const player = usePlayer();
253
+
254
+ const triggerUpdate = () => {
255
+ setLastUpdate(Date.now());
256
+ };
257
+
258
+ // TODO: Create generic RX to state update
259
+ useEffect(() => {
260
+ // TODO: Use generic resolver source
261
+ if (!behavior) {
262
+ return;
263
+ }
264
+
265
+ const currentSelection = String(behavior.current_selection);
266
+
267
+ if (currentSelection?.startsWith("@{ctx/")) {
268
+ const keyWithoutCtx = currentSelection.substring(
269
+ "@{ctx/".length,
270
+ currentSelection.length - 1
271
+ );
272
+
273
+ if (keyWithoutCtx) {
274
+ const subscription = StorageMultiSelectProvider.getProvider(
275
+ keyWithoutCtx
276
+ )
277
+ .getObservable()
278
+ .subscribe(() => {
279
+ triggerUpdate();
280
+ });
281
+
282
+ return () => {
283
+ subscription.unsubscribe();
284
+ };
285
+ }
286
+ }
287
+ }, [behavior]);
288
+
289
+ useEffect(() => {
290
+ if (!behavior) {
291
+ return;
292
+ }
293
+
294
+ if (behavior?.selection_source === "@{push/topics}") {
295
+ const subscription = PushTopicManager.getInstance()
296
+ .getEntryObservable()
297
+ .subscribe(() => {
298
+ triggerUpdate();
299
+ });
300
+
301
+ return () => {
302
+ subscription.unsubscribe();
303
+ };
304
+ }
305
+ }, [behavior]);
306
+
307
+ useEffect(() => {
308
+ if (!behavior) {
309
+ return;
310
+ }
311
+
312
+ if (behavior?.selection_source === "now_playing" && player) {
313
+ const subscription = player.getEntryObservable().subscribe(() => {
314
+ triggerUpdate();
315
+ });
316
+
317
+ return () => {
318
+ subscription.unsubscribe();
319
+ };
320
+ }
321
+ }, [behavior, player]);
322
+
323
+ return lastUpdate;
324
+ };
325
+
326
+ export const useCellState = ({
327
+ id,
328
+ behavior,
329
+ focused,
330
+ }: {
331
+ id: string | number;
332
+ behavior: Behavior;
333
+ focused: boolean;
334
+ }): CellState => {
335
+ const lastUpdate = useBehaviorUpdate(behavior);
336
+
337
+ const _isSelected = useMemo(
338
+ () => isSelected(id, behavior),
339
+ [behavior, id, lastUpdate]
340
+ );
341
+
342
+ return getCellState({ focused, selected: _isSelected });
219
343
  };
220
344
 
221
345
  export const hasFocusableInsideBuilder = (elementsBuilder) => (item) => {
@@ -35,7 +35,10 @@ import {
35
35
  log_warning,
36
36
  } from "./logger";
37
37
  import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
38
- import { useTargetScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
38
+ import {
39
+ useSetNavbarState,
40
+ useTargetScreenData,
41
+ } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
39
42
  import {
40
43
  PlayerContainerContext,
41
44
  PlayerContainerContextProvider,
@@ -228,6 +231,7 @@ const PlayerContainerComponent = (props: Props) => {
228
231
  const { appData } = usePickFromState(["appData"]);
229
232
  const prevItemId = usePrevious(item?.id);
230
233
  const screenData = useTargetScreenData(item);
234
+ const { setVisible: showNavBar } = useSetNavbarState();
231
235
 
232
236
  const playerEvent = (event, ...args) => {
233
237
  playerManager.invokeHandler(event, ...args);
@@ -242,8 +246,8 @@ const PlayerContainerComponent = (props: Props) => {
242
246
  }
243
247
 
244
248
  navigator.goBack();
245
- navigator.showNavBar();
246
- }, [isModal, navigator]);
249
+ showNavBar(true);
250
+ }, [isModal, navigator.goBack, showNavBar]);
247
251
 
248
252
  const playEntry = (entry) => navigator.replaceTop(entry, { mode });
249
253
 
@@ -478,7 +482,7 @@ const PlayerContainerComponent = (props: Props) => {
478
482
  playerEvent("source_changed", { item });
479
483
 
480
484
  if (!isModal) {
481
- navigator.hideNavBar();
485
+ showNavBar(false);
482
486
  }
483
487
 
484
488
  if (!Player) {
@@ -489,10 +493,10 @@ const PlayerContainerComponent = (props: Props) => {
489
493
  playerEvent("player_did_close");
490
494
 
491
495
  if (!isModal) {
492
- navigator.showNavBar();
496
+ showNavBar(true);
493
497
  }
494
498
  };
495
- }, []);
499
+ }, [showNavBar, /* added as suggested: */ item?.id, isModal, Player]);
496
500
 
497
501
  useEffect(() => {
498
502
  if (prevItemId && !R.equals(prevItemId, item?.id)) {
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import * as R from "ramda";
3
- import { View, FlatList, StyleSheet } from "react-native";
3
+ import { View, FlatList, StyleSheet, Platform } 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";
@@ -208,6 +208,9 @@ function ComponentsMapComponent(props: Props) {
208
208
  >
209
209
  <ViewportTracker>
210
210
  <FlatList
211
+ // Fix for WebView rerender crashes on Android API 28+
212
+ // https://github.com/react-native-webview/react-native-webview/issues/1915#issuecomment-964035468
213
+ overScrollMode={Platform.OS === "android" ? "never" : "auto"}
211
214
  scrollIndicatorInsets={scrollIndicatorInsets}
212
215
  extraData={feed}
213
216
  onLayout={handleOnLayout}
@@ -12,9 +12,6 @@ type Props = ZappScreenProps & {
12
12
  feedUrl?: string;
13
13
  isInsideContainer?: boolean;
14
14
  screenData: {};
15
- setScreenTitle: (string) => void;
16
- setScreenSummary: (string) => void;
17
- setIsScreenWrappedInContainer: (any) => void;
18
15
  groupId: string;
19
16
  scrollViewExtraProps: (
20
17
  | import("react-native").ScrollViewProps
@@ -52,7 +49,9 @@ export class RiverComponent extends React.Component<Props, State> {
52
49
 
53
50
  componentDidUpdate(prevProps) {
54
51
  const {
55
- navigator: { setScreenTitle, setScreenSummary },
52
+ screenContext: {
53
+ navBar: { setTitle: setScreenTitle, setSummary: setScreenSummary },
54
+ },
56
55
  isInsideContainer,
57
56
  } = this.props;
58
57
 
@@ -5,7 +5,6 @@ import { Text } from "react-native";
5
5
  import * as R from "ramda";
6
6
 
7
7
  import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
8
- import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
9
8
  import {
10
9
  useFeedLoader,
11
10
  useLayoutVersion,
@@ -17,6 +16,10 @@ import { utilsLogger } from "@applicaster/zapp-react-native-utils/logger";
17
16
  import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils";
18
17
  import { toBooleanWithDefaultFalse } from "@applicaster/zapp-react-native-utils/booleanUtils";
19
18
  import { isWeb } from "@applicaster/zapp-react-native-utils/reactUtils";
19
+ import {
20
+ useNavbarState,
21
+ useSetNavbarState,
22
+ } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
20
23
 
21
24
  type Props = {
22
25
  screenId: string;
@@ -43,8 +46,10 @@ export const River = (props: Props) => {
43
46
  extraOffset,
44
47
  } = props;
45
48
 
46
- const { setScreenTitle, setScreenSummary, screenTitle, screenSummary } =
47
- useNavigation();
49
+ const { title: screenTitle, summary: screenSummary } = useNavbarState();
50
+
51
+ const { setTitle: setScreenTitle, setSummary: setScreenSummary } =
52
+ useSetNavbarState();
48
53
 
49
54
  const navigationPluginData = useNavigationPluginData();
50
55
 
@@ -92,7 +97,7 @@ export const River = (props: Props) => {
92
97
  setScreenTitle(stringOrEmpty(screenData?.title));
93
98
  setScreenSummary(stringOrEmpty(screenData?.summary));
94
99
  }
95
- }, [feedData, screenData]);
100
+ }, [feedData, screenData, screenTitle, screenSummary]);
96
101
 
97
102
  React.useEffect(() => {
98
103
  if (
@@ -60,6 +60,7 @@ exports[`componentsMap renders renders components map correctly 1`] = `
60
60
  onScroll={[Function]}
61
61
  onScrollBeginDrag={[Function]}
62
62
  onScrollEndDrag={[Function]}
63
+ overScrollMode="auto"
63
64
  refreshControl={null}
64
65
  removeClippedSubviews={true}
65
66
  renderItem={[Function]}
@@ -7,6 +7,7 @@ import { ContainerContext } from "../../Contexts";
7
7
  import { RiverComponent } from "./River";
8
8
  import { withDimensionsProvider } from "@applicaster/zapp-react-native-utils/dimensionsProvider";
9
9
  import { WithRiverFeedLoader } from "../../Decorators/RiverFeedLoader";
10
+ import { withScreenContext } from "../../Contexts/ScreenContext";
10
11
 
11
12
  const reduxConnector = connectToStore(R.pick(["rivers", "appData"]));
12
13
 
@@ -16,5 +17,6 @@ export const River = R.compose(
16
17
  WithRiverFeedLoader,
17
18
  withNavigator,
18
19
  withDimensionsProvider,
19
- ContainerContext.withConsumer
20
+ ContainerContext.withConsumer,
21
+ withScreenContext
20
22
  )(RiverComponent);
@@ -53,6 +53,9 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen", () => ({
53
53
  useCurrentScreenData: jest.fn(() => ({
54
54
  id: "testId",
55
55
  })),
56
+ useNavbarState: jest.fn(() => ({
57
+ visible: jest.fn(() => mock_navBarVisibleFlag),
58
+ })),
56
59
  }));
57
60
 
58
61
  const {
@@ -67,11 +70,11 @@ const navBarProps = { nav_items: [] };
67
70
  const screenData = {};
68
71
 
69
72
  jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
70
- useNavBarStateForScreen: jest.fn(() => ({
71
- isNavBarVisible: jest.fn(() => mock_navBarVisibleFlag),
72
- canGoBack: () => false,
73
+ useRoute: jest.fn(() => ({
74
+ pathname: "/river/testId",
73
75
  })),
74
76
  useNavigation: jest.fn(() => ({
77
+ canGoBack: () => false,
75
78
  currentRoute: "/river/testId",
76
79
  data: { screen: { id: "testId" } },
77
80
  })),
@@ -9,6 +9,10 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
9
9
  }
10
10
  }
11
11
  >
12
+ <View
13
+ nav_items={Array []}
14
+ testID="navBar"
15
+ />
12
16
  <View>
13
17
  <View
14
18
  pathname="/foo/path"