@applicaster/zapp-react-native-ui-components 12.0.0-alpha.9611121395 → 12.0.0-alpha.9709055278
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/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 +14 -2
- package/Components/PlayerImageBackground/index.tsx +34 -8
- package/Components/River/ComponentsMap/ComponentsMap.tsx +86 -42
- package/Components/River/__tests__/componentsMap.test.js +6 -0
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +4 -0
- 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 +25 -42
- 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/package.json +5 -5
- package/Components/VideoModal/hooks/usePosition.ts +0 -50
- /package/Contexts/{index.js → index.ts} +0 -0
|
@@ -43,14 +43,16 @@ function Image({
|
|
|
43
43
|
[source, error]
|
|
44
44
|
);
|
|
45
45
|
|
|
46
|
+
const _source = shouldRenderImg
|
|
47
|
+
? withDimensions(source)
|
|
48
|
+
: defaultPlaceHolderImage;
|
|
49
|
+
|
|
46
50
|
return (
|
|
47
51
|
// @ts-ignore
|
|
48
52
|
<MemoizedImage
|
|
49
53
|
style={style as ImageStyle}
|
|
50
54
|
onError={() => setErrorState(true)}
|
|
51
|
-
source={
|
|
52
|
-
shouldRenderImg ? withDimensions(source) : defaultPlaceHolderImage
|
|
53
|
-
}
|
|
55
|
+
source={_source?.uri ? _source : undefined}
|
|
54
56
|
{...R.omit(["source"], otherProps)}
|
|
55
57
|
/>
|
|
56
58
|
);
|
|
@@ -177,10 +177,23 @@ const getPlayerConfig = (player_screen_id, actionIdentifier) => {
|
|
|
177
177
|
const positionAbsolute: ViewStyle = { position: "absolute" };
|
|
178
178
|
|
|
179
179
|
const LiveImageComponent = (props: LiveImageProps) => {
|
|
180
|
-
const {
|
|
180
|
+
const {
|
|
181
|
+
item,
|
|
182
|
+
style: componentStyle,
|
|
183
|
+
cellUUID,
|
|
184
|
+
imageKey,
|
|
185
|
+
actionIdentifier,
|
|
186
|
+
state,
|
|
187
|
+
} = props;
|
|
181
188
|
|
|
182
189
|
const component = useUIComponentContext();
|
|
183
190
|
|
|
191
|
+
// Fix for blinking on state change
|
|
192
|
+
const style = React.useMemo(
|
|
193
|
+
() => ({ ...componentStyle, backgroundColor: "transparent" }),
|
|
194
|
+
[componentStyle]
|
|
195
|
+
);
|
|
196
|
+
|
|
184
197
|
const componentType = React.useMemo(
|
|
185
198
|
() => getPropComponentType(component),
|
|
186
199
|
[component?.id]
|
|
@@ -125,13 +125,24 @@ export const useFilterChildren = <
|
|
|
125
125
|
|
|
126
126
|
const filteredChildren = children.filter((child) => {
|
|
127
127
|
const item = child.props.item;
|
|
128
|
-
const
|
|
128
|
+
const actionIdentifier = child.props.pluginIdentifier;
|
|
129
|
+
const action = actions.actions[actionIdentifier];
|
|
130
|
+
|
|
129
131
|
// context value of specific plugin
|
|
130
|
-
|
|
132
|
+
if (action?.module && action.module.context) {
|
|
133
|
+
const currentValue = action.module.context._currentValue;
|
|
134
|
+
|
|
135
|
+
return currentValue?.isActionAvailable
|
|
136
|
+
? currentValue.isActionAvailable(item)
|
|
137
|
+
: true;
|
|
138
|
+
}
|
|
131
139
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
:
|
|
140
|
+
masterCellLogger.error({
|
|
141
|
+
message: `Action plugin for ${actionIdentifier} could not be found, check the configuration of your action button`,
|
|
142
|
+
data: { item, action: child.props.pluginIdentifier },
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return false;
|
|
135
146
|
});
|
|
136
147
|
|
|
137
148
|
return filteredChildren;
|
|
@@ -54,6 +54,11 @@ import { toNumber } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
|
54
54
|
import { usePlayNextOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayNextOverlay";
|
|
55
55
|
import { PlayNextState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/OverlayObserver/OverlaysObserver";
|
|
56
56
|
|
|
57
|
+
import {
|
|
58
|
+
useModalAnimationContext,
|
|
59
|
+
PlayerAnimationStateEnum,
|
|
60
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
61
|
+
|
|
57
62
|
type Props = {
|
|
58
63
|
Player: React.ComponentType<any>;
|
|
59
64
|
PlayerLoadingView?: React.ComponentType<any>; // 👀 we are not receiving this prop
|
|
@@ -229,6 +234,9 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
229
234
|
const screenData = useTargetScreenData(item);
|
|
230
235
|
const { setVisible: showNavBar } = useSetNavbarState();
|
|
231
236
|
|
|
237
|
+
const { isActiveGesture, startComponentsAnimation, setPlayerAnimationState } =
|
|
238
|
+
useModalAnimationContext();
|
|
239
|
+
|
|
232
240
|
const playerEvent = (event, ...args) => {
|
|
233
241
|
playerManager.invokeHandler(event, ...args);
|
|
234
242
|
};
|
|
@@ -446,7 +454,7 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
446
454
|
if (disableMiniPlayer) {
|
|
447
455
|
navigator.closeVideoModal();
|
|
448
456
|
} else {
|
|
449
|
-
|
|
457
|
+
setPlayerAnimationState(PlayerAnimationStateEnum.minimize);
|
|
450
458
|
}
|
|
451
459
|
}
|
|
452
460
|
|
|
@@ -641,7 +649,11 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
641
649
|
autoplay={true}
|
|
642
650
|
controls={false}
|
|
643
651
|
disableCastAction={disableCastAction}
|
|
644
|
-
docked={
|
|
652
|
+
docked={
|
|
653
|
+
navigator.isVideoModalDocked() &&
|
|
654
|
+
!startComponentsAnimation &&
|
|
655
|
+
!isActiveGesture
|
|
656
|
+
}
|
|
645
657
|
entry={item}
|
|
646
658
|
fullscreen={mode === VideoModalMode.FULLSCREEN}
|
|
647
659
|
inline={inline}
|
|
@@ -1,38 +1,64 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
|
2
|
-
import { ImageBackground } from "react-native";
|
|
2
|
+
import { ImageBackground, View } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
5
|
+
import {
|
|
6
|
+
AnimationComponent,
|
|
7
|
+
ComponentAnimationType,
|
|
8
|
+
useModalAnimationContext,
|
|
9
|
+
PlayerAnimationStateEnum,
|
|
10
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
5
11
|
|
|
6
12
|
type Props = PropsWithChildren<{
|
|
7
13
|
entry: ZappEntry;
|
|
8
14
|
style?: { [K: string]: any };
|
|
9
15
|
imageStyle?: { [K: string]: any };
|
|
10
16
|
imageKey?: string;
|
|
17
|
+
defaultImageDimensions?: { [K: string]: any };
|
|
11
18
|
}>;
|
|
12
19
|
|
|
20
|
+
const imageSize = { width: "100%", height: "100%" };
|
|
21
|
+
|
|
13
22
|
const PlayerImageBackgroundComponent = ({
|
|
14
23
|
entry,
|
|
15
24
|
children,
|
|
16
25
|
style,
|
|
17
26
|
imageStyle,
|
|
18
27
|
imageKey,
|
|
28
|
+
defaultImageDimensions,
|
|
19
29
|
}: Props) => {
|
|
20
30
|
const source = React.useMemo(
|
|
21
31
|
() => ({ uri: imageSrcFromMediaItem(entry, imageKey) }),
|
|
22
32
|
[imageKey, entry]
|
|
23
33
|
);
|
|
24
34
|
|
|
35
|
+
const { playerAnimationState } = useModalAnimationContext();
|
|
36
|
+
|
|
25
37
|
if (!source) return <>{children}</>;
|
|
26
38
|
|
|
27
39
|
return (
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
<View
|
|
41
|
+
style={
|
|
42
|
+
playerAnimationState === PlayerAnimationStateEnum.maximaze
|
|
43
|
+
? defaultImageDimensions
|
|
44
|
+
: style
|
|
45
|
+
}
|
|
33
46
|
>
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
<AnimationComponent
|
|
48
|
+
style={style}
|
|
49
|
+
animationType={ComponentAnimationType.player}
|
|
50
|
+
additionalData={defaultImageDimensions}
|
|
51
|
+
>
|
|
52
|
+
<ImageBackground
|
|
53
|
+
resizeMode="cover"
|
|
54
|
+
style={imageSize}
|
|
55
|
+
imageStyle={imageStyle}
|
|
56
|
+
source={source}
|
|
57
|
+
>
|
|
58
|
+
{children}
|
|
59
|
+
</ImageBackground>
|
|
60
|
+
</AnimationComponent>
|
|
61
|
+
</View>
|
|
36
62
|
);
|
|
37
63
|
};
|
|
38
64
|
|
|
@@ -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,44 +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;
|
|
202
|
-
|
|
203
|
-
const oldState = useScreenScrollStore.getState();
|
|
204
|
-
const scrollingVelocity = isScrollingDone ? 0 : 1;
|
|
205
|
-
const scrollPosition = y;
|
|
206
|
-
|
|
207
|
-
if (
|
|
208
|
-
scrollingVelocity !== oldState.scrollingVelocity ||
|
|
209
|
-
scrollPosition !== oldState.scrollPosition
|
|
210
|
-
) {
|
|
211
|
-
useScreenScrollStore.setState({
|
|
212
|
-
scrollingVelocity,
|
|
213
|
-
scrollPosition,
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
[]
|
|
218
|
-
);
|
|
201
|
+
const navBarStore = useScreenContextV2()._navBarStore;
|
|
219
202
|
|
|
220
|
-
const
|
|
221
|
-
({
|
|
222
|
-
onScrollFlatList({ nativeEvent }, true);
|
|
223
|
-
},
|
|
224
|
-
[onScrollFlatList]
|
|
203
|
+
const scrollY = navBarStore(
|
|
204
|
+
useShallow(({ scrollYAnimated }) => scrollYAnimated)
|
|
225
205
|
);
|
|
226
206
|
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
)
|
|
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
|
+
}, []);
|
|
235
262
|
|
|
236
263
|
if (shouldShowLoadingError) {
|
|
237
264
|
return <RiverError />;
|
|
@@ -248,6 +275,9 @@ function ComponentsMapComponent(props: Props) {
|
|
|
248
275
|
>
|
|
249
276
|
<ViewportTracker>
|
|
250
277
|
<FlatList
|
|
278
|
+
ref={(ref) => {
|
|
279
|
+
flatListRef.current = ref;
|
|
280
|
+
}}
|
|
251
281
|
// Fix for WebView rerender crashes on Android API 28+
|
|
252
282
|
// https://github.com/react-native-webview/react-native-webview/issues/1915#issuecomment-964035468
|
|
253
283
|
overScrollMode={Platform.OS === "android" ? "never" : "auto"}
|
|
@@ -267,10 +297,24 @@ function ComponentsMapComponent(props: Props) {
|
|
|
267
297
|
}
|
|
268
298
|
ListFooterComponent={renderFooter}
|
|
269
299
|
refreshControl={refreshControl}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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}
|
|
317
|
+
scrollEventThrottle={16}
|
|
274
318
|
{...scrollViewExtraProps}
|
|
275
319
|
/>
|
|
276
320
|
</ViewportTracker>
|
|
@@ -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
|
}));
|
|
@@ -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=""
|
|
@@ -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
|
+
};
|