@applicaster/zapp-react-native-ui-components 13.0.0-alpha.6944415045 → 13.0.0-alpha.7100577251
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.ios.ts +1 -1
- package/Components/BaseFocusable/index.tsx +1 -1
- package/Components/Cell/Cell.tsx +7 -4
- package/Components/Cell/TvOSCellComponent.tsx +22 -20
- package/Components/Cell/index.js +1 -3
- package/Components/Focusable/FocusableTvOS.tsx +1 -5
- package/Components/Focusable/Touchable.tsx +19 -20
- package/Components/FocusableList/index.tsx +9 -25
- package/Components/FocusableScrollView/index.tsx +12 -39
- package/Components/Layout/TV/NavBarContainer.tsx +7 -8
- package/Components/MasterCell/DefaultComponents/BorderContainerView/__tests__/index.test.tsx +66 -0
- package/Components/MasterCell/DefaultComponents/BorderContainerView/index.tsx +4 -1
- package/Components/MasterCell/DefaultComponents/Image/Image.ios.tsx +5 -11
- package/Components/MasterCell/DefaultComponents/ImageBorderContainer/__tests__/index.test.ts +93 -0
- package/Components/MasterCell/DefaultComponents/SecondaryImage/utils.ts +1 -1
- package/Components/MasterCell/DefaultComponents/__tests__/image.test.js +1 -1
- package/Components/MasterCell/hooks/useAsyncRendering/MasterCellAsyncRenderManager.ts +2 -2
- package/Components/MasterCell/utils/index.ts +1 -1
- package/Components/ModalComponent/Header/index.tsx +3 -3
- package/Components/PlayerImageBackground/index.tsx +23 -3
- package/Components/River/ComponentsMap/ComponentsMap.tsx +39 -65
- package/Components/River/ComponentsMap/hooks/useLoadingState.ts +78 -51
- package/Components/River/RiverFooter.tsx +39 -9
- package/Components/River/RiverItem.tsx +37 -2
- package/Components/River/TV/index.tsx +1 -6
- package/Components/River/__tests__/__snapshots__/componentsMap.test.js.snap +100 -31
- package/Components/River/__tests__/componentsMap.test.js +17 -5
- package/Components/Screen/hooks.ts +56 -0
- package/Components/Screen/index.tsx +13 -39
- package/Components/Tabs/Tab.tsx +6 -6
- package/Components/TextInputTv/index.tsx +2 -2
- package/Components/Transitioner/AnimationManager.js +8 -8
- package/Components/Transitioner/Scene.tsx +52 -23
- package/Components/Transitioner/__tests__/__snapshots__/Scene.test.js.snap +59 -43
- package/Components/Transitioner/__tests__/__snapshots__/transitioner.test.js.snap +2 -2
- package/Components/Transitioner/index.js +8 -4
- package/Components/VideoLive/LiveImageManager.ts +27 -1
- package/Components/VideoLive/PlayerLiveImageComponent.tsx +29 -21
- package/Components/VideoLive/__tests__/PlayerLiveImageComponent.test.tsx +51 -1
- package/Components/VideoLive/__tests__/__snapshots__/PlayerLiveImageComponent.test.tsx.snap +0 -5
- package/Components/VideoModal/ModalAnimation/AnimationComponent.tsx +7 -6
- package/Components/VideoModal/ModalAnimation/utils.ts +2 -2
- package/Components/VideoModal/OpaqueLayer.tsx +33 -0
- package/Components/VideoModal/PlayerDetails.tsx +4 -1
- package/Components/VideoModal/PlayerWrapper.tsx +16 -35
- package/Components/VideoModal/VideoModal.tsx +14 -23
- package/Components/VideoModal/__tests__/PlayerWrapper.test.tsx +1 -1
- package/Components/VideoModal/__tests__/__snapshots__/PlayerWrapper.test.tsx.snap +0 -90
- package/Components/VideoModal/hooks/__tests__/useDelayedPlayerDetails.test.ts +89 -0
- package/Components/VideoModal/hooks/index.ts +7 -0
- package/Components/VideoModal/hooks/useDelayedPlayerDetails.ts +49 -0
- package/Components/VideoModal/hooks/utils/__tests__/showDetails.test.ts +91 -0
- package/Components/VideoModal/hooks/utils/index.ts +33 -0
- package/Components/VideoModal/utils.ts +1 -1
- package/Contexts/ScreenContext/index.tsx +3 -2
- package/Decorators/ZappPipesDataConnector/__tests__/Hero.js +1 -1
- package/Decorators/ZappPipesDataConnector/index.tsx +31 -1
- package/package.json +5 -5
- package/Contexts/ComponentsMapOffsetContext/index.tsx +0 -46
|
@@ -9,7 +9,7 @@ exports[`<TransitionerComponent /> renders correctly 1`] = `
|
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
>
|
|
12
|
-
<
|
|
12
|
+
<SceneComponent
|
|
13
13
|
isActive={true}
|
|
14
14
|
screenUniqueId="mocked-uuid"
|
|
15
15
|
style={{}}
|
|
@@ -23,6 +23,6 @@ exports[`<TransitionerComponent /> renders correctly 1`] = `
|
|
|
23
23
|
children
|
|
24
24
|
</Text>
|
|
25
25
|
</View>
|
|
26
|
-
</
|
|
26
|
+
</SceneComponent>
|
|
27
27
|
</View>
|
|
28
28
|
`;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { useWindowDimensions } from "react-native";
|
|
3
2
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
4
3
|
import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout";
|
|
5
4
|
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks";
|
|
@@ -7,10 +6,15 @@ import { TransitionerComponent } from "./Transitioner";
|
|
|
7
6
|
|
|
8
7
|
export const Transitioner = (props) => {
|
|
9
8
|
const navigator = useNavigation();
|
|
10
|
-
const { height, width } = useWindowDimensions();
|
|
11
9
|
|
|
12
|
-
const
|
|
13
|
-
|
|
10
|
+
const {
|
|
11
|
+
width,
|
|
12
|
+
height,
|
|
13
|
+
deviceInfo: { isTablet },
|
|
14
|
+
} = useDimensions("window", {
|
|
15
|
+
updateForInactiveScreens: false,
|
|
16
|
+
deviceInfo: true,
|
|
17
|
+
});
|
|
14
18
|
|
|
15
19
|
const { appData } = usePickFromState(["appData"]);
|
|
16
20
|
const isTabletPortrait = appData?.isTabletPortrait;
|
|
@@ -8,6 +8,8 @@ import { loggerLiveImageManager } from "./loggerHelper";
|
|
|
8
8
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
9
9
|
import { Component } from "react";
|
|
10
10
|
|
|
11
|
+
const TIMEOUT_FOR_DELAY_CHECK_PLAYER_POSITION = 500; // ms
|
|
12
|
+
|
|
11
13
|
const { log_debug, log_info, log_error } = loggerLiveImageManager;
|
|
12
14
|
|
|
13
15
|
export type LiveImageManagerEvent =
|
|
@@ -62,6 +64,9 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
62
64
|
protected currentlyPlaying: LiveImage | null = null;
|
|
63
65
|
protected primaryPlayer: Player | null = null;
|
|
64
66
|
|
|
67
|
+
private checkPlayerPositionTimeout: ReturnType<typeof setTimeout> | null =
|
|
68
|
+
null;
|
|
69
|
+
|
|
65
70
|
protected listeners: Record<
|
|
66
71
|
string,
|
|
67
72
|
Record<LiveImageManagerEvent, (event?: Record<string, any>) => void>
|
|
@@ -118,6 +123,11 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
118
123
|
});
|
|
119
124
|
};
|
|
120
125
|
|
|
126
|
+
private cancelCheckPlayerPositionTimeout = () => {
|
|
127
|
+
clearTimeout(this.checkPlayerPositionTimeout);
|
|
128
|
+
this.checkPlayerPositionTimeout = null;
|
|
129
|
+
};
|
|
130
|
+
|
|
121
131
|
public onViewportEnter = (item: LiveImage) => {
|
|
122
132
|
log_debug(
|
|
123
133
|
`onViewportEnter: live-image ${playerInfo(
|
|
@@ -125,7 +135,21 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
125
135
|
)}, primary ${playerInfo(this.primaryPlayer)}`
|
|
126
136
|
);
|
|
127
137
|
|
|
128
|
-
|
|
138
|
+
if (!isTV()) {
|
|
139
|
+
// mobile only
|
|
140
|
+
// we have to delay running checkPlayerPosition, because sometimes on fast scrolling we get wrong order onEnter, then onLeave.
|
|
141
|
+
// which could cause select wrong item to play
|
|
142
|
+
|
|
143
|
+
this.cancelCheckPlayerPositionTimeout();
|
|
144
|
+
|
|
145
|
+
this.checkPlayerPositionTimeout = setTimeout(() => {
|
|
146
|
+
this.cancelCheckPlayerPositionTimeout();
|
|
147
|
+
|
|
148
|
+
this.checkPlayerPosition(item);
|
|
149
|
+
}, TIMEOUT_FOR_DELAY_CHECK_PLAYER_POSITION);
|
|
150
|
+
} else {
|
|
151
|
+
this.checkPlayerPosition(item);
|
|
152
|
+
}
|
|
129
153
|
};
|
|
130
154
|
|
|
131
155
|
public onViewportLeave = (item: LiveImage) => {
|
|
@@ -246,6 +270,8 @@ export class LiveImageManager implements PlayerLifecycleListener {
|
|
|
246
270
|
};
|
|
247
271
|
|
|
248
272
|
public checkPlayerPosition = (item: LiveImage) => {
|
|
273
|
+
this.cancelCheckPlayerPositionTimeout();
|
|
274
|
+
|
|
249
275
|
log_debug(
|
|
250
276
|
`checkPlayerPosition: live-image playerId: ${playerInfo(
|
|
251
277
|
item.player
|
|
@@ -44,7 +44,10 @@ type Props = {
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
const PlayerLiveImageComponent = (props: Props) => {
|
|
47
|
-
const dimensions = useDimensions("screen", {
|
|
47
|
+
const dimensions = useDimensions("screen", {
|
|
48
|
+
fullDimensions: true,
|
|
49
|
+
updateForInactiveScreens: false,
|
|
50
|
+
});
|
|
48
51
|
|
|
49
52
|
const { item, style, playerId } = props;
|
|
50
53
|
|
|
@@ -135,13 +138,16 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
135
138
|
} else {
|
|
136
139
|
throw new Error("Player factory item is null");
|
|
137
140
|
}
|
|
138
|
-
}, [playerId, item, playerPluginId, screenConfig]);
|
|
141
|
+
}, [playerId, item.id, playerPluginId, screenConfig]);
|
|
139
142
|
|
|
140
143
|
React.useEffect(() => {
|
|
141
144
|
liveImageItem.setMode = setModeDebounced;
|
|
142
145
|
}, [setModeDebounced, liveImageItem]);
|
|
143
146
|
|
|
144
|
-
const { start, end } = React.useMemo(
|
|
147
|
+
const { start, end } = React.useMemo(
|
|
148
|
+
() => getAutoplaySettings(item),
|
|
149
|
+
[item.id]
|
|
150
|
+
);
|
|
145
151
|
|
|
146
152
|
const controller = liveImageItem.getPlayer();
|
|
147
153
|
const player = usePlayer(playerId);
|
|
@@ -174,7 +180,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
174
180
|
|
|
175
181
|
unregister();
|
|
176
182
|
};
|
|
177
|
-
}, [item, liveImageItem]);
|
|
183
|
+
}, [item.id, liveImageItem]);
|
|
178
184
|
|
|
179
185
|
React.useEffect(() => {
|
|
180
186
|
if (!player) {
|
|
@@ -244,25 +250,27 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
244
250
|
}, [item.id]);
|
|
245
251
|
|
|
246
252
|
React.useEffect(() => {
|
|
247
|
-
if (playerManager) {
|
|
248
|
-
|
|
253
|
+
if (isMeasurement(item) || !playerManager) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
249
256
|
|
|
250
|
-
|
|
251
|
-
log_error(
|
|
252
|
-
`PlayerLiveImageComponent: player ${playerId} already registered`
|
|
253
|
-
);
|
|
254
|
-
} else {
|
|
255
|
-
playerManager.registerPlayer({
|
|
256
|
-
id: playerId,
|
|
257
|
-
playerController: controller,
|
|
258
|
-
});
|
|
257
|
+
const isPlayerRegistered = playerManager.isPlayerRegistered(playerId);
|
|
259
258
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
|
|
259
|
+
if (isPlayerRegistered) {
|
|
260
|
+
log_error(
|
|
261
|
+
`PlayerLiveImageComponent: player ${playerId} already registered`
|
|
262
|
+
);
|
|
263
|
+
} else {
|
|
264
|
+
playerManager.registerPlayer({
|
|
265
|
+
id: playerId,
|
|
266
|
+
playerController: controller,
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
return () => {
|
|
270
|
+
playerManager.unregisterPlayer(playerId);
|
|
271
|
+
};
|
|
264
272
|
}
|
|
265
|
-
}, [liveImageItem, playerId, controller]);
|
|
273
|
+
}, [liveImageItem, playerId, controller, item.id]);
|
|
266
274
|
|
|
267
275
|
const onPositionUpdated = React.useCallback(
|
|
268
276
|
(data) => {
|
|
@@ -302,7 +310,7 @@ const PlayerLiveImageComponent = (props: Props) => {
|
|
|
302
310
|
LiveImageManager.instance.checkPlayerPosition(liveImageItem);
|
|
303
311
|
}
|
|
304
312
|
},
|
|
305
|
-
[liveImageItem, dimensions]
|
|
313
|
+
[liveImageItem, dimensions.height, dimensions.width]
|
|
306
314
|
);
|
|
307
315
|
|
|
308
316
|
const platformSpecificProps = isApplePlatform()
|
|
@@ -4,6 +4,7 @@ import { render } from "@testing-library/react-native";
|
|
|
4
4
|
import * as PlayerFactory from "@applicaster/zapp-react-native-utils/appUtils/playerManager/playerFactory";
|
|
5
5
|
import { ThemeContext } from "@applicaster/zapp-react-native-utils/theme";
|
|
6
6
|
import * as navigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation";
|
|
7
|
+
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
|
|
7
8
|
|
|
8
9
|
import { PlayerLiveImage } from "../PlayerLiveImageComponent";
|
|
9
10
|
import * as useNavigationHooks from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
|
|
@@ -32,7 +33,7 @@ const mockStore = configureStore();
|
|
|
32
33
|
|
|
33
34
|
const store = mockStore({ appData: {} });
|
|
34
35
|
|
|
35
|
-
const Wrapper = ({ children }: { children: React.
|
|
36
|
+
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
|
36
37
|
/* @ts-ignore */
|
|
37
38
|
<Provider store={store}>
|
|
38
39
|
<ThemeContext.Provider
|
|
@@ -118,4 +119,53 @@ describe("PlayerLiveImageComponent", () => {
|
|
|
118
119
|
|
|
119
120
|
// TODO: implement this test
|
|
120
121
|
});
|
|
122
|
+
|
|
123
|
+
it("should register the player for normal item", () => {
|
|
124
|
+
render(
|
|
125
|
+
<Wrapper>
|
|
126
|
+
<PlayerLiveImage {...defaultProps} />
|
|
127
|
+
</Wrapper>
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const isPlayerRegistered = playerManager.isPlayerRegistered(
|
|
131
|
+
defaultProps.playerId
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
expect(isPlayerRegistered).toBe(true);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("should unregister the player for normal item", () => {
|
|
138
|
+
const component = render(
|
|
139
|
+
<Wrapper>
|
|
140
|
+
<PlayerLiveImage {...defaultProps} />
|
|
141
|
+
</Wrapper>
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
component.unmount();
|
|
145
|
+
|
|
146
|
+
const isPlayerRegistered = playerManager.isPlayerRegistered(
|
|
147
|
+
defaultProps.playerId
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
expect(isPlayerRegistered).toBe(false);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("should not register the player for 'pre-measurement' item", () => {
|
|
154
|
+
const props = {
|
|
155
|
+
...defaultProps,
|
|
156
|
+
item: {
|
|
157
|
+
...defaultProps.item,
|
|
158
|
+
id: "pre-measurement-1",
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
render(
|
|
163
|
+
<Wrapper>
|
|
164
|
+
<PlayerLiveImage {...props} />
|
|
165
|
+
</Wrapper>
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
const isPlayerRegistered = playerManager.isPlayerRegistered(props.playerId);
|
|
169
|
+
expect(isPlayerRegistered).toBe(false);
|
|
170
|
+
});
|
|
121
171
|
});
|
|
@@ -100,10 +100,11 @@ export const AnimationView = ({
|
|
|
100
100
|
const moveUpValue = additionalData.saveArea
|
|
101
101
|
? -insets.top + (isAudioItem ? 0 : progressBarHeight)
|
|
102
102
|
: isTablet
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
? isTabletLandscape &&
|
|
104
|
+
(!isAudioItem || (isAudioItem && inlineAudioPlayer))
|
|
105
|
+
? -tabletLandscapePlayerTopPosition + progressBarHeight
|
|
106
|
+
: -130
|
|
107
|
+
: -50 + progressBarHeight;
|
|
107
108
|
|
|
108
109
|
const moveComponentHorizontalValue = additionalData.moveValue
|
|
109
110
|
? isRTL
|
|
@@ -434,8 +435,8 @@ export const AnimationComponent = (props: Props) => {
|
|
|
434
435
|
const Component = useAnimation
|
|
435
436
|
? AnimationView
|
|
436
437
|
: style
|
|
437
|
-
|
|
438
|
-
|
|
438
|
+
? View
|
|
439
|
+
: React.Fragment;
|
|
439
440
|
|
|
440
441
|
if (
|
|
441
442
|
additionalData.extraAnimation &&
|
|
@@ -108,8 +108,8 @@ export const calculateAnimationValue = (animationType, dragPosition, data) => {
|
|
|
108
108
|
: { forWidth: 3, forHeight: 3 }
|
|
109
109
|
: { forWidth: 2, forHeight: 2 }
|
|
110
110
|
: isTabletLandscape
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
? { forWidth: 8, forHeight: 6.5 }
|
|
112
|
+
: { forWidth: 3.5, forHeight: 2 };
|
|
113
113
|
|
|
114
114
|
const minWidth =
|
|
115
115
|
isAudioItem && !inlineAudioPlayer ? minimisedHeight : minimisedWidth;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { StyleSheet, View } from "react-native";
|
|
3
|
+
|
|
4
|
+
import { useTheme } from "@applicaster/zapp-react-native-utils/theme";
|
|
5
|
+
|
|
6
|
+
import { Spinner } from "../Spinner";
|
|
7
|
+
|
|
8
|
+
const styles = StyleSheet.create({
|
|
9
|
+
container: {
|
|
10
|
+
...StyleSheet.absoluteFillObject,
|
|
11
|
+
alignItems: "center",
|
|
12
|
+
justifyContent: "center",
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const OpaqueLayer = () => {
|
|
17
|
+
const theme = useTheme();
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<View
|
|
21
|
+
style={[
|
|
22
|
+
styles.container,
|
|
23
|
+
{
|
|
24
|
+
// we assume that it's non-transparent and we could show spinner always until it will be covered by player
|
|
25
|
+
// this spinner hides all content under modal
|
|
26
|
+
backgroundColor: theme?.app_background_color,
|
|
27
|
+
},
|
|
28
|
+
]}
|
|
29
|
+
>
|
|
30
|
+
<Spinner />
|
|
31
|
+
</View>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ViewStyle,
|
|
5
5
|
Animated,
|
|
6
6
|
Easing,
|
|
7
|
+
StyleSheet,
|
|
7
8
|
Dimensions,
|
|
8
9
|
} from "react-native";
|
|
9
10
|
import { useTargetScreenData } from "@applicaster/zapp-react-native-utils/reactHooks/screen";
|
|
@@ -90,7 +91,9 @@ export const PlayerDetails = ({
|
|
|
90
91
|
{
|
|
91
92
|
// workaround for avoid wrong text-height after going back to portrait rotation
|
|
92
93
|
// we don't see this view in landscape mode, so we are able to use fixed width from portrait mode
|
|
93
|
-
width: isTablet
|
|
94
|
+
width: isTablet
|
|
95
|
+
? undefined
|
|
96
|
+
: (StyleSheet.flatten(style)?.width ?? SCREEN_WIDTH),
|
|
94
97
|
},
|
|
95
98
|
]}
|
|
96
99
|
>
|
|
@@ -10,7 +10,8 @@ import { Edge, SafeAreaView } from "react-native-safe-area-context";
|
|
|
10
10
|
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
11
11
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
12
|
import { PlayerDetails } from "./PlayerDetails";
|
|
13
|
-
import {
|
|
13
|
+
import { playerDimensionsHack } from "./utils";
|
|
14
|
+
import { useDelayedPlayerDetails } from "./hooks";
|
|
14
15
|
|
|
15
16
|
import {
|
|
16
17
|
AnimatedScrollModal,
|
|
@@ -121,34 +122,6 @@ const getTabletWidth = (
|
|
|
121
122
|
return Number(width) - sidebarWidth;
|
|
122
123
|
};
|
|
123
124
|
|
|
124
|
-
const showDetails = (
|
|
125
|
-
isMobile: boolean,
|
|
126
|
-
docked: boolean,
|
|
127
|
-
isInlineModal,
|
|
128
|
-
pip
|
|
129
|
-
): boolean => {
|
|
130
|
-
if (pip) {
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
if (!isInlineModal) {
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// for mobile we always show details. Mounting of it very heavy operation.
|
|
139
|
-
if (isMobile) {
|
|
140
|
-
return true;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// workaround for tablets we need to mount/unmount in order to avoid PlayerDetails content dissappearing
|
|
144
|
-
// FIXME - find out the reason of dissapearing of content
|
|
145
|
-
if (docked) {
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return true;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
125
|
const PlayerWrapperComponent = (props: Props) => {
|
|
153
126
|
const {
|
|
154
127
|
entry,
|
|
@@ -167,7 +140,15 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
167
140
|
|
|
168
141
|
const isInlineModal = inline && isModal;
|
|
169
142
|
|
|
170
|
-
//
|
|
143
|
+
// Mounting the PlayerDetails component is a resource-intensive process.
|
|
144
|
+
// Therefore, for performance reasons, we mount it with a delay to make the rotation process as smooth as possible.
|
|
145
|
+
// The flow is as follows: the rotation occurs first, and then, after a short delay, we mount the PlayerDetails component.
|
|
146
|
+
// This helps to avoid blocking the rotation and any animations related to the rotation.
|
|
147
|
+
const isShowPlayerDetails = useDelayedPlayerDetails({
|
|
148
|
+
isInline: isInlineModal,
|
|
149
|
+
isDocked: docked,
|
|
150
|
+
isPip: pip,
|
|
151
|
+
});
|
|
171
152
|
|
|
172
153
|
const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
|
|
173
154
|
|
|
@@ -203,8 +184,8 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
203
184
|
const WrapperView = React.useMemo(() => (isTV() ? View : SafeAreaView), []);
|
|
204
185
|
|
|
205
186
|
const childrenStyles = React.useMemo(
|
|
206
|
-
() => ({ ...playerDimensions, ...
|
|
207
|
-
[containerDimensions,
|
|
187
|
+
() => ({ ...playerDimensions, ...playerDimensionsHack }),
|
|
188
|
+
[containerDimensions, playerDimensionsHack]
|
|
208
189
|
);
|
|
209
190
|
|
|
210
191
|
return (
|
|
@@ -213,7 +194,7 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
213
194
|
style={[
|
|
214
195
|
safeAreaStyles(configuration, isTablet),
|
|
215
196
|
style,
|
|
216
|
-
|
|
197
|
+
playerDimensionsHack,
|
|
217
198
|
]}
|
|
218
199
|
>
|
|
219
200
|
<AnimationComponent
|
|
@@ -227,7 +208,7 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
227
208
|
defaultStyles.playerContainer,
|
|
228
209
|
containerDimensions,
|
|
229
210
|
containerStyle,
|
|
230
|
-
|
|
211
|
+
playerDimensionsHack,
|
|
231
212
|
]}
|
|
232
213
|
>
|
|
233
214
|
<AnimationComponent
|
|
@@ -246,7 +227,7 @@ const PlayerWrapperComponent = (props: Props) => {
|
|
|
246
227
|
</View>
|
|
247
228
|
|
|
248
229
|
<AnimatedScrollModal>
|
|
249
|
-
{
|
|
230
|
+
{isShowPlayerDetails && (
|
|
250
231
|
<AnimationComponent
|
|
251
232
|
animationType={ComponentAnimationType.componentFade}
|
|
252
233
|
style={defaultStyles.flex}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import
|
|
3
|
-
import { StyleSheet,
|
|
2
|
+
import { equals } from "ramda";
|
|
3
|
+
import { StyleSheet, StatusBar } from "react-native";
|
|
4
4
|
|
|
5
5
|
import { HandlePlayable } from "@applicaster/zapp-react-native-ui-components/Components/HandlePlayable";
|
|
6
6
|
import {
|
|
@@ -17,17 +17,20 @@ import {
|
|
|
17
17
|
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks/device/useIsTablet";
|
|
18
18
|
|
|
19
19
|
import { withModalNavigationContextProvider } from "../../Contexts/ModalNavigationContext";
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
import {
|
|
21
|
+
useModalSize,
|
|
22
|
+
useBackgroundColor,
|
|
23
|
+
useInitialPlayerState,
|
|
24
|
+
} from "./hooks";
|
|
25
|
+
|
|
23
26
|
import { APP_EVENTS } from "@applicaster/zapp-react-native-utils/appUtils/events";
|
|
24
|
-
import { Spinner } from "../Spinner";
|
|
25
27
|
import { PathnameContext } from "@applicaster/zapp-react-native-ui-components/Contexts/PathnameContext";
|
|
26
28
|
import { ROUTE_TYPES } from "@applicaster/zapp-react-native-utils/navigationUtils/routeTypes";
|
|
27
29
|
import { useSubscriberFor } from "@applicaster/zapp-react-native-utils/reactHooks/useSubscriberFor";
|
|
28
30
|
import { requiresAuthentication } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
29
31
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
30
32
|
import { ScreenContextProvider } from "../../Contexts/ScreenContext";
|
|
33
|
+
import { OpaqueLayer } from "./OpaqueLayer";
|
|
31
34
|
|
|
32
35
|
import { AnimatedPlayerModalWrapper } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
33
36
|
|
|
@@ -39,17 +42,6 @@ const styles = StyleSheet.create({
|
|
|
39
42
|
bottom: 0,
|
|
40
43
|
position: "absolute",
|
|
41
44
|
},
|
|
42
|
-
// eslint-disable-next-line react-native/no-color-literals
|
|
43
|
-
loaderContainer: {
|
|
44
|
-
top: 0,
|
|
45
|
-
left: 0,
|
|
46
|
-
right: 0,
|
|
47
|
-
bottom: 0,
|
|
48
|
-
position: "absolute",
|
|
49
|
-
alignItems: "center",
|
|
50
|
-
justifyContent: "center",
|
|
51
|
-
backgroundColor: "rgba(64,64,64,.5)",
|
|
52
|
-
},
|
|
53
45
|
});
|
|
54
46
|
|
|
55
47
|
const VideoModalComponent = () => {
|
|
@@ -100,7 +92,7 @@ const VideoModalComponent = () => {
|
|
|
100
92
|
|
|
101
93
|
const onHooksSuccess = ({ payload }) => {
|
|
102
94
|
// set new modified entry
|
|
103
|
-
if (!
|
|
95
|
+
if (!equals(payload, item)) {
|
|
104
96
|
onVideoModalHookSuccessAnalyticsEvent();
|
|
105
97
|
setVideoModalItem(payload);
|
|
106
98
|
}
|
|
@@ -136,7 +128,10 @@ const VideoModalComponent = () => {
|
|
|
136
128
|
|
|
137
129
|
<PathnameContext.Provider value={pathname}>
|
|
138
130
|
<ScreenContextProvider pathname={pathname}>
|
|
139
|
-
{
|
|
131
|
+
{/* Hide content underneath when we switch to next video in fullscreen mode */}
|
|
132
|
+
{mode === "FULLSCREEN" && <OpaqueLayer />}
|
|
133
|
+
|
|
134
|
+
{itemIdHooksFinished === item?.id && (
|
|
140
135
|
<AnimatedPlayerModalWrapper
|
|
141
136
|
style={[
|
|
142
137
|
styles.container,
|
|
@@ -153,10 +148,6 @@ const VideoModalComponent = () => {
|
|
|
153
148
|
mode={mode}
|
|
154
149
|
/>
|
|
155
150
|
</AnimatedPlayerModalWrapper>
|
|
156
|
-
) : (
|
|
157
|
-
<View style={styles.loaderContainer}>
|
|
158
|
-
<Spinner />
|
|
159
|
-
</View>
|
|
160
151
|
)}
|
|
161
152
|
</ScreenContextProvider>
|
|
162
153
|
</PathnameContext.Provider>
|
|
@@ -62,7 +62,7 @@ jest.mock("@applicaster/zapp-react-native-utils/reactHooks/navigation", () => ({
|
|
|
62
62
|
})),
|
|
63
63
|
}));
|
|
64
64
|
|
|
65
|
-
jest.mock("../utils", () => ({
|
|
65
|
+
jest.mock("../utils", () => ({ playerDimensionsHack: {} }));
|
|
66
66
|
|
|
67
67
|
const { PlayerWrapper } = require("../PlayerWrapper");
|
|
68
68
|
|
|
@@ -71,36 +71,6 @@ exports[`PlayerWrapper renders inline 1`] = `
|
|
|
71
71
|
}
|
|
72
72
|
testID="test-player-container"
|
|
73
73
|
/>
|
|
74
|
-
<View
|
|
75
|
-
animationType="componentFade"
|
|
76
|
-
style={
|
|
77
|
-
{
|
|
78
|
-
"flex": 1,
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
>
|
|
82
|
-
<View
|
|
83
|
-
configuration={
|
|
84
|
-
{
|
|
85
|
-
"tablet_landscape_player_container_background_color": "red",
|
|
86
|
-
"tablet_landscape_sidebar_width": "35%",
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
entry={
|
|
90
|
-
{
|
|
91
|
-
"id": "test",
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
isTablet={false}
|
|
95
|
-
isTabletLandscape={false}
|
|
96
|
-
style={
|
|
97
|
-
{
|
|
98
|
-
"flex": 1,
|
|
99
|
-
"paddingTop": 20,
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
/>
|
|
103
|
-
</View>
|
|
104
74
|
</View>
|
|
105
75
|
</RNCSafeAreaView>
|
|
106
76
|
</RNCSafeAreaProvider>
|
|
@@ -177,36 +147,6 @@ exports[`PlayerWrapper renders inline and docked 1`] = `
|
|
|
177
147
|
}
|
|
178
148
|
testID="test-player-container"
|
|
179
149
|
/>
|
|
180
|
-
<View
|
|
181
|
-
animationType="componentFade"
|
|
182
|
-
style={
|
|
183
|
-
{
|
|
184
|
-
"flex": 1,
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
>
|
|
188
|
-
<View
|
|
189
|
-
configuration={
|
|
190
|
-
{
|
|
191
|
-
"tablet_landscape_player_container_background_color": "red",
|
|
192
|
-
"tablet_landscape_sidebar_width": "35%",
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
entry={
|
|
196
|
-
{
|
|
197
|
-
"id": "test",
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
isTablet={false}
|
|
201
|
-
isTabletLandscape={false}
|
|
202
|
-
style={
|
|
203
|
-
{
|
|
204
|
-
"flex": 1,
|
|
205
|
-
"paddingTop": 20,
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
/>
|
|
209
|
-
</View>
|
|
210
150
|
</View>
|
|
211
151
|
</RNCSafeAreaView>
|
|
212
152
|
</RNCSafeAreaProvider>
|
|
@@ -299,36 +239,6 @@ exports[`PlayerWrapper renders inline on tablet in landscape orientation 1`] = `
|
|
|
299
239
|
}
|
|
300
240
|
/>
|
|
301
241
|
</View>
|
|
302
|
-
<View
|
|
303
|
-
animationType="componentFade"
|
|
304
|
-
style={
|
|
305
|
-
{
|
|
306
|
-
"flex": 1,
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
>
|
|
310
|
-
<View
|
|
311
|
-
configuration={
|
|
312
|
-
{
|
|
313
|
-
"tablet_landscape_player_container_background_color": "red",
|
|
314
|
-
"tablet_landscape_sidebar_width": "35%",
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
entry={
|
|
318
|
-
{
|
|
319
|
-
"id": "test",
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
isTablet={true}
|
|
323
|
-
isTabletLandscape={true}
|
|
324
|
-
style={
|
|
325
|
-
{
|
|
326
|
-
"flex": 1,
|
|
327
|
-
"paddingTop": 20,
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
/>
|
|
331
|
-
</View>
|
|
332
242
|
</View>
|
|
333
243
|
</RNCSafeAreaView>
|
|
334
244
|
</RNCSafeAreaProvider>
|