@applicaster/zapp-react-native-ui-components 12.0.0-rc.52 → 12.0.0-rc.54
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.
- package/Components/GeneralContentScreen/utils/__tests__/useCurationAPI.test.js +13 -6
- package/Components/GeneralContentScreen/utils/useCurationAPI.ts +1 -1
- package/Components/River/ComponentsMap/ComponentsMap.tsx +85 -22
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
- package/Components/Screen/index.tsx +35 -24
- package/Components/Viewport/ViewportTracker/ViewportTracker.tsx +1 -1
- package/Components/Viewport/ViewportTracker/index.tsx +1 -0
- package/Components/Viewport/utils.js +1 -1
- package/Contexts/MenuToggleContext/{index.js → index.ts} +16 -0
- package/Contexts/ScreenContext/__tests__/__snapshots__/index.test.tsx.snap +3 -0
- package/Contexts/ScreenContext/__tests__/index.test.tsx +27 -0
- package/Contexts/ScreenContext/index.tsx +94 -25
- package/package.json +5 -5
- /package/Contexts/{index.js → index.ts} +0 -0
|
@@ -50,7 +50,11 @@ describe("getTransformedPreset should return the passed components if smartCompo
|
|
|
50
50
|
);
|
|
51
51
|
|
|
52
52
|
expect(transformed_preset).toBeDefined();
|
|
53
|
-
|
|
53
|
+
|
|
54
|
+
expect(transformed_preset.id).toEqual(
|
|
55
|
+
`${mockComp.id}-${mockPreset.feed_url}-0`
|
|
56
|
+
); // id was transformed
|
|
57
|
+
|
|
54
58
|
expect(transformed_preset.data.source).toEqual(mockPreset.feed_url); // source was replaced with preset feed_url.
|
|
55
59
|
});
|
|
56
60
|
});
|
|
@@ -117,7 +121,10 @@ describe("getTransformedPreset should return the passed components if smartCompo
|
|
|
117
121
|
|
|
118
122
|
expect(Array.isArray(result)).toBe(true);
|
|
119
123
|
expect(result).toHaveLength(2);
|
|
120
|
-
|
|
124
|
+
|
|
125
|
+
expect(result[0].id).toEqual(
|
|
126
|
+
`${mockSmartComp.id}-${mockFeeds.preset_source.data.entry[0].feed_url}-0`
|
|
127
|
+
);
|
|
121
128
|
|
|
122
129
|
expect(result[0].data.source).toEqual(
|
|
123
130
|
mockFeeds.preset_source.data.entry[0].feed_url
|
|
@@ -287,7 +294,7 @@ describe("getTransformedPreset should return the passed components if smartCompo
|
|
|
287
294
|
mockComponents[0],
|
|
288
295
|
{
|
|
289
296
|
...mockLayoutPresets.preset_one,
|
|
290
|
-
id: mockComponents[1].id
|
|
297
|
+
id: `${mockComponents[1].id}-${mockPresetEntry[0].feed_url}-1`,
|
|
291
298
|
data: { source: mockPresetEntry[0].feed_url },
|
|
292
299
|
},
|
|
293
300
|
];
|
|
@@ -344,12 +351,12 @@ describe("getTransformedPreset should return the passed components if smartCompo
|
|
|
344
351
|
const mockTransformedComponents = [
|
|
345
352
|
{
|
|
346
353
|
...mockLayoutPresets.preset_one,
|
|
347
|
-
id: mockComponents[0].id
|
|
354
|
+
id: `${mockComponents[0].id}-${mockPresetEntry1[0].feed_url}-0`,
|
|
348
355
|
data: { source: mockPresetEntry1[0].feed_url },
|
|
349
356
|
},
|
|
350
357
|
{
|
|
351
358
|
...mockLayoutPresets.preset_one,
|
|
352
|
-
id: mockComponents[1].id
|
|
359
|
+
id: `${mockComponents[1].id}-${mockPresetEntry2[0].feed_url}-1`,
|
|
353
360
|
data: { source: mockPresetEntry2[0].feed_url },
|
|
354
361
|
},
|
|
355
362
|
];
|
|
@@ -412,7 +419,7 @@ describe("getTransformedPreset should return the passed components if smartCompo
|
|
|
412
419
|
const mockTransformedComponents = mockPresetEntry.map((preset, i) => {
|
|
413
420
|
return {
|
|
414
421
|
...mockLayoutPresets[preset.preset_name],
|
|
415
|
-
id: mockComponents[0].id
|
|
422
|
+
id: `${mockComponents[0].id}-${preset.feed_url}-${i}`,
|
|
416
423
|
data: { source: preset.feed_url },
|
|
417
424
|
};
|
|
418
425
|
});
|
|
@@ -41,7 +41,7 @@ export const getTransformedPreset = (
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
const updatedPresetComponent = produce(presetComponent, (draft) => {
|
|
44
|
-
draft.id = `${componentId}
|
|
44
|
+
draft.id = `${componentId}-${preset?.feed_url}-${index}`;
|
|
45
45
|
draft.data.source = preset?.feed_url;
|
|
46
46
|
|
|
47
47
|
if (draft.ui_components) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
|
-
import { View,
|
|
3
|
+
import { View, StyleSheet, Platform, Animated, FlatList } 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";
|
|
@@ -21,7 +21,8 @@ import {
|
|
|
21
21
|
import { useScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenData";
|
|
22
22
|
import { isLast } from "@applicaster/zapp-react-native-utils/arrayUtils";
|
|
23
23
|
import { withComponentsMapProvider } from "@applicaster/zapp-react-native-ui-components/Decorators/ComponentsMapWrapper";
|
|
24
|
-
import {
|
|
24
|
+
import { useScreenContextV2 } from "@applicaster/zapp-react-native-utils/reactHooks/screen/useScreenContext";
|
|
25
|
+
import { useShallow } from "zustand/react/shallow";
|
|
25
26
|
|
|
26
27
|
type Props = {
|
|
27
28
|
feed: ZappFeed;
|
|
@@ -41,8 +42,10 @@ const styles = StyleSheet.create({
|
|
|
41
42
|
},
|
|
42
43
|
});
|
|
43
44
|
|
|
44
|
-
const
|
|
45
|
+
const getNearestValue = (value, optionA, optionB) =>
|
|
46
|
+
Math.abs(value - optionA) < Math.abs(value - optionB) ? optionA : optionB;
|
|
45
47
|
|
|
48
|
+
const scrollIndicatorInsets = { right: 1 };
|
|
46
49
|
const keyExtractor = R.compose(String, R.prop("id"));
|
|
47
50
|
|
|
48
51
|
function ComponentsMapComponent(props: Props) {
|
|
@@ -60,6 +63,7 @@ function ComponentsMapComponent(props: Props) {
|
|
|
60
63
|
refreshingPipesV1,
|
|
61
64
|
} = props;
|
|
62
65
|
|
|
66
|
+
const flatListRef = React.useRef<FlatList | null>(null);
|
|
63
67
|
const screenConfig = useScreenConfiguration(riverId);
|
|
64
68
|
const screenData = useScreenData(riverId);
|
|
65
69
|
const pullToRefreshEnabled = screenData?.rules?.pull_to_refresh_enabled;
|
|
@@ -194,26 +198,67 @@ function ComponentsMapComponent(props: Props) {
|
|
|
194
198
|
[]
|
|
195
199
|
);
|
|
196
200
|
|
|
197
|
-
const
|
|
198
|
-
({ nativeEvent }, isScrollingDone = false) => {
|
|
199
|
-
const {
|
|
200
|
-
contentOffset: { y },
|
|
201
|
-
} = nativeEvent;
|
|
201
|
+
const navBarStore = useScreenContextV2()._navBarStore;
|
|
202
202
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
scrollPosition: y,
|
|
206
|
-
});
|
|
207
|
-
},
|
|
208
|
-
[]
|
|
203
|
+
const scrollY = navBarStore(
|
|
204
|
+
useShallow(({ scrollYAnimated }) => scrollYAnimated)
|
|
209
205
|
);
|
|
210
206
|
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
207
|
+
const canMomentum = React.useRef(false);
|
|
208
|
+
|
|
209
|
+
const onScrollBeginDrag = React.useCallback(() => {
|
|
210
|
+
canMomentum.current = true;
|
|
211
|
+
}, []);
|
|
212
|
+
|
|
213
|
+
/* onMomentumScrollEnd: Handling snap to expanded/collapsed state ( for navbar ) */
|
|
214
|
+
const _onMomentumScrollEnd = React.useCallback(({ nativeEvent }) => {
|
|
215
|
+
if (!canMomentum.current) return;
|
|
216
|
+
canMomentum.current = false;
|
|
217
|
+
|
|
218
|
+
const { height: headerHeight, scrollState } = navBarStore.getState();
|
|
219
|
+
|
|
220
|
+
const offsetY = nativeEvent.contentOffset.y;
|
|
221
|
+
|
|
222
|
+
if (
|
|
223
|
+
!(scrollState === 0 || scrollState === -headerHeight) &&
|
|
224
|
+
flatListRef.current
|
|
225
|
+
) {
|
|
226
|
+
const offset =
|
|
227
|
+
getNearestValue(Math.round(scrollState), -headerHeight, 0) ===
|
|
228
|
+
-headerHeight
|
|
229
|
+
? Math.round(offsetY + scrollState + headerHeight)
|
|
230
|
+
: Math.round(offsetY + scrollState);
|
|
231
|
+
|
|
232
|
+
flatListRef.current.scrollToOffset({
|
|
233
|
+
animated: true,
|
|
234
|
+
offset,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}, []);
|
|
238
|
+
|
|
239
|
+
/* onScrollEnd: Handling snap to expanded/collapsed state ( for navbar ) */
|
|
240
|
+
const _onScrollEndDrag = React.useCallback(({ nativeEvent }) => {
|
|
241
|
+
const { height: headerHeight, scrollState } = navBarStore.getState();
|
|
242
|
+
|
|
243
|
+
const offsetY = nativeEvent.contentOffset.y;
|
|
244
|
+
|
|
245
|
+
if (
|
|
246
|
+
!(scrollState === 0 || scrollState === -headerHeight) &&
|
|
247
|
+
flatListRef.current &&
|
|
248
|
+
nativeEvent.velocity.y === 0
|
|
249
|
+
) {
|
|
250
|
+
const offset =
|
|
251
|
+
getNearestValue(Math.round(scrollState), -headerHeight, 0) ===
|
|
252
|
+
-headerHeight
|
|
253
|
+
? Math.round(offsetY + scrollState + headerHeight)
|
|
254
|
+
: Math.round(offsetY + scrollState);
|
|
255
|
+
|
|
256
|
+
flatListRef.current.scrollToOffset({
|
|
257
|
+
animated: true,
|
|
258
|
+
offset,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}, []);
|
|
217
262
|
|
|
218
263
|
if (shouldShowLoadingError) {
|
|
219
264
|
return <RiverError />;
|
|
@@ -230,6 +275,9 @@ function ComponentsMapComponent(props: Props) {
|
|
|
230
275
|
>
|
|
231
276
|
<ViewportTracker>
|
|
232
277
|
<FlatList
|
|
278
|
+
ref={(ref) => {
|
|
279
|
+
flatListRef.current = ref;
|
|
280
|
+
}}
|
|
233
281
|
// Fix for WebView rerender crashes on Android API 28+
|
|
234
282
|
// https://github.com/react-native-webview/react-native-webview/issues/1915#issuecomment-964035468
|
|
235
283
|
overScrollMode={Platform.OS === "android" ? "never" : "auto"}
|
|
@@ -249,8 +297,23 @@ function ComponentsMapComponent(props: Props) {
|
|
|
249
297
|
}
|
|
250
298
|
ListFooterComponent={renderFooter}
|
|
251
299
|
refreshControl={refreshControl}
|
|
252
|
-
|
|
253
|
-
|
|
300
|
+
onScrollBeginDrag={onScrollBeginDrag}
|
|
301
|
+
onScroll={Animated.event(
|
|
302
|
+
[
|
|
303
|
+
{
|
|
304
|
+
nativeEvent: {
|
|
305
|
+
contentOffset: {
|
|
306
|
+
y: scrollY,
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
],
|
|
311
|
+
{
|
|
312
|
+
useNativeDriver: false,
|
|
313
|
+
}
|
|
314
|
+
)}
|
|
315
|
+
onMomentumScrollEnd={_onMomentumScrollEnd}
|
|
316
|
+
onScrollEndDrag={_onScrollEndDrag}
|
|
254
317
|
scrollEventThrottle={16}
|
|
255
318
|
{...scrollViewExtraProps}
|
|
256
319
|
/>
|
|
@@ -11,7 +11,9 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
|
|
|
11
11
|
}
|
|
12
12
|
>
|
|
13
13
|
<View
|
|
14
|
+
hasMenu={false}
|
|
14
15
|
id="/river/testId"
|
|
16
|
+
pathname="/river/testId"
|
|
15
17
|
selected="testId"
|
|
16
18
|
testID="navBar"
|
|
17
19
|
title=""
|
|
@@ -41,7 +43,9 @@ exports[`<Screen Component /> when the navbar should show renders correctly 1`]
|
|
|
41
43
|
}
|
|
42
44
|
>
|
|
43
45
|
<View
|
|
46
|
+
hasMenu={false}
|
|
44
47
|
id="/river/testId"
|
|
48
|
+
pathname="/river/testId"
|
|
45
49
|
selected="testId"
|
|
46
50
|
testID="navBar"
|
|
47
51
|
title=""
|
|
@@ -6,7 +6,10 @@ import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
|
6
6
|
|
|
7
7
|
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
8
8
|
import { getComponentModule } from "@applicaster/zapp-react-native-utils/pluginUtils";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
getNavigationPropsV2,
|
|
11
|
+
resolveNavigationPlugin,
|
|
12
|
+
} from "@applicaster/zapp-react-native-utils/navigationUtils";
|
|
10
13
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
11
14
|
import {
|
|
12
15
|
useDimensions,
|
|
@@ -52,11 +55,11 @@ function isValidColor(string) {
|
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
type Props = {
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
pathname: unknown;
|
|
59
|
+
screenData: unknown;
|
|
57
60
|
};
|
|
58
61
|
|
|
59
|
-
export function Screen(
|
|
62
|
+
export function Screen(_props: Props) {
|
|
60
63
|
const theme = useTheme<BaseThemePropertiesMobile>();
|
|
61
64
|
const navigation = useNavigation();
|
|
62
65
|
const { plugins } = usePickFromState(["plugins"]);
|
|
@@ -70,26 +73,38 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
|
|
|
70
73
|
fullDimensions: true,
|
|
71
74
|
});
|
|
72
75
|
|
|
73
|
-
const
|
|
76
|
+
const { screenData, pathname } = useRoute();
|
|
74
77
|
|
|
75
78
|
const currentRiver = useScreenData(
|
|
76
|
-
getScreenId(
|
|
79
|
+
getScreenId(screenData, navigation.activeRiver)
|
|
77
80
|
);
|
|
78
81
|
|
|
79
82
|
const { title } = useNavbarState();
|
|
80
83
|
|
|
81
|
-
const
|
|
82
|
-
(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
const hasMenu =
|
|
85
|
+
resolveNavigationPlugin({
|
|
86
|
+
category: "menu",
|
|
87
|
+
navigations: currentRiver.navigations,
|
|
88
|
+
plugins,
|
|
89
|
+
})?.identifier === "quick_brick_side_menu";
|
|
90
|
+
|
|
91
|
+
const navBarProps = React.useMemo<MobileNavBarPluginProps | null>(() => {
|
|
92
|
+
const props = getNavigationPropsV2({
|
|
93
|
+
currentRiver,
|
|
94
|
+
title,
|
|
95
|
+
category: "nav_bar",
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
if (props) {
|
|
99
|
+
return {
|
|
100
|
+
...props,
|
|
101
|
+
id: pathname,
|
|
102
|
+
pathname: pathname,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return null;
|
|
107
|
+
}, [currentRiver, pathname]);
|
|
93
108
|
|
|
94
109
|
const NavBar = React.useMemo(
|
|
95
110
|
() =>
|
|
@@ -97,12 +112,10 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
|
|
|
97
112
|
"nav_bar",
|
|
98
113
|
currentRiver,
|
|
99
114
|
plugins
|
|
100
|
-
) as React.ComponentType<MobileNavBarPluginProps>,
|
|
115
|
+
) as React.ComponentType<MobileNavBarPluginProps & { hasMenu: boolean }>,
|
|
101
116
|
[]
|
|
102
117
|
);
|
|
103
118
|
|
|
104
|
-
const { screenData, pathname } = routeData;
|
|
105
|
-
|
|
106
119
|
const offlinePlugin = getComponentModule({
|
|
107
120
|
plugins,
|
|
108
121
|
components: {},
|
|
@@ -133,9 +146,7 @@ export function Screen({ setToggleMenu, setCloseMenu }: Props) {
|
|
|
133
146
|
return (
|
|
134
147
|
<ScreenContextProvider pathname={pathname}>
|
|
135
148
|
<View style={style}>
|
|
136
|
-
<NavBar
|
|
137
|
-
{...{ ...(navBarProps as MobileNavBarPluginProps), id: pathname }}
|
|
138
|
-
/>
|
|
149
|
+
{navBarProps && <NavBar {...navBarProps} hasMenu={hasMenu} />}
|
|
139
150
|
|
|
140
151
|
<OfflineFallbackScreen screenData={targetScreenData}>
|
|
141
152
|
{/* @TODO RouteManager doesn't use props, can they be removed ? */}
|
|
@@ -6,6 +6,7 @@ import { ViewportEventContext, ViewportEvents } from "../ViewportEvents";
|
|
|
6
6
|
type Props = {
|
|
7
7
|
viewportEventsManager?: any;
|
|
8
8
|
children: React.ReactNode;
|
|
9
|
+
flatListRef?: any; // this ref is used to bind to children component
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export function ViewportTracker(props: Props) {
|
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
|
|
3
3
|
export function callOnChildren(children, method, ...args) {
|
|
4
4
|
const childMethod = React.Children.only(children).props[method];
|
|
5
|
-
childMethod && childMethod(...args);
|
|
5
|
+
typeof childMethod === "function" && childMethod?.(...args);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export function isInViewport(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createContext } from "@applicaster/zapp-react-native-utils/reactUtils/createContext";
|
|
2
|
+
import React from "react";
|
|
2
3
|
|
|
3
4
|
const initialContext = { toggleMenu: {}, closeMenu: {}, openMenu: {} };
|
|
4
5
|
|
|
@@ -16,3 +17,18 @@ const stateValidator = ({ property }) =>
|
|
|
16
17
|
property === "openMenu";
|
|
17
18
|
|
|
18
19
|
export const MenuToggleContext = createContext(initialContext, stateValidator);
|
|
20
|
+
|
|
21
|
+
export type MenuToggleContextType = {
|
|
22
|
+
toggleMenu: any;
|
|
23
|
+
setToggleMenu: () => void;
|
|
24
|
+
openMenu: any;
|
|
25
|
+
setOpenMenu: () => void;
|
|
26
|
+
closeMenu: any;
|
|
27
|
+
setCloseMenu: () => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const useMenuToggleContext = () => {
|
|
31
|
+
return React.useContext<MenuToggleContextType>(
|
|
32
|
+
MenuToggleContext.ReactContext
|
|
33
|
+
);
|
|
34
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { render } from "@testing-library/react-native";
|
|
2
|
+
import { ScreenContext, ScreenContextProvider, withScreenContext } from "../";
|
|
3
|
+
import React from "react";
|
|
4
|
+
|
|
5
|
+
describe("ScreenContext", () => {
|
|
6
|
+
describe("ScreneContext context", () => {
|
|
7
|
+
it("should return the context", () => {
|
|
8
|
+
expect(ScreenContext).toBeDefined();
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe("ScreenContextProvider", () => {
|
|
13
|
+
it("should return the provider", () => {
|
|
14
|
+
expect(ScreenContextProvider).toBeDefined();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe("withScreenContext", () => {
|
|
19
|
+
it("should return the context", () => {
|
|
20
|
+
const Component = () => null;
|
|
21
|
+
const WrappedComponent = withScreenContext(Component);
|
|
22
|
+
const { toJSON } = render(<WrappedComponent />);
|
|
23
|
+
|
|
24
|
+
expect(toJSON()).toMatchSnapshot();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
ReactNode,
|
|
4
|
+
useCallback,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
} from "react";
|
|
2
8
|
import {
|
|
3
9
|
useCurrentScreenData,
|
|
4
10
|
useNavigation,
|
|
@@ -7,27 +13,67 @@ import {
|
|
|
7
13
|
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
8
14
|
import { useModalNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ModalNavigationContext";
|
|
9
15
|
import { useNestedNavigationContext } from "@applicaster/zapp-react-native-ui-components/Contexts/NestedNavigationContext";
|
|
16
|
+
import { create, StoreApi, UseBoundStore } from "zustand";
|
|
17
|
+
import { useShallow } from "zustand/react/shallow";
|
|
18
|
+
import { Animated } from "react-native";
|
|
19
|
+
|
|
20
|
+
interface NavBarStoreState {
|
|
21
|
+
visible: boolean;
|
|
22
|
+
title: string;
|
|
23
|
+
summary: string;
|
|
24
|
+
setVisible: (state: boolean) => void;
|
|
25
|
+
setTitle: (title: string) => void;
|
|
26
|
+
setSummary: (subtitle: string) => void;
|
|
27
|
+
height: number;
|
|
28
|
+
scrollState: number;
|
|
29
|
+
isOnBottomNavBar: boolean;
|
|
30
|
+
scrollYAnimated: Animated.Value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface NavBarState {
|
|
34
|
+
visible: boolean;
|
|
35
|
+
title: string;
|
|
36
|
+
summary: string;
|
|
37
|
+
setVisible: (state: boolean) => void;
|
|
38
|
+
setTitle: (title: string) => void;
|
|
39
|
+
setSummary: (subtitle: string) => void;
|
|
40
|
+
}
|
|
10
41
|
|
|
11
42
|
type ScreenContextType = {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
title: string;
|
|
15
|
-
summary: string;
|
|
16
|
-
setVisible: (state: boolean) => void;
|
|
17
|
-
setTitle: (title: string) => void;
|
|
18
|
-
setSummary: (subtitle: string) => void;
|
|
19
|
-
};
|
|
43
|
+
_navBarStore: UseBoundStore<StoreApi<NavBarStoreState>>;
|
|
44
|
+
navBar: NavBarState;
|
|
20
45
|
legacyFormatScreenData: LegacyNavigationScreenData | null;
|
|
21
46
|
};
|
|
22
47
|
|
|
48
|
+
const createStore = () =>
|
|
49
|
+
create<NavBarStoreState>((set) => ({
|
|
50
|
+
title: "",
|
|
51
|
+
summary: "",
|
|
52
|
+
visible: true,
|
|
53
|
+
height: 0,
|
|
54
|
+
scrollState: 0,
|
|
55
|
+
isOnBottomNavBar: true,
|
|
56
|
+
scrollYAnimated: new Animated.Value(0),
|
|
57
|
+
setTitle(title) {
|
|
58
|
+
set({ title });
|
|
59
|
+
},
|
|
60
|
+
setSummary(summary) {
|
|
61
|
+
set({ summary });
|
|
62
|
+
},
|
|
63
|
+
setVisible(visible) {
|
|
64
|
+
set({ visible });
|
|
65
|
+
},
|
|
66
|
+
}));
|
|
67
|
+
|
|
23
68
|
export const ScreenContext = createContext<ScreenContextType>({
|
|
69
|
+
_navBarStore: createStore(),
|
|
24
70
|
navBar: {
|
|
25
71
|
visible: true,
|
|
26
72
|
title: "",
|
|
27
73
|
summary: "",
|
|
28
|
-
setVisible: (_state) =>
|
|
29
|
-
setTitle: (_title) =>
|
|
30
|
-
setSummary: (_subtitle) =>
|
|
74
|
+
setVisible: (_state) => void 0,
|
|
75
|
+
setTitle: (_title) => void 0,
|
|
76
|
+
setSummary: (_subtitle) => void 0,
|
|
31
77
|
},
|
|
32
78
|
legacyFormatScreenData: {} as LegacyNavigationScreenData,
|
|
33
79
|
});
|
|
@@ -53,9 +99,30 @@ export function ScreenContextProvider({
|
|
|
53
99
|
const isNested = useNestedNavigationContext();
|
|
54
100
|
const currentScreenScreenData = useCurrentScreenData();
|
|
55
101
|
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
102
|
+
const screenNavBarStateRef =
|
|
103
|
+
useRef<null | ReturnType<typeof createStore>>(null);
|
|
104
|
+
|
|
105
|
+
const getScreenNavBarState = useCallback(() => {
|
|
106
|
+
if (screenNavBarStateRef.current !== null) {
|
|
107
|
+
return screenNavBarStateRef.current;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const navBarState = createStore();
|
|
111
|
+
screenNavBarStateRef.current = navBarState;
|
|
112
|
+
|
|
113
|
+
return navBarState;
|
|
114
|
+
}, []);
|
|
115
|
+
|
|
116
|
+
const screenNavBarState = getScreenNavBarState()(
|
|
117
|
+
useShallow((state) => ({
|
|
118
|
+
visible: state.visible,
|
|
119
|
+
title: state.title,
|
|
120
|
+
summary: state.summary,
|
|
121
|
+
setTitle: state.setTitle,
|
|
122
|
+
setSummary: state.setSummary,
|
|
123
|
+
setVisible: state.setVisible,
|
|
124
|
+
}))
|
|
125
|
+
);
|
|
59
126
|
|
|
60
127
|
const isHook = pathname.includes("hook");
|
|
61
128
|
|
|
@@ -73,26 +140,28 @@ export function ScreenContextProvider({
|
|
|
73
140
|
const isVisible = isNavBarVisible(
|
|
74
141
|
pathname,
|
|
75
142
|
currentScreenScreenData, // what fallback should be if currentScreenData is not available?
|
|
76
|
-
|
|
143
|
+
screenNavBarState.visible,
|
|
77
144
|
canGoBack(isHook, pathname),
|
|
78
145
|
videoModalState
|
|
79
146
|
);
|
|
80
147
|
|
|
81
|
-
const navBarState = useMemo(
|
|
82
|
-
|
|
83
|
-
title:
|
|
84
|
-
summary:
|
|
148
|
+
const navBarState = useMemo(
|
|
149
|
+
() => ({
|
|
150
|
+
title: screenNavBarState.title,
|
|
151
|
+
summary: screenNavBarState.summary,
|
|
85
152
|
visible: isVisible,
|
|
86
|
-
setTitle:
|
|
87
|
-
setSummary:
|
|
88
|
-
setVisible:
|
|
89
|
-
}
|
|
90
|
-
|
|
153
|
+
setTitle: screenNavBarState.setTitle,
|
|
154
|
+
setSummary: screenNavBarState.setSummary,
|
|
155
|
+
setVisible: screenNavBarState.setVisible,
|
|
156
|
+
}),
|
|
157
|
+
[isVisible, screenNavBarState.title, screenNavBarState.summary]
|
|
158
|
+
);
|
|
91
159
|
|
|
92
160
|
return (
|
|
93
161
|
<ScreenContext.Provider
|
|
94
162
|
value={useMemo(
|
|
95
163
|
() => ({
|
|
164
|
+
_navBarStore: getScreenNavBarState(),
|
|
96
165
|
navBar: navBarState,
|
|
97
166
|
legacyFormatScreenData: routeScreenData,
|
|
98
167
|
}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/zapp-react-native-ui-components",
|
|
3
|
-
"version": "12.0.0-rc.
|
|
3
|
+
"version": "12.0.0-rc.54",
|
|
4
4
|
"description": "Applicaster Zapp React Native ui components for the Quick Brick App",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -34,10 +34,10 @@
|
|
|
34
34
|
"redux-mock-store": "^1.5.3"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@applicaster/applicaster-types": "12.0.0-rc.
|
|
38
|
-
"@applicaster/zapp-react-native-bridge": "12.0.0-rc.
|
|
39
|
-
"@applicaster/zapp-react-native-redux": "12.0.0-rc.
|
|
40
|
-
"@applicaster/zapp-react-native-utils": "12.0.0-rc.
|
|
37
|
+
"@applicaster/applicaster-types": "12.0.0-rc.54",
|
|
38
|
+
"@applicaster/zapp-react-native-bridge": "12.0.0-rc.54",
|
|
39
|
+
"@applicaster/zapp-react-native-redux": "12.0.0-rc.54",
|
|
40
|
+
"@applicaster/zapp-react-native-utils": "12.0.0-rc.54",
|
|
41
41
|
"promise": "^8.3.0",
|
|
42
42
|
"react-router-native": "^5.1.2",
|
|
43
43
|
"url": "^0.11.0",
|
|
File without changes
|