@applicaster/zapp-react-native-ui-components 14.0.0-alpha.2385258459 → 14.0.0-alpha.2482261241

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 (38) hide show
  1. package/Components/BaseFocusable/index.tsx +23 -12
  2. package/Components/Cell/__tests__/CellWIthFocusable.test.js +3 -2
  3. package/Components/FeedLoader/FeedLoader.tsx +6 -15
  4. package/Components/FeedLoader/FeedLoaderHOC.tsx +21 -0
  5. package/Components/FeedLoader/index.js +2 -8
  6. package/Components/FreezeWithCallback/__tests__/index.test.tsx +67 -43
  7. package/Components/GeneralContentScreen/utils/useCurationAPI.ts +5 -6
  8. package/Components/Layout/TV/__tests__/index.test.tsx +0 -1
  9. package/Components/MasterCell/DefaultComponents/ActionButton.tsx +6 -2
  10. package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +10 -10
  11. package/Components/MasterCell/DefaultComponents/__tests__/text.test.tsx +18 -18
  12. package/Components/MasterCell/SharedUI/CollapsibleTextContainer/__tests__/index.test.tsx +10 -10
  13. package/Components/MasterCell/utils/behaviorProvider.ts +82 -14
  14. package/Components/MasterCell/utils/index.ts +11 -5
  15. package/Components/OfflineHandler/__tests__/index.test.tsx +6 -13
  16. package/Components/River/ComponentsMap/hooks/__tests__/useLoadingState.test.ts +0 -1
  17. package/Components/River/RefreshControl.tsx +11 -19
  18. package/Components/River/__tests__/river.test.js +12 -26
  19. package/Components/Screen/__tests__/Screen.test.tsx +5 -17
  20. package/Components/Tabs/Tabs.tsx +2 -3
  21. package/Components/Touchable/__tests__/touchable.test.tsx +12 -17
  22. package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +3 -9
  23. package/Components/VideoModal/__tests__/PlayerDetails.test.tsx +5 -5
  24. package/Contexts/ConfigutaionContext/__tests__/ConfigurationProvider.test.tsx +3 -3
  25. package/Contexts/ScreenContext/index.tsx +46 -6
  26. package/Decorators/ConfigurationWrapper/__tests__/withConfigurationProvider.test.tsx +3 -3
  27. package/Decorators/RiverFeedLoader/__tests__/__snapshots__/riverFeedLoader.test.tsx.snap +221 -209
  28. package/Decorators/RiverFeedLoader/__tests__/riverFeedLoader.test.tsx +14 -16
  29. package/Decorators/RiverFeedLoader/__tests__/utils.test.ts +0 -20
  30. package/Decorators/RiverFeedLoader/index.tsx +22 -4
  31. package/Decorators/RiverFeedLoader/utils/index.ts +0 -18
  32. package/Decorators/ZappPipesDataConnector/__tests__/UrlFeedResolver.test.tsx +27 -27
  33. package/Decorators/ZappPipesDataConnector/resolvers/UrlFeedResolver.tsx +35 -10
  34. package/Decorators/ZappPipesDataConnector/utils/mongoFilter.ts +738 -0
  35. package/Decorators/ZappPipesDataConnector/utils/useFilter.tsx +157 -0
  36. package/events/index.ts +1 -0
  37. package/package.json +5 -5
  38. package/Components/River/__tests__/__snapshots__/river.test.js.snap +0 -27
@@ -1,28 +1,58 @@
1
1
  import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
2
- import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageSingleSelectProvider";
2
+ import { StorageSingleValueProvider } from "@applicaster/zapp-react-native-utils/storage/StorageSingleSelectProvider";
3
3
  import { PushTopicManager } from "@applicaster/zapp-react-native-bridge/PushNotifications/PushTopicManager";
4
- import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-bridge/ZappStorage/StorageMultiSelectProvider";
4
+ import { StorageMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/StorageMultiSelectProvider";
5
5
  import React, { useEffect } from "react";
6
6
  import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayer";
7
7
  import { BehaviorSubject } from "rxjs";
8
8
  import { masterCellLogger } from "../logger";
9
9
  import get from "lodash/get";
10
-
11
- const parseContextKey = (key: string): string | null => {
12
- if (!key?.startsWith("@{ctx/")) return null;
13
-
14
- return key.substring("@{ctx/".length, key.length - 1);
10
+ import { ScreenMultiSelectProvider } from "@applicaster/zapp-react-native-utils/storage/ScreenStateMultiSelectProvider";
11
+ import { ScreenSingleValueProvider } from "@applicaster/zapp-react-native-utils/storage/ScreenSingleValueProvider";
12
+ import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks";
13
+ import { useScreenStateStore } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useScreenStateStore";
14
+
15
+ const parseContextKey = (
16
+ key: string,
17
+ context: string = "ctx"
18
+ ): string | null => {
19
+ if (!key?.startsWith(`@{${context}/`)) return null;
20
+
21
+ return key.substring(`@{${context}/`.length, key.length - 1);
15
22
  };
16
23
 
17
24
  const getDataSourceProvider = (
18
- behavior: Behavior
25
+ behavior: Behavior,
26
+ screenRoute: string,
27
+ screenStateStore: ReturnType<typeof useScreenStateStore>
19
28
  ): BehaviorSubject<string[] | string> | null => {
20
29
  if (!behavior) return null;
21
30
 
22
31
  const selection = String(behavior.current_selection);
32
+ const screenKey = parseContextKey(selection, "screen");
33
+
34
+ if (screenKey) {
35
+ if (behavior.select_mode === "multi") {
36
+ return ScreenMultiSelectProvider.getProvider(
37
+ screenKey,
38
+ screenRoute,
39
+ screenStateStore
40
+ ).getObservable();
41
+ }
42
+
43
+ if (behavior.select_mode === "single") {
44
+ return ScreenSingleValueProvider.getProvider(
45
+ screenKey,
46
+ screenRoute,
47
+ screenStateStore
48
+ ).getObservable();
49
+ }
50
+ }
51
+
23
52
  const contextKey = parseContextKey(selection);
24
53
 
25
54
  if (contextKey) {
55
+ // TODO: Add storage scope to behavior
26
56
  if (behavior.select_mode === "multi") {
27
57
  return StorageMultiSelectProvider.getProvider(contextKey).getObservable();
28
58
  }
@@ -41,6 +71,8 @@ const getDataSourceProvider = (
41
71
 
42
72
  export const useBehaviorUpdate = (behavior: Behavior) => {
43
73
  const [lastUpdate, setLastUpdate] = React.useState<number | null>(null);
74
+ const screenRoute = useRoute()?.pathname || "";
75
+ const screenStateStore = useScreenStateStore();
44
76
  const player = usePlayer();
45
77
 
46
78
  const triggerUpdate = () => setLastUpdate(Date.now());
@@ -48,7 +80,11 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
48
80
  useEffect(() => {
49
81
  if (!behavior) return;
50
82
 
51
- const dataSource = getDataSourceProvider(behavior);
83
+ const dataSource = getDataSourceProvider(
84
+ behavior,
85
+ screenRoute,
86
+ screenStateStore
87
+ );
52
88
 
53
89
  if (dataSource) {
54
90
  const subscription = dataSource.subscribe(triggerUpdate);
@@ -72,10 +108,17 @@ export const useBehaviorUpdate = (behavior: Behavior) => {
72
108
 
73
109
  // We cant use async in this function (its inside render),
74
110
  // so we rely on useBehaviorUpdate to update current value and trigger re-render
75
- export const isCellSelected = (
76
- item: ZappEntry,
77
- behavior?: Behavior
78
- ): boolean => {
111
+ export const isCellSelected = ({
112
+ item,
113
+ screenRoute,
114
+ screenStateStore,
115
+ behavior,
116
+ }: {
117
+ item: ZappEntry;
118
+ screenRoute: string;
119
+ screenStateStore: ReturnType<typeof useScreenStateStore>;
120
+ behavior?: Behavior;
121
+ }): boolean => {
79
122
  if (!behavior) return false;
80
123
 
81
124
  const id = behavior.selector ? get(item, behavior.selector) : item.id;
@@ -99,7 +142,32 @@ export const isCellSelected = (
99
142
  }
100
143
 
101
144
  const selection = String(behavior.current_selection);
102
- const contextKey = parseContextKey(selection);
145
+
146
+ const screenKey = parseContextKey(selection, "screen");
147
+
148
+ if (screenKey) {
149
+ if (behavior.select_mode === "single") {
150
+ const selectedItem = ScreenSingleValueProvider.getProvider(
151
+ screenKey,
152
+ screenRoute,
153
+ screenStateStore
154
+ ).getValue();
155
+
156
+ return selectedItem === String(id);
157
+ }
158
+
159
+ if (behavior.select_mode === "multi") {
160
+ const selectedItems = ScreenMultiSelectProvider.getProvider(
161
+ screenKey,
162
+ screenRoute,
163
+ screenStateStore
164
+ ).getSelectedItems();
165
+
166
+ return selectedItems?.includes(String(id));
167
+ }
168
+ }
169
+
170
+ const contextKey = parseContextKey(selection, "ctx");
103
171
 
104
172
  if (contextKey) {
105
173
  if (behavior.select_mode === "single") {
@@ -8,6 +8,8 @@ import { masterCellLogger } from "../logger";
8
8
  import { getCellState } from "../../Cell/utils";
9
9
  import { getColorFromData } from "@applicaster/zapp-react-native-utils/cellUtils";
10
10
  import { isCellSelected, useBehaviorUpdate } from "./behaviorProvider";
11
+ import { useRoute } from "@applicaster/zapp-react-native-utils/reactHooks";
12
+ import { useScreenStateStore } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useScreenStateStore";
11
13
 
12
14
  const hasElementSpecificViewType = (viewType) => (element) => {
13
15
  if (R.isNil(element)) {
@@ -190,10 +192,6 @@ export const getFocusedButtonId = (focusable) => {
190
192
  });
191
193
  };
192
194
 
193
- export const isSelected = (item: ZappEntry, behavior?: Behavior) => {
194
- return isCellSelected(item, behavior);
195
- };
196
-
197
195
  export const useCellState = ({
198
196
  item,
199
197
  behavior,
@@ -204,9 +202,17 @@ export const useCellState = ({
204
202
  focused: boolean;
205
203
  }): CellState => {
206
204
  const lastUpdate = useBehaviorUpdate(behavior);
205
+ const router = useRoute();
206
+ const screenStateStore = useScreenStateStore();
207
207
 
208
208
  const _isSelected = useMemo(
209
- () => isSelected(item, behavior),
209
+ () =>
210
+ isCellSelected({
211
+ item,
212
+ screenRoute: router?.pathname,
213
+ screenStateStore,
214
+ behavior,
215
+ }),
210
216
  [behavior, item, lastUpdate]
211
217
  );
212
218
 
@@ -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
  });
@@ -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", () => {
@@ -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
  });
@@ -158,12 +158,11 @@ const TabsComponent = ({
158
158
 
159
159
  const renderItem = React.useCallback(
160
160
  ({ item, index, item: { id } }: RenderItemProps) => (
161
- <>
161
+ <React.Fragment key={id}>
162
162
  <Tab
163
163
  ref={(ref) => {
164
164
  tabRefs.current[index] = ref;
165
165
  }}
166
- key={id}
167
166
  {...{
168
167
  title: getTitle(item),
169
168
  id,
@@ -177,7 +176,7 @@ const TabsComponent = ({
177
176
  {display_mode === "fractional" &&
178
177
  index !== tabs?.length - 1 &&
179
178
  renderGutter()}
180
- </>
179
+ </React.Fragment>
181
180
  ),
182
181
  [tabs, display_mode, configuration, onTabPress, getTitle, getSelectedItem]
183
182
  );
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import { View, TouchableOpacity } from "react-native";
3
- import { create, act } from "react-test-renderer";
3
+ import { render } from "@testing-library/react-native";
4
4
 
5
5
  import { Touchable } from "..";
6
6
 
@@ -23,38 +23,31 @@ describe("<Touchable />", () => {
23
23
  });
24
24
 
25
25
  it("has accessible flag set to false", () => {
26
- let wrapper;
26
+ const { toJSON, UNSAFE_getByType } = render(<Touchable {...props} />);
27
27
 
28
- act(() => {
29
- wrapper = create(<Touchable {...props} />);
30
- });
31
-
32
- const touchableWrapper = wrapper.root.findByType(TouchableOpacity);
33
- expect(wrapper.toJSON()).toMatchSnapshot();
28
+ const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
29
+ expect(toJSON()).toMatchSnapshot();
34
30
  expect(touchableWrapper.props).toHaveProperty("accessible", false);
35
31
  });
36
32
  });
37
33
 
38
34
  describe("when not running in automated tests environment", () => {
39
- let wrapper;
40
-
41
- act(() => {
42
- wrapper = create(<Touchable {...props} />);
43
- });
44
-
45
- const touchableWrapper = wrapper.root.findByType(TouchableOpacity);
46
-
47
35
  beforeEach(props.onPress.mockClear);
48
36
 
49
37
  it("renders correctly", () => {
50
- expect(wrapper.toJSON()).toMatchSnapshot();
38
+ const { toJSON } = render(<Touchable {...props} />);
39
+ expect(toJSON()).toMatchSnapshot();
51
40
  });
52
41
 
53
42
  it("has accessible flag set to true", () => {
43
+ const { UNSAFE_getByType } = render(<Touchable {...props} />);
44
+ const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
54
45
  expect(touchableWrapper.props).toHaveProperty("accessible", true);
55
46
  });
56
47
 
57
48
  it("assigns testID and accessibilityLabel props correctly", () => {
49
+ const { UNSAFE_getByType } = render(<Touchable {...props} />);
50
+ const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
58
51
  expect(touchableWrapper.props).toHaveProperty("testID", props.testID);
59
52
 
60
53
  expect(touchableWrapper.props).toHaveProperty(
@@ -64,6 +57,8 @@ describe("<Touchable />", () => {
64
57
  });
65
58
 
66
59
  it("calls the onPress event when it is pressed", () => {
60
+ const { UNSAFE_getByType } = render(<Touchable {...props} />);
61
+ const touchableWrapper = UNSAFE_getByType(TouchableOpacity);
67
62
  touchableWrapper.props.onPress();
68
63
  expect(props.onPress).toHaveBeenCalledTimes(1);
69
64
  });
@@ -1,9 +1,8 @@
1
1
  import React from "react";
2
- import { Animated, Platform, StyleSheet, View } from "react-native";
2
+ import { Animated, StyleSheet, View } from "react-native";
3
3
 
4
4
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
5
5
  import {
6
- GestureHandlerRootView,
7
6
  NativeViewGestureHandler,
8
7
  PanGestureHandler,
9
8
  State,
@@ -357,15 +356,10 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
357
356
  };
358
357
  }, [playerAnimationState, isAudioItem, isMinimizedModal]);
359
358
 
360
- const Wrapper = React.useMemo(
361
- () => (Platform.OS === "android" ? GestureHandlerRootView : View),
362
- []
363
- );
364
-
365
359
  const scrollEnabled = isMaximizedModal && isNotMinimizeMaximazeAnimation;
366
360
 
367
361
  return (
368
- <Wrapper style={generalStyles.container}>
362
+ <View style={generalStyles.container}>
369
363
  <TapGestureHandler
370
364
  maxDurationMs={100000}
371
365
  ref={tapHandlerRef}
@@ -405,7 +399,7 @@ export const AnimatedScrollModalComponent = ({ children }: Props) => {
405
399
  </PanGestureHandler>
406
400
  </View>
407
401
  </TapGestureHandler>
408
- </Wrapper>
402
+ </View>
409
403
  );
410
404
  };
411
405
 
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import renderer from "react-test-renderer";
2
+ import { render } from "@testing-library/react-native";
3
3
 
4
4
  const props = {
5
5
  entry: {},
@@ -42,16 +42,16 @@ const { PlayerDetails } = require("../PlayerDetails");
42
42
 
43
43
  describe("PlayerDetails", () => {
44
44
  it("renders properly", () => {
45
- const element = renderer.create(<PlayerDetails {...props} />);
45
+ const { toJSON } = render(<PlayerDetails {...props} />);
46
46
 
47
- expect(element).toMatchSnapshot();
47
+ expect(toJSON()).toMatchSnapshot();
48
48
  });
49
49
 
50
50
  it("renders properly on tablet in landscape orientation", () => {
51
- const element = renderer.create(
51
+ const { toJSON } = render(
52
52
  <PlayerDetails {...props} isTabletLandscape={true} />
53
53
  );
54
54
 
55
- expect(element).toMatchSnapshot();
55
+ expect(toJSON()).toMatchSnapshot();
56
56
  });
57
57
  });
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import TestRenderer from "react-test-renderer";
2
+ import { render } from "@testing-library/react-native";
3
3
  import { View } from "react-native";
4
4
  import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration";
5
5
 
@@ -14,12 +14,12 @@ describe("withConfigurationProvider", () => {
14
14
  };
15
15
 
16
16
  it("provides configuration to children", () => {
17
- const wrapper = TestRenderer.create(
17
+ const { toJSON } = render(
18
18
  <ConfigurationProvider configuration={{ target: "foobar" }}>
19
19
  <TestComponent />
20
20
  </ConfigurationProvider>
21
21
  );
22
22
 
23
- expect(wrapper.toJSON()).toMatchSnapshot();
23
+ expect(toJSON()).toMatchSnapshot();
24
24
  });
25
25
  });
@@ -13,7 +13,8 @@ import {
13
13
  } from "@applicaster/zapp-react-native-utils/reactHooks";
14
14
  import { useModalNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ModalNavigationContext";
15
15
  import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NestedNavigationContext";
16
- import { create, StoreApi, UseBoundStore } from "zustand";
16
+ import { create } from "zustand";
17
+ import { subscribeWithSelector } from "zustand/middleware";
17
18
  import { useShallow } from "zustand/react/shallow";
18
19
  import { Animated } from "react-native";
19
20
 
@@ -39,11 +40,26 @@ interface NavBarState {
39
40
  setSummary: (subtitle: string) => void;
40
41
  }
41
42
 
42
- type ScreenContextType = {
43
- _navBarStore: UseBoundStore<StoreApi<NavBarStoreState>>;
44
- navBar: NavBarState;
45
- legacyFormatScreenData: LegacyNavigationScreenData | null;
46
- };
43
+ const createStateStore = () =>
44
+ create(
45
+ subscribeWithSelector<ScreenStateStore>((set) => ({
46
+ data: {},
47
+ setValue: (key, value) =>
48
+ set((state) => ({
49
+ data: {
50
+ ...state.data,
51
+ [key]: value,
52
+ },
53
+ })),
54
+ removeValue: (key) =>
55
+ set((state) => {
56
+ const newData = { ...state.data };
57
+ delete newData[key];
58
+
59
+ return { data: newData };
60
+ }),
61
+ }))
62
+ );
47
63
 
48
64
  const createStore = () =>
49
65
  create<NavBarStoreState>((set) => ({
@@ -65,7 +81,15 @@ const createStore = () =>
65
81
  },
66
82
  }));
67
83
 
84
+ type ScreenContextType = {
85
+ _navBarStore: ReturnType<typeof createStore>;
86
+ _stateStore: ReturnType<typeof createStateStore>;
87
+ navBar: NavBarState;
88
+ legacyFormatScreenData: LegacyNavigationScreenData | null;
89
+ };
90
+
68
91
  export const ScreenContext = createContext<ScreenContextType>({
92
+ _stateStore: createStateStore(),
69
93
  _navBarStore: createStore(),
70
94
  navBar: {
71
95
  visible: true,
@@ -103,6 +127,21 @@ export function ScreenContextProvider({
103
127
  null
104
128
  );
105
129
 
130
+ const screenStateRef = useRef<null | ReturnType<typeof createStateStore>>(
131
+ null
132
+ );
133
+
134
+ const getScreenState = useCallback(() => {
135
+ if (screenStateRef.current !== null) {
136
+ return screenStateRef.current;
137
+ }
138
+
139
+ const stateStore = createStateStore();
140
+ screenStateRef.current = stateStore;
141
+
142
+ return stateStore;
143
+ }, []);
144
+
106
145
  const getScreenNavBarState = useCallback(() => {
107
146
  if (screenNavBarStateRef.current !== null) {
108
147
  return screenNavBarStateRef.current;
@@ -163,6 +202,7 @@ export function ScreenContextProvider({
163
202
  value={useMemo(
164
203
  () => ({
165
204
  _navBarStore: getScreenNavBarState(),
205
+ _stateStore: getScreenState(),
166
206
  navBar: navBarState,
167
207
  legacyFormatScreenData: routeScreenData,
168
208
  }),