@applicaster/zapp-react-native-ui-components 12.0.0-alpha.9262886003 → 12.0.0-alpha.9433151351
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/Cell/Cell.tsx +2 -2
- package/Components/Cell/CellWithFocusable.tsx +21 -14
- package/Components/Cell/TvOSCellComponent.tsx +2 -2
- package/Components/FocusableCell/index.tsx +7 -7
- package/Components/Image/utils/index.ts +21 -11
- package/Components/MasterCell/DefaultComponents/Toggle.tsx +5 -1
- package/Components/PlayerContainer/PlayerContainer.tsx +62 -29
- package/Components/PlayerImageBackground/index.tsx +34 -8
- package/Components/River/__tests__/componentsMap.test.js +7 -0
- package/Components/Screen/__tests__/Screen.test.tsx +5 -1
- package/Components/Screen/__tests__/__snapshots__/Screen.test.tsx.snap +10 -2
- package/Components/Screen/index.tsx +14 -12
- package/Components/Tabs/TV/styles.ts +1 -1
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +25 -5
- package/Components/VideoModal/ModalAnimation/AnimatedPlayerModalWrapper.tsx +78 -0
- package/Components/VideoModal/ModalAnimation/AnimatedScrollModal.tsx +322 -0
- package/Components/VideoModal/ModalAnimation/AnimatedVideoPlayerComponent.tsx +144 -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/Decorators/ComponentsMapWrapper/withComponentsMapProvider.tsx +7 -2
- package/package.json +5 -5
- package/Components/VideoModal/hooks/usePosition.ts +0 -50
package/Components/Cell/Cell.tsx
CHANGED
|
@@ -202,7 +202,7 @@ export class CellComponent extends React.Component<Props> {
|
|
|
202
202
|
groupId,
|
|
203
203
|
isFocusable = true,
|
|
204
204
|
skipFocusManagerRegistration,
|
|
205
|
-
behavior
|
|
205
|
+
behavior,
|
|
206
206
|
} = this.props;
|
|
207
207
|
|
|
208
208
|
const { id } = item;
|
|
@@ -263,7 +263,7 @@ export class CellComponent extends React.Component<Props> {
|
|
|
263
263
|
item,
|
|
264
264
|
focused: this.isCellFocused(focused),
|
|
265
265
|
scrollTo: this.scrollToIndex(event),
|
|
266
|
-
behavior
|
|
266
|
+
behavior,
|
|
267
267
|
}}
|
|
268
268
|
/>
|
|
269
269
|
);
|
|
@@ -35,18 +35,18 @@ const useCellFocusedState = (groupId: string, id: string) => {
|
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
type Props = {
|
|
38
|
-
item: ZappEntry
|
|
39
|
-
CellRenderer: React.ComponentType<{ item: Object
|
|
40
|
-
id: string
|
|
41
|
-
groupId: string
|
|
42
|
-
onFocus: Function
|
|
43
|
-
index: number
|
|
44
|
-
scrollTo: Function
|
|
45
|
-
preferredFocus?: boolean
|
|
46
|
-
skipFocusManagerRegistration?: boolean
|
|
47
|
-
isFocusable?: boolean
|
|
48
|
-
behavior: Behavior
|
|
49
|
-
selected?: boolean
|
|
38
|
+
item: ZappEntry;
|
|
39
|
+
CellRenderer: React.ComponentType<{ item: Object; state: string }>;
|
|
40
|
+
id: string;
|
|
41
|
+
groupId: string;
|
|
42
|
+
onFocus: Function;
|
|
43
|
+
index: number;
|
|
44
|
+
scrollTo: Function;
|
|
45
|
+
preferredFocus?: boolean;
|
|
46
|
+
skipFocusManagerRegistration?: boolean;
|
|
47
|
+
isFocusable?: boolean;
|
|
48
|
+
behavior: Behavior;
|
|
49
|
+
selected?: boolean;
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
export function CellWithFocusable(props: Props) {
|
|
@@ -62,11 +62,18 @@ export function CellWithFocusable(props: Props) {
|
|
|
62
62
|
skipFocusManagerRegistration,
|
|
63
63
|
isFocusable,
|
|
64
64
|
behavior,
|
|
65
|
-
selected
|
|
65
|
+
selected,
|
|
66
66
|
} = props;
|
|
67
67
|
|
|
68
68
|
const isFocused = useCellFocusedState(groupId, id);
|
|
69
|
-
|
|
69
|
+
|
|
70
|
+
const state = useCellState({
|
|
71
|
+
id: item.id,
|
|
72
|
+
behavior,
|
|
73
|
+
focused: isFocused,
|
|
74
|
+
selected,
|
|
75
|
+
});
|
|
76
|
+
|
|
70
77
|
const [focusedButtonId, setFocusedButtonId] = React.useState(undefined);
|
|
71
78
|
|
|
72
79
|
// for horizontal scrolling
|
|
@@ -249,7 +249,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
249
249
|
hasReceivedFocus,
|
|
250
250
|
groupId,
|
|
251
251
|
isFocusable,
|
|
252
|
-
behavior
|
|
252
|
+
behavior,
|
|
253
253
|
} = this.props;
|
|
254
254
|
|
|
255
255
|
const { id } = item;
|
|
@@ -310,7 +310,7 @@ export class TvOSCellComponent extends React.Component<Props, State> {
|
|
|
310
310
|
item,
|
|
311
311
|
focused: this.props.focused || selectedCell || focused,
|
|
312
312
|
scrollTo: this.scrollTo,
|
|
313
|
-
behavior
|
|
313
|
+
behavior,
|
|
314
314
|
}}
|
|
315
315
|
/>
|
|
316
316
|
);
|
|
@@ -3,12 +3,12 @@ import { Platform } from "react-native";
|
|
|
3
3
|
import { useCellState } from "../MasterCell/utils";
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
|
-
index: number
|
|
7
|
-
item: ZappEntry
|
|
8
|
-
focused: boolean
|
|
9
|
-
scrollTo?: (index: number) => void
|
|
10
|
-
CellRenderer: React.ComponentType<{ item: Object
|
|
11
|
-
behavior: Behavior
|
|
6
|
+
index: number;
|
|
7
|
+
item: ZappEntry;
|
|
8
|
+
focused: boolean;
|
|
9
|
+
scrollTo?: (index: number) => void;
|
|
10
|
+
CellRenderer: React.ComponentType<{ item: Object; state: string }>;
|
|
11
|
+
behavior: Behavior;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
const isAndroid = Platform.OS === "android";
|
|
@@ -20,7 +20,7 @@ export function FocusableCell(props: Props) {
|
|
|
20
20
|
CellRenderer,
|
|
21
21
|
focused,
|
|
22
22
|
scrollTo = null,
|
|
23
|
-
behavior
|
|
23
|
+
behavior,
|
|
24
24
|
} = props;
|
|
25
25
|
|
|
26
26
|
const state = useCellState({ id: item.id, behavior, focused });
|
|
@@ -1,19 +1,29 @@
|
|
|
1
|
+
import FastImage, { Source } from "@applicaster/react-native-fast-image";
|
|
1
2
|
import { useMemo } from "react";
|
|
3
|
+
import { ImageRequireSource } from "react-native";
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
function getSourceCache(cache: Source["cache"]) {
|
|
6
|
+
return cache || FastImage.cacheControl.web;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const useImageSource = (source?: Source | ImageRequireSource) => {
|
|
4
10
|
return useMemo(() => {
|
|
5
|
-
if (
|
|
6
|
-
|
|
11
|
+
if (source) {
|
|
12
|
+
if (typeof source === "number") {
|
|
13
|
+
return source;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
uri: source.uri,
|
|
18
|
+
headers: source.headers,
|
|
19
|
+
priority: source.priority,
|
|
20
|
+
cache: getSourceCache(source?.cache),
|
|
21
|
+
maxWidth: source.maxWidth,
|
|
22
|
+
maxHeight: source.maxHeight,
|
|
23
|
+
};
|
|
7
24
|
}
|
|
8
25
|
|
|
9
|
-
return
|
|
10
|
-
uri: source.uri,
|
|
11
|
-
headers: source.headers,
|
|
12
|
-
priority: source.priority,
|
|
13
|
-
cache: source.cache,
|
|
14
|
-
maxWidth: source.maxWidth,
|
|
15
|
-
maxHeight: source.maxHeight,
|
|
16
|
-
};
|
|
26
|
+
return undefined;
|
|
17
27
|
}, [
|
|
18
28
|
...(typeof source === "object"
|
|
19
29
|
? [
|
|
@@ -23,7 +23,11 @@ export const Toggle = (props: Props) => {
|
|
|
23
23
|
iosBackgroundColor,
|
|
24
24
|
} = style;
|
|
25
25
|
|
|
26
|
-
const isSelected = React.useMemo(
|
|
26
|
+
const isSelected = React.useMemo(
|
|
27
|
+
() => cellState === "selected",
|
|
28
|
+
[item?.id, cellState]
|
|
29
|
+
);
|
|
30
|
+
|
|
27
31
|
const actionContext = useActions(action?.identifier);
|
|
28
32
|
|
|
29
33
|
const [actionState, setActionState] = useState(
|
|
@@ -54,6 +54,8 @@ 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 { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
58
|
+
|
|
57
59
|
type Props = {
|
|
58
60
|
Player: React.ComponentType<any>;
|
|
59
61
|
PlayerLoadingView?: React.ComponentType<any>; // 👀 we are not receiving this prop
|
|
@@ -145,34 +147,36 @@ const renderApplePlayer = ({
|
|
|
145
147
|
}) => {
|
|
146
148
|
const { title, summary } = item || {};
|
|
147
149
|
|
|
148
|
-
if (!isApplePlatform()) {
|
|
150
|
+
if (!isApplePlatform() || !player) {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// TODO: Check if it is not breaking default player logic on tvos
|
|
155
|
+
// Also if needs to add on tvos brightcove player for QB player
|
|
156
|
+
if (player.supportsNativeControls()) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (isAudioContent) {
|
|
161
|
+
return (
|
|
162
|
+
<AudioPlayer
|
|
163
|
+
audio_item={item}
|
|
164
|
+
plugin_configuration={pluginConfiguration}
|
|
165
|
+
/>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!playNextData && player.isPaused() && player.isAd() === false) {
|
|
149
170
|
return null;
|
|
150
171
|
}
|
|
151
172
|
|
|
152
173
|
return (
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
<ProgramInfo
|
|
160
|
-
title={title}
|
|
161
|
-
subtitle={summary}
|
|
162
|
-
plugin_configuration={pluginConfiguration}
|
|
163
|
-
videoStyle={videoStyle}
|
|
164
|
-
/>
|
|
165
|
-
)}
|
|
166
|
-
</>
|
|
167
|
-
)}
|
|
168
|
-
|
|
169
|
-
{isAudioContent && (
|
|
170
|
-
<AudioPlayer
|
|
171
|
-
audio_item={item}
|
|
172
|
-
plugin_configuration={pluginConfiguration}
|
|
173
|
-
/>
|
|
174
|
-
)}
|
|
175
|
-
</>
|
|
174
|
+
<ProgramInfo
|
|
175
|
+
title={title}
|
|
176
|
+
subtitle={summary}
|
|
177
|
+
plugin_configuration={pluginConfiguration}
|
|
178
|
+
videoStyle={videoStyle}
|
|
179
|
+
/>
|
|
176
180
|
);
|
|
177
181
|
};
|
|
178
182
|
|
|
@@ -339,6 +343,18 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
339
343
|
}
|
|
340
344
|
}, [item?.id, item?.extensions?.resumeTime, player]);
|
|
341
345
|
|
|
346
|
+
const onVideoFullscreenPlayerWillPresent = React.useCallback(() => {
|
|
347
|
+
playerManager.invokeHandler("toggleFullscreen", {
|
|
348
|
+
fullscreen: true,
|
|
349
|
+
});
|
|
350
|
+
}, []);
|
|
351
|
+
|
|
352
|
+
const onVideoFullscreenPlayerWillDismiss = React.useCallback(() => {
|
|
353
|
+
playerManager.invokeHandler("toggleFullscreen", {
|
|
354
|
+
fullscreen: false,
|
|
355
|
+
});
|
|
356
|
+
}, []);
|
|
357
|
+
|
|
342
358
|
// Util methods
|
|
343
359
|
const toggleFullscreen = (event) => {
|
|
344
360
|
const { fullscreen = false } = event || {};
|
|
@@ -381,17 +397,27 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
381
397
|
id: playerContainerId,
|
|
382
398
|
listener: {
|
|
383
399
|
onVideoEnd,
|
|
384
|
-
onError
|
|
385
|
-
onLoad
|
|
400
|
+
onError,
|
|
401
|
+
onLoad,
|
|
386
402
|
onPlayerClose: close,
|
|
387
403
|
onPlayerDetached: close,
|
|
404
|
+
onVideoFullscreenPlayerWillDismiss,
|
|
405
|
+
onVideoFullscreenPlayerWillPresent,
|
|
388
406
|
},
|
|
389
407
|
});
|
|
390
408
|
|
|
391
409
|
return () => {
|
|
392
410
|
player.removeListener(playerContainerId);
|
|
393
411
|
};
|
|
394
|
-
}, [
|
|
412
|
+
}, [
|
|
413
|
+
player,
|
|
414
|
+
onVideoEnd,
|
|
415
|
+
onError,
|
|
416
|
+
onLoad,
|
|
417
|
+
close,
|
|
418
|
+
onVideoFullscreenPlayerWillDismiss,
|
|
419
|
+
onVideoFullscreenPlayerWillPresent,
|
|
420
|
+
]);
|
|
395
421
|
|
|
396
422
|
useEffect(() => {
|
|
397
423
|
// TODO: We should not use playerManager here to connect buttons to player container
|
|
@@ -580,6 +606,9 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
580
606
|
pluginConfiguration,
|
|
581
607
|
};
|
|
582
608
|
|
|
609
|
+
const { isActiveGesture, startComponentsAnimation } =
|
|
610
|
+
useModalAnimationContext();
|
|
611
|
+
|
|
583
612
|
return (
|
|
584
613
|
<PlayerStateContext.Provider value={value}>
|
|
585
614
|
<PlayerContainerContextProvider
|
|
@@ -621,9 +650,13 @@ const PlayerContainerComponent = (props: Props) => {
|
|
|
621
650
|
}}
|
|
622
651
|
focused={isInlineTV ? true : undefined}
|
|
623
652
|
autoplay={true}
|
|
624
|
-
controls={
|
|
653
|
+
controls={false}
|
|
625
654
|
disableCastAction={disableCastAction}
|
|
626
|
-
docked={
|
|
655
|
+
docked={
|
|
656
|
+
navigator.isVideoModalDocked() &&
|
|
657
|
+
!startComponentsAnimation &&
|
|
658
|
+
!isActiveGesture
|
|
659
|
+
}
|
|
627
660
|
entry={item}
|
|
628
661
|
fullscreen={mode === VideoModalMode.FULLSCREEN}
|
|
629
662
|
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
|
|
|
@@ -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
|
}));
|
|
@@ -83,6 +89,7 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
|
|
|
83
89
|
useNavigation: jest.fn(() => ({ currentRoute: "/river/A1234" })),
|
|
84
90
|
useRoute: jest.fn(() => ({ pathname: "/river/A1234", screenData })),
|
|
85
91
|
useProfilerLogging: jest.fn(),
|
|
92
|
+
useIsScreenActive: jest.fn().mockReturnValue(true),
|
|
86
93
|
}));
|
|
87
94
|
|
|
88
95
|
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/screen", () => ({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
|
-
import {
|
|
3
|
+
import { act, create } from "react-test-renderer";
|
|
4
4
|
|
|
5
5
|
const Mocked_RouteManager = jest.fn((props) => (
|
|
6
6
|
<View testID="routeManager" {...props} />
|
|
@@ -69,12 +69,16 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
|
|
|
69
69
|
isNavBarVisible: mockIsNavBarVisible,
|
|
70
70
|
useRoute: jest.fn(() => ({
|
|
71
71
|
pathname: "/river/testId",
|
|
72
|
+
screenData: { id: "testId" },
|
|
72
73
|
})),
|
|
73
74
|
useNavigation: jest.fn(() => ({
|
|
74
75
|
canGoBack: () => false,
|
|
75
76
|
currentRoute: "/river/testId",
|
|
77
|
+
activeRiver: { id: "testId" },
|
|
78
|
+
screenData: { id: "testId" },
|
|
76
79
|
data: { screen: { id: "testId" } },
|
|
77
80
|
})),
|
|
81
|
+
useIsScreenActive: jest.fn().mockReturnValue(true),
|
|
78
82
|
}));
|
|
79
83
|
|
|
80
84
|
jest.mock("@applicaster/zapp-react-native-redux/hooks", () => ({
|
|
@@ -19,7 +19,11 @@ exports[`<Screen Component /> when the navbar should be hidden renders correctly
|
|
|
19
19
|
<View>
|
|
20
20
|
<View
|
|
21
21
|
pathname="/river/testId"
|
|
22
|
-
screenData={
|
|
22
|
+
screenData={
|
|
23
|
+
Object {
|
|
24
|
+
"id": "testId",
|
|
25
|
+
}
|
|
26
|
+
}
|
|
23
27
|
testID="routeManager"
|
|
24
28
|
/>
|
|
25
29
|
</View>
|
|
@@ -45,7 +49,11 @@ exports[`<Screen Component /> when the navbar should show renders correctly 1`]
|
|
|
45
49
|
<View>
|
|
46
50
|
<View
|
|
47
51
|
pathname="/river/testId"
|
|
48
|
-
screenData={
|
|
52
|
+
screenData={
|
|
53
|
+
Object {
|
|
54
|
+
"id": "testId",
|
|
55
|
+
}
|
|
56
|
+
}
|
|
49
57
|
testID="routeManager"
|
|
50
58
|
/>
|
|
51
59
|
</View>
|
|
@@ -23,6 +23,17 @@ import { RouteManager } from "../RouteManager";
|
|
|
23
23
|
import { useScreenConfiguration } from "../River/useScreenConfiguration";
|
|
24
24
|
import { useScreenOrientationHandler } from "./orientationHandler";
|
|
25
25
|
|
|
26
|
+
const getScreenId = (
|
|
27
|
+
screenData: LegacyNavigationScreenData,
|
|
28
|
+
fallbackRiver: ZappRiver
|
|
29
|
+
) => {
|
|
30
|
+
return screenData?.targetScreen
|
|
31
|
+
? screenData?.targetScreen?.id ?? fallbackRiver.id
|
|
32
|
+
: "screen_id" in screenData
|
|
33
|
+
? screenData.screen_id
|
|
34
|
+
: fallbackRiver.id;
|
|
35
|
+
};
|
|
36
|
+
|
|
26
37
|
function colorIsNotTransparent(color) {
|
|
27
38
|
const layers = R.compose(
|
|
28
39
|
R.map(R.trim),
|
|
@@ -41,17 +52,11 @@ function isValidColor(string) {
|
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
type Props = {
|
|
44
|
-
pathname: string;
|
|
45
|
-
screenData: Record<string, any>;
|
|
46
55
|
setToggleMenu: () => void;
|
|
47
56
|
setCloseMenu: () => void;
|
|
48
57
|
};
|
|
49
58
|
|
|
50
|
-
export function Screen({
|
|
51
|
-
setToggleMenu,
|
|
52
|
-
setCloseMenu,
|
|
53
|
-
screenData: _screenData,
|
|
54
|
-
}: Props) {
|
|
59
|
+
export function Screen({ setToggleMenu, setCloseMenu }: Props) {
|
|
55
60
|
const theme = useTheme<BaseThemePropertiesMobile>();
|
|
56
61
|
const navigation = useNavigation();
|
|
57
62
|
const { plugins } = usePickFromState(["plugins"]);
|
|
@@ -68,10 +73,7 @@ export function Screen({
|
|
|
68
73
|
const routeData = useRoute();
|
|
69
74
|
|
|
70
75
|
const currentRiver = useScreenData(
|
|
71
|
-
(routeData.screenData
|
|
72
|
-
? (routeData.screenData as ZappRiver)?.targetScreen?.id ??
|
|
73
|
-
navigation.activeRiver.id
|
|
74
|
-
: (routeData.screenData as ZappRiver)?.screen_id
|
|
76
|
+
getScreenId(routeData.screenData, navigation.activeRiver)
|
|
75
77
|
);
|
|
76
78
|
|
|
77
79
|
const { title } = useNavbarState();
|
|
@@ -137,7 +139,7 @@ export function Screen({
|
|
|
137
139
|
|
|
138
140
|
<OfflineFallbackScreen screenData={screenData}>
|
|
139
141
|
{/* @TODO RouteManager doesn't use props, can they be removed ? */}
|
|
140
|
-
<RouteManager pathname={pathname} screenData={
|
|
142
|
+
<RouteManager pathname={pathname} screenData={screenData} />
|
|
141
143
|
</OfflineFallbackScreen>
|
|
142
144
|
</View>
|
|
143
145
|
</ScreenContextProvider>
|
|
@@ -4,8 +4,13 @@ import { render } from "@testing-library/react-native";
|
|
|
4
4
|
import * as PlayerFactory from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerFactory";
|
|
5
5
|
import { Player } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/player";
|
|
6
6
|
import { ThemeContext } from "@applicaster/zapp-react-native-utils/theme";
|
|
7
|
+
import * as navigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
7
8
|
|
|
8
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";
|
|
9
14
|
|
|
10
15
|
const seekTo = jest.fn();
|
|
11
16
|
|
|
@@ -18,12 +23,25 @@ jest.mock(
|
|
|
18
23
|
})
|
|
19
24
|
);
|
|
20
25
|
|
|
26
|
+
jest
|
|
27
|
+
.spyOn(useNavigationHooks, "useNavigation")
|
|
28
|
+
.mockImplementation(() => ({ videoModalState: { visible: false } }));
|
|
29
|
+
|
|
30
|
+
jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation");
|
|
31
|
+
|
|
32
|
+
const mockStore = configureStore();
|
|
33
|
+
|
|
34
|
+
const store = mockStore({ appData: {} });
|
|
35
|
+
|
|
21
36
|
const Wrapper = ({ children }: { children: React.ReactChildren }) => (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
/* @ts-ignore */
|
|
38
|
+
<Provider store={store}>
|
|
39
|
+
<ThemeContext.Provider
|
|
40
|
+
value={{ themes: { myTheme: {} }, selectedThemeId: "myTheme" }}
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
</ThemeContext.Provider>
|
|
44
|
+
</Provider>
|
|
27
45
|
);
|
|
28
46
|
|
|
29
47
|
describe("PlayerLiveImageComponent", () => {
|
|
@@ -46,6 +64,8 @@ describe("PlayerLiveImageComponent", () => {
|
|
|
46
64
|
controller: new Player({}),
|
|
47
65
|
Component: () => null,
|
|
48
66
|
}));
|
|
67
|
+
|
|
68
|
+
jest.spyOn(navigationHooks, "useIsScreenActive").mockReturnValue(true);
|
|
49
69
|
});
|
|
50
70
|
|
|
51
71
|
it("should render correctly with default props", () => {
|
|
@@ -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
|
+
};
|