@applicaster/zapp-react-native-ui-components 12.0.0-alpha.4757075613 → 12.0.0-alpha.4837064762
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/BaseFocusable/index.tsx +1 -1
- package/Components/Cell/Cell.tsx +5 -1
- package/Components/Cell/CellWithFocusable.tsx +17 -5
- package/Components/FocusableGroup/index.tsx +1 -0
- package/Components/HandlePlayable/HandlePlayable.tsx +3 -0
- package/Components/Layout/TV/ScreenLayoutContextProvider.tsx +2 -2
- package/Components/Layout/TV/index.tsx +124 -25
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -3
- package/Components/MasterCell/DefaultComponents/LiveImage/index.tsx +14 -1
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
- package/Components/MasterCell/utils/index.ts +16 -5
- package/Components/PlayerContainer/PlayerContainer.tsx +17 -3
- package/Components/PlayerImageBackground/index.tsx +34 -8
- package/Components/River/ComponentsMap/ComponentsMap.tsx +85 -22
- package/Components/River/__tests__/componentsMap.test.js +6 -0
- package/Components/Screen/TV/index.web.tsx +151 -0
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
- package/Components/Screen/index.tsx +35 -24
- package/Components/ScreenResolver/index.tsx +3 -1
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +20 -5
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +0 -5
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +342 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +151 -0
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +438 -0
- package/Components/VideoModal/ModalAnimation/ModalAnimationContext.tsx +143 -0
- package/Components/VideoModal/ModalAnimation/index.ts +15 -0
- package/Components/VideoModal/ModalAnimation/utils.ts +299 -0
- package/Components/VideoModal/PlayerWrapper.tsx +64 -41
- package/Components/VideoModal/VideoModal.tsx +8 -25
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +6 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +151 -119
- package/Components/VideoModal/utils.ts +3 -3
- 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/Contexts/ZappPipesContext/ZappPipesEntryContext.ts +1 -1
- package/package.json +5 -5
- package/Components/VideoModal/hooks/usePosition.ts +0 -50
- /package/Contexts/{index.js → index.ts} +0 -0
|
@@ -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
|
/>
|
|
@@ -6,6 +6,12 @@ import configureStore from "redux-mock-store";
|
|
|
6
6
|
|
|
7
7
|
import * as themeUtils from "@applicaster/zapp-react-native-utils/theme";
|
|
8
8
|
|
|
9
|
+
// silences the errors related to React-native-gesture-handler in tests
|
|
10
|
+
jest.mock(
|
|
11
|
+
"@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation",
|
|
12
|
+
() => () => null
|
|
13
|
+
);
|
|
14
|
+
|
|
9
15
|
jest.mock("react-native-safe-area-context", () => ({
|
|
10
16
|
useSafeAreaInsets: () => ({ top: 50 }),
|
|
11
17
|
}));
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { last, pathOr } from "ramda";
|
|
3
|
+
import { ScreenResolver } from "../../ScreenResolver";
|
|
4
|
+
import {
|
|
5
|
+
getNavigationProps,
|
|
6
|
+
getPathAttributes,
|
|
7
|
+
resolveNavigationPlugin,
|
|
8
|
+
} from "@applicaster/zapp-react-native-utils/navigationUtils";
|
|
9
|
+
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
10
|
+
import { NavBarContainer } from "../../Layout/TV/NavBarContainer";
|
|
11
|
+
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
12
|
+
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
13
|
+
|
|
14
|
+
type Components = {
|
|
15
|
+
NavBar: React.ComponentType<any>;
|
|
16
|
+
Background: React.ComponentType<any>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type Props = {
|
|
20
|
+
route: string;
|
|
21
|
+
Components: Components;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const isPlayer = (routeState): boolean => {
|
|
25
|
+
const pluginType = pathOr(
|
|
26
|
+
"unknown_plugin_type",
|
|
27
|
+
["state", "screen", "plugin_type"],
|
|
28
|
+
routeState
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
return pluginType === "player";
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const getActiveRiver = ({
|
|
35
|
+
screenId,
|
|
36
|
+
screenType,
|
|
37
|
+
routeState,
|
|
38
|
+
rivers,
|
|
39
|
+
fallbackActiveRiver,
|
|
40
|
+
}) => {
|
|
41
|
+
if (rivers[screenId]) {
|
|
42
|
+
// river presents
|
|
43
|
+
return screenType === "hooks"
|
|
44
|
+
? routeState?.state?.entry?.payload
|
|
45
|
+
: routeState?.state?.screen;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// screenId is not presented into rivers, use fallback instead
|
|
49
|
+
return fallbackActiveRiver;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const getNavigations = ({
|
|
53
|
+
screenId,
|
|
54
|
+
screenType,
|
|
55
|
+
routeState,
|
|
56
|
+
rivers,
|
|
57
|
+
fallbackNavigations,
|
|
58
|
+
}) => {
|
|
59
|
+
if (rivers[screenId]) {
|
|
60
|
+
// river presents
|
|
61
|
+
return screenType === "hooks"
|
|
62
|
+
? routeState?.state?.entry?.payload.navigations
|
|
63
|
+
: routeState?.state?.screen?.navigations;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// screenId is not presented into rivers, use fallback instead
|
|
67
|
+
return fallbackNavigations;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const Screen = (props: Props) => {
|
|
71
|
+
if (!props.route) {
|
|
72
|
+
throw new Error("Required props route is missing");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const navigator = useNavigation();
|
|
76
|
+
const { plugins = [], rivers = [] } = usePickFromState(["plugins", "rivers"]);
|
|
77
|
+
|
|
78
|
+
const pathAttributes = getPathAttributes({ pathname: props.route });
|
|
79
|
+
const routeState = navigator.getStackForPathname(props.route);
|
|
80
|
+
|
|
81
|
+
const { screenType, screenId } = last(pathAttributes);
|
|
82
|
+
|
|
83
|
+
// console.log("debug_2", "Screen", {
|
|
84
|
+
// screenType,
|
|
85
|
+
// routeState,
|
|
86
|
+
// route: props.route,
|
|
87
|
+
// navigator,
|
|
88
|
+
// });
|
|
89
|
+
|
|
90
|
+
const activeRiver = getActiveRiver({
|
|
91
|
+
screenId,
|
|
92
|
+
screenType,
|
|
93
|
+
routeState,
|
|
94
|
+
rivers,
|
|
95
|
+
fallbackActiveRiver: navigator.activeRiver,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const navigationProps = getNavigationProps({
|
|
99
|
+
navigator: {
|
|
100
|
+
// @ts-ignore
|
|
101
|
+
activeRiver,
|
|
102
|
+
// @ts-ignore
|
|
103
|
+
screenTitle: routeState.state.entry?.title || routeState.screen?.name,
|
|
104
|
+
},
|
|
105
|
+
category: "menu",
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const navigations = getNavigations({
|
|
109
|
+
screenId,
|
|
110
|
+
screenType,
|
|
111
|
+
routeState,
|
|
112
|
+
rivers,
|
|
113
|
+
fallbackNavigations: navigator.activeRiver.navigations,
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const menuPlugin = resolveNavigationPlugin({
|
|
117
|
+
category: "menu",
|
|
118
|
+
navigations,
|
|
119
|
+
plugins,
|
|
120
|
+
}) as QuickBrickPlugin;
|
|
121
|
+
|
|
122
|
+
const NavBar = (props.Components.NavBar ||
|
|
123
|
+
menuPlugin.module) as React.ComponentType<any>;
|
|
124
|
+
|
|
125
|
+
const isNavBarVisible = !isPlayer(routeState);
|
|
126
|
+
|
|
127
|
+
const screenData =
|
|
128
|
+
screenType === "hooks"
|
|
129
|
+
? routeState?.state?.entry
|
|
130
|
+
: routeState?.state?.screen;
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<>
|
|
134
|
+
<NavBarContainer isVisible={isNavBarVisible} onReady={noop}>
|
|
135
|
+
<NavBar
|
|
136
|
+
groupId={props.route}
|
|
137
|
+
isVisible={isNavBarVisible}
|
|
138
|
+
menuPlugin={menuPlugin}
|
|
139
|
+
navigationProps={navigationProps}
|
|
140
|
+
// Maybe activeRiver?
|
|
141
|
+
/>
|
|
142
|
+
</NavBarContainer>
|
|
143
|
+
<ScreenResolver
|
|
144
|
+
screenType={screenType}
|
|
145
|
+
screenId={screenId}
|
|
146
|
+
screenData={screenData}
|
|
147
|
+
groupId={props.route}
|
|
148
|
+
/>
|
|
149
|
+
</>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
@@ -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 ? */}
|
|
@@ -32,12 +32,13 @@ type Props = {
|
|
|
32
32
|
nextFocusLeft?: React.Ref<any>;
|
|
33
33
|
nextFocusUp?: React.Ref<any>;
|
|
34
34
|
};
|
|
35
|
+
groupId?: string;
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
export function ScreenResolverComponent(props: Props) {
|
|
38
39
|
useScreenAnalytics(props);
|
|
39
40
|
|
|
40
|
-
const { screenType, screenId, screenData } = props;
|
|
41
|
+
const { screenType, screenId, screenData, groupId } = props;
|
|
41
42
|
|
|
42
43
|
const { hookPlugin } = screenData || {};
|
|
43
44
|
|
|
@@ -81,6 +82,7 @@ export function ScreenResolverComponent(props: Props) {
|
|
|
81
82
|
item={screenData}
|
|
82
83
|
mode={mode === "PIP" ? "PIP" : "FULLSCREEN"}
|
|
83
84
|
isModal={false}
|
|
85
|
+
groupId={groupId}
|
|
84
86
|
/>
|
|
85
87
|
);
|
|
86
88
|
}
|
|
@@ -7,6 +7,10 @@ import { ThemeContext } from "@applicaster/zapp-react-native-utils/theme";
|
|
|
7
7
|
import * as navigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
8
8
|
|
|
9
9
|
import { PlayerLiveImage } from "../PlayerLiveImageComponent";
|
|
10
|
+
import * as useNavigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
|
|
11
|
+
|
|
12
|
+
import { Provider } from "react-redux";
|
|
13
|
+
import configureStore from "redux-mock-store";
|
|
10
14
|
|
|
11
15
|
const seekTo = jest.fn();
|
|
12
16
|
|
|
@@ -19,14 +23,25 @@ jest.mock(
|
|
|
19
23
|
})
|
|
20
24
|
);
|
|
21
25
|
|
|
26
|
+
jest
|
|
27
|
+
.spyOn(useNavigationHooks, "useNavigation")
|
|
28
|
+
.mockImplementation(() => ({ videoModalState: { visible: false } }));
|
|
29
|
+
|
|
22
30
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
|
|
23
31
|
|
|
32
|
+
const mockStore = configureStore();
|
|
33
|
+
|
|
34
|
+
const store = mockStore({ appData: {} });
|
|
35
|
+
|
|
24
36
|
const Wrapper = ({ children }: { children: React.ReactChildren }) => (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
37
|
+
/* @ts-ignore */
|
|
38
|
+
<Provider store={store}>
|
|
39
|
+
<ThemeContext.Provider
|
|
40
|
+
value={{ themes: { myTheme: {} }, selectedThemeId: "myTheme" }}
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</ThemeContext.Provider>
|
|
44
|
+
</Provider>
|
|
30
45
|
);
|
|
31
46
|
|
|
32
47
|
describe("PlayerLiveImageComponent", () => {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Animated, ViewStyle } from "react-native";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
useModalAnimationContext,
|
|
6
|
+
PlayerAnimationStateEnum,
|
|
7
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
8
|
+
import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
style: ViewStyle[];
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const AnimatedPlayerModalWrapper = (props: Props) => {
|
|
16
|
+
const {
|
|
17
|
+
playerAnimationState,
|
|
18
|
+
animatedValues: { lastScrollY, dragScrollY, translateYOffset },
|
|
19
|
+
modalSnapPoints,
|
|
20
|
+
setStartComponentsAnimation,
|
|
21
|
+
lastScrollYValue,
|
|
22
|
+
} = useModalAnimationContext();
|
|
23
|
+
|
|
24
|
+
const { height: screenHeight } = useDimensions("screen", {
|
|
25
|
+
deviceInfo: true,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const interpolateConfig: Animated.InterpolationConfigType = React.useMemo(
|
|
29
|
+
() => ({
|
|
30
|
+
inputRange: modalSnapPoints,
|
|
31
|
+
outputRange: modalSnapPoints,
|
|
32
|
+
extrapolate: "clamp",
|
|
33
|
+
}),
|
|
34
|
+
[modalSnapPoints]
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
let translateY;
|
|
38
|
+
|
|
39
|
+
if (playerAnimationState === PlayerAnimationStateEnum.drag_player) {
|
|
40
|
+
translateY = translateYOffset.interpolate(interpolateConfig);
|
|
41
|
+
} else {
|
|
42
|
+
const reverseLastScrollY = Animated.multiply(
|
|
43
|
+
new Animated.Value(-1),
|
|
44
|
+
lastScrollY
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
translateY = Animated.add(
|
|
48
|
+
translateYOffset,
|
|
49
|
+
Animated.add(dragScrollY, reverseLastScrollY)
|
|
50
|
+
).interpolate(interpolateConfig);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
React.useEffect(() => {
|
|
54
|
+
const translateYListener = translateY.addListener(({ value }) => {
|
|
55
|
+
const preparedValue = Math.round(
|
|
56
|
+
Math.abs(value) - lastScrollYValue.current
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
(playerAnimationState === PlayerAnimationStateEnum.minimize ||
|
|
60
|
+
playerAnimationState === PlayerAnimationStateEnum.maximaze) &&
|
|
61
|
+
setStartComponentsAnimation(
|
|
62
|
+
preparedValue >= Math.round((screenHeight * 10) / 100)
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return () => {
|
|
67
|
+
translateYListener && translateY.removeListener(translateYListener);
|
|
68
|
+
};
|
|
69
|
+
}, [playerAnimationState]);
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<Animated.View
|
|
73
|
+
style={[props.style, { transform: [{ translateY: translateY }] }]}
|
|
74
|
+
>
|
|
75
|
+
{props.children}
|
|
76
|
+
</Animated.View>
|
|
77
|
+
);
|
|
78
|
+
};
|