@applicaster/quick-brick-player 14.0.0-alpha.3552323332 → 14.0.0-alpha.4009339136
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/package.json +6 -6
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +81 -25
- package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +99 -85
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +16 -1
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +48 -8
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +5 -9
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +72 -21
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +16 -0
- package/src/Player/AudioLayer/Layout/TransportInfo/index.tsx +12 -12
- package/src/Player/AudioLayer/components/SleepTimerModalHeader/SleepTimerModalHeader.tsx +1 -1
- package/src/Player/PlayerView/GenericTVPlayerView.tsx +1 -2
- package/src/Player/index.tsx +104 -167
- package/src/Player/PlayerModal/PlayerModal.tsx +0 -110
- package/src/Player/PlayerModal/VideoPlayerModal.tsx +0 -245
- package/src/Player/PlayerModal/consts/index.ts +0 -20
- package/src/Player/PlayerModal/hooks/index.ts +0 -168
- package/src/Player/PlayerModal/index.ts +0 -3
- package/src/Player/PlayerModal/styles.ts +0 -95
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/quick-brick-player",
|
|
3
|
-
"version": "14.0.0-alpha.
|
|
3
|
+
"version": "14.0.0-alpha.4009339136",
|
|
4
4
|
"description": "Quick Brick Player",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://github.com/applicaster/quickbrick#readme",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@applicaster/quick-brick-mobile-transport-controls": "14.0.0-
|
|
39
|
-
"@applicaster/quick-brick-tv-transport-controls": "14.0.0-rc.
|
|
40
|
-
"@applicaster/zapp-react-native-tvos-app": "14.0.0-alpha.
|
|
41
|
-
"@applicaster/zapp-react-native-ui-components": "14.0.0-alpha.
|
|
42
|
-
"@applicaster/zapp-react-native-utils": "14.0.0-alpha.
|
|
38
|
+
"@applicaster/quick-brick-mobile-transport-controls": "14.0.0-rc.25",
|
|
39
|
+
"@applicaster/quick-brick-tv-transport-controls": "14.0.0-rc.13",
|
|
40
|
+
"@applicaster/zapp-react-native-tvos-app": "14.0.0-alpha.4009339136",
|
|
41
|
+
"@applicaster/zapp-react-native-ui-components": "14.0.0-alpha.4009339136",
|
|
42
|
+
"@applicaster/zapp-react-native-utils": "14.0.0-alpha.4009339136",
|
|
43
43
|
"query-string": "7.1.3",
|
|
44
44
|
"react-native-web-linear-gradient": "1.1.2",
|
|
45
45
|
"shaka-player": "4.3.5",
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
Dimensions as ScreenDimensions,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
View,
|
|
7
|
+
ViewStyle,
|
|
8
|
+
} from "react-native";
|
|
4
9
|
|
|
5
10
|
import { Edge, SafeAreaView } from "react-native-safe-area-context";
|
|
6
11
|
import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
|
|
@@ -8,9 +13,14 @@ import { usePlayer } from "@applicaster/zapp-react-native-utils/appUtils/playerM
|
|
|
8
13
|
import * as R from "ramda";
|
|
9
14
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
10
15
|
import Layout from "./Layout";
|
|
11
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
useIsTablet,
|
|
18
|
+
useNavigation,
|
|
19
|
+
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
12
20
|
import { createLogger } from "@applicaster/zapp-react-native-utils/logger";
|
|
13
21
|
import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
|
|
22
|
+
import { PlayerDetails } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/PlayerDetails";
|
|
23
|
+
import { isTV } from "@applicaster/zapp-react-native-utils/reactUtils";
|
|
14
24
|
import { formatSpeed } from "./utils";
|
|
15
25
|
import {
|
|
16
26
|
getBottomSheetModalDefaultItemIcon,
|
|
@@ -20,7 +30,12 @@ import {
|
|
|
20
30
|
getBottomSheetModalSelectedItemIcon,
|
|
21
31
|
} from "../Utils";
|
|
22
32
|
import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
|
|
23
|
-
|
|
33
|
+
import {
|
|
34
|
+
AnimatedScrollModal,
|
|
35
|
+
AnimationComponent,
|
|
36
|
+
ComponentAnimationType,
|
|
37
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
38
|
+
import { PADDING_HORIZONTAL } from "./Layout/const";
|
|
24
39
|
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
25
40
|
|
|
26
41
|
import { DEFAULT_SPEED, PlaybackSpeed, SpeedController } from "./SpeedManager";
|
|
@@ -66,10 +81,18 @@ type Props = {
|
|
|
66
81
|
isTabletPortrait?: boolean;
|
|
67
82
|
};
|
|
68
83
|
|
|
84
|
+
const { width: SCREEN_WIDTH } = ScreenDimensions.get("screen");
|
|
85
|
+
|
|
69
86
|
const Styles = StyleSheet.create({
|
|
70
87
|
playerContainer: {
|
|
71
88
|
flex: 1,
|
|
72
89
|
},
|
|
90
|
+
paddingHorizontal: { paddingTop: 0, paddingHorizontal: PADDING_HORIZONTAL },
|
|
91
|
+
playerDetails: {
|
|
92
|
+
marginTop: 60,
|
|
93
|
+
alignSelf: "center",
|
|
94
|
+
width: SCREEN_WIDTH - PADDING_HORIZONTAL * 2,
|
|
95
|
+
},
|
|
73
96
|
});
|
|
74
97
|
|
|
75
98
|
const edges: Edge[] = ["right", "left", "top"];
|
|
@@ -84,10 +107,16 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
84
107
|
configuration,
|
|
85
108
|
style,
|
|
86
109
|
entry,
|
|
110
|
+
children,
|
|
87
111
|
layoutState,
|
|
88
112
|
playNextData = null,
|
|
113
|
+
isTabletPortrait,
|
|
89
114
|
} = props;
|
|
90
115
|
|
|
116
|
+
const isTablet = useIsTablet();
|
|
117
|
+
|
|
118
|
+
const isTabletLandscape = !isTV() && isTablet && !isTabletPortrait;
|
|
119
|
+
|
|
91
120
|
const { title, summary } = useTitleSummaryOverlay(
|
|
92
121
|
entry,
|
|
93
122
|
playerState?.isLive,
|
|
@@ -235,6 +264,10 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
235
264
|
});
|
|
236
265
|
}, [playbackSpeed, onSpeedSelect, configuration["playback_speed_title"]]);
|
|
237
266
|
|
|
267
|
+
const onCloseVideoModal = React.useCallback(() => {
|
|
268
|
+
playerManager.close();
|
|
269
|
+
}, [playerManager]);
|
|
270
|
+
|
|
238
271
|
const onPlayerSeek = React.useCallback(
|
|
239
272
|
(targetTime: number) => {
|
|
240
273
|
player?.seekTo(targetTime);
|
|
@@ -252,28 +285,51 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
252
285
|
|
|
253
286
|
return (
|
|
254
287
|
<SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
|
|
255
|
-
<
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
288
|
+
<AnimationComponent
|
|
289
|
+
animationType={ComponentAnimationType.moveUpComponent}
|
|
290
|
+
additionalData={{ saveArea: true }}
|
|
291
|
+
style={Styles.playerContainer}
|
|
292
|
+
>
|
|
293
|
+
<AnimatedScrollModal>
|
|
294
|
+
<View style={Styles.playerContainer} onLayout={onLayout}>
|
|
295
|
+
<Layout
|
|
296
|
+
entry={entry}
|
|
297
|
+
playerState={playerState}
|
|
298
|
+
layoutState={layoutState}
|
|
299
|
+
value={value}
|
|
300
|
+
onPlaybackButtonPress={onPlaybackButtonPress}
|
|
301
|
+
onRewindButtonPress={onRewindButtonPress}
|
|
302
|
+
onForwardButtonPress={onForwardButtonPress}
|
|
303
|
+
onPlayerSeek={onPlayerSeek}
|
|
304
|
+
onSkipStart={onSkipStart}
|
|
305
|
+
onSpeedButtonPress={onSpeedButtonPress}
|
|
306
|
+
playbackSpeedName={formatSpeed(playbackSpeed.value)}
|
|
307
|
+
onSkipLive={onSkipLive}
|
|
308
|
+
onCloseVideoModal={onCloseVideoModal}
|
|
309
|
+
maximiseVideoModal={maximiseVideoModal}
|
|
310
|
+
configuration={configuration}
|
|
311
|
+
dimensions={dimensions}
|
|
312
|
+
playNextData={playNextData}
|
|
313
|
+
title={title}
|
|
314
|
+
summary={summary}
|
|
315
|
+
/>
|
|
316
|
+
<View style={Styles.paddingHorizontal}>
|
|
317
|
+
{children}
|
|
318
|
+
<AnimationComponent
|
|
319
|
+
animationType={ComponentAnimationType.componentFade}
|
|
320
|
+
>
|
|
321
|
+
<PlayerDetails
|
|
322
|
+
isAudioPlayer
|
|
323
|
+
configuration={configuration}
|
|
324
|
+
style={Styles.playerDetails}
|
|
325
|
+
entry={entry}
|
|
326
|
+
isTabletLandscape={isTabletLandscape}
|
|
327
|
+
/>
|
|
328
|
+
</AnimationComponent>
|
|
329
|
+
</View>
|
|
330
|
+
</View>
|
|
331
|
+
</AnimatedScrollModal>
|
|
332
|
+
</AnimationComponent>
|
|
277
333
|
</SafeAreaView>
|
|
278
334
|
);
|
|
279
335
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { StyleSheet, View, ViewStyle } from "react-native";
|
|
3
|
-
import * as R from "ramda";
|
|
4
2
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
StyleSheet,
|
|
4
|
+
TouchableWithoutFeedback,
|
|
5
|
+
View,
|
|
6
|
+
ViewStyle,
|
|
7
|
+
} from "react-native";
|
|
8
|
+
import * as R from "ramda";
|
|
9
|
+
import { useIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
9
10
|
|
|
10
11
|
import {
|
|
11
12
|
Button,
|
|
@@ -16,12 +17,15 @@ import {
|
|
|
16
17
|
|
|
17
18
|
import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
|
|
18
19
|
|
|
20
|
+
import {
|
|
21
|
+
AnimationComponent,
|
|
22
|
+
ComponentAnimationType,
|
|
23
|
+
PlayerAnimationStateEnum,
|
|
24
|
+
useModalAnimationContext,
|
|
25
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
19
26
|
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
20
27
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
21
28
|
import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
|
|
22
|
-
import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
|
|
23
|
-
import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
|
|
24
|
-
import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
|
|
25
29
|
|
|
26
30
|
const bottomTabBarHeight = getTabBarHeight();
|
|
27
31
|
|
|
@@ -30,16 +34,13 @@ type Props = {
|
|
|
30
34
|
layoutState: QuickBrickPlayer.LayoutState;
|
|
31
35
|
playerState: QuickBrickPlayer.PlayerState;
|
|
32
36
|
value: GetValue;
|
|
37
|
+
dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"];
|
|
33
38
|
onCloseVideoModal: () => void;
|
|
34
39
|
onPlayerSeek: (targetTime: number) => void;
|
|
35
40
|
playNextData: PlayNextData;
|
|
36
41
|
title: string | number;
|
|
37
42
|
summary: string | number;
|
|
38
43
|
ImageComponent?: React.ReactNode;
|
|
39
|
-
isActiveGesture?: boolean;
|
|
40
|
-
minimisedHeight: number;
|
|
41
|
-
progressBarHeight: number;
|
|
42
|
-
aspectRatio?: number;
|
|
43
44
|
};
|
|
44
45
|
|
|
45
46
|
const styles = StyleSheet.create({
|
|
@@ -47,7 +48,6 @@ const styles = StyleSheet.create({
|
|
|
47
48
|
flex: 1,
|
|
48
49
|
flexDirection: "column",
|
|
49
50
|
alignItems: "stretch",
|
|
50
|
-
marginTop: 3, // from plugins/mobile-transport-controls/src/ProgressBar/layouts/DockedLayout.tsx
|
|
51
51
|
},
|
|
52
52
|
content: {
|
|
53
53
|
flex: 1,
|
|
@@ -99,6 +99,26 @@ const playerDimensionsStyle = (
|
|
|
99
99
|
width: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
+
const animatedContainerStyle = (
|
|
103
|
+
docked: boolean,
|
|
104
|
+
progressBarHeight: number
|
|
105
|
+
): ViewStyle => ({
|
|
106
|
+
top: progressBarHeight,
|
|
107
|
+
position: "absolute",
|
|
108
|
+
width: "100%",
|
|
109
|
+
zIndex: docked ? 1 : -1,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const backgroundImageStyle = (
|
|
113
|
+
dimensions: QuickBrickPlayer.AudioPlayerProps["dimensions"],
|
|
114
|
+
minimisedHeight: number,
|
|
115
|
+
isActiveGesture: boolean
|
|
116
|
+
): ViewStyle => ({
|
|
117
|
+
height: isActiveGesture ? minimisedHeight : dimensions.height,
|
|
118
|
+
aspectRatio: 1,
|
|
119
|
+
position: "absolute",
|
|
120
|
+
});
|
|
121
|
+
|
|
102
122
|
const controlButtons = (
|
|
103
123
|
live: boolean,
|
|
104
124
|
paused: boolean,
|
|
@@ -160,74 +180,58 @@ export const DockedControls = (props: Props) => {
|
|
|
160
180
|
const {
|
|
161
181
|
entry,
|
|
162
182
|
layoutState,
|
|
183
|
+
playerState,
|
|
184
|
+
value,
|
|
185
|
+
dimensions,
|
|
186
|
+
onCloseVideoModal,
|
|
163
187
|
onPlayerSeek,
|
|
164
188
|
playNextData,
|
|
189
|
+
title,
|
|
190
|
+
summary,
|
|
165
191
|
ImageComponent,
|
|
166
|
-
isActiveGesture = true,
|
|
167
|
-
aspectRatio,
|
|
168
192
|
} = props;
|
|
169
193
|
|
|
170
|
-
const onCloseVideoModal = React.useCallback(() => {
|
|
171
|
-
playerManager.close();
|
|
172
|
-
}, []);
|
|
173
|
-
|
|
174
|
-
const { minimised_height: minimisedHeight } = useConfiguration();
|
|
175
|
-
|
|
176
|
-
const configuration = useZStore("playerConfiguration")();
|
|
177
|
-
const playerState = usePlayerState("shared-player-wrapper-docked");
|
|
178
|
-
|
|
179
|
-
const getValue = (key: string, stylesObj: {}) =>
|
|
180
|
-
R.propOr(null, key, stylesObj);
|
|
181
|
-
|
|
182
|
-
const value = React.useCallback(
|
|
183
|
-
(key: string) => {
|
|
184
|
-
const retVal = getValue(key, configuration);
|
|
185
|
-
|
|
186
|
-
const minimumAllowedSeekableDurationInSeconds = getValue(
|
|
187
|
-
"minimumAllowedSeekableDurationInSeconds",
|
|
188
|
-
configuration
|
|
189
|
-
);
|
|
190
|
-
|
|
191
|
-
if (key === "liveSeekingEnabled") {
|
|
192
|
-
return playerState.seekableDuration <
|
|
193
|
-
minimumAllowedSeekableDurationInSeconds || playerManager.isCasting()
|
|
194
|
-
? false
|
|
195
|
-
: retVal;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return retVal;
|
|
199
|
-
},
|
|
200
|
-
[...Object.values(configuration), playerState]
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
const { title, summary } = useTitleSummaryOverlay(
|
|
204
|
-
entry,
|
|
205
|
-
playerState?.isLive,
|
|
206
|
-
configuration?.audio_live_player_update_interval
|
|
207
|
-
);
|
|
208
|
-
|
|
209
194
|
const isTablet = useIsTablet();
|
|
210
195
|
|
|
211
196
|
const liveButton = Boolean(value("live_badge_enabled"));
|
|
212
197
|
|
|
213
|
-
const
|
|
198
|
+
const {
|
|
199
|
+
isActiveGesture,
|
|
200
|
+
setPlayerAnimationState,
|
|
201
|
+
startComponentsAnimation,
|
|
202
|
+
minimisedHeight,
|
|
203
|
+
progressBarHeight,
|
|
204
|
+
} = useModalAnimationContext();
|
|
205
|
+
|
|
206
|
+
const maximazeVideoModal = React.useCallback(
|
|
207
|
+
() => setPlayerAnimationState(PlayerAnimationStateEnum.maximize),
|
|
208
|
+
[]
|
|
209
|
+
);
|
|
214
210
|
|
|
215
211
|
const dockedBackgroundColor = value("docked_player_background_color");
|
|
216
212
|
|
|
217
213
|
const insets = useSafeAreaInsets();
|
|
218
214
|
|
|
215
|
+
if (!layoutState.docked && !startComponentsAnimation) return null;
|
|
216
|
+
|
|
219
217
|
return (
|
|
220
|
-
<
|
|
218
|
+
<AnimationComponent
|
|
219
|
+
animationType={ComponentAnimationType.componentAppears}
|
|
221
220
|
style={[
|
|
222
221
|
styles.container,
|
|
222
|
+
animatedContainerStyle(
|
|
223
|
+
isActiveGesture || layoutState.docked,
|
|
224
|
+
progressBarHeight
|
|
225
|
+
),
|
|
223
226
|
{
|
|
224
227
|
height: minimisedHeight + bottomTabBarHeight + insets.bottom,
|
|
225
228
|
},
|
|
226
229
|
]}
|
|
227
230
|
>
|
|
228
|
-
{!playerState.isLive
|
|
231
|
+
{!playerState.isLive &&
|
|
232
|
+
(layoutState.docked || startComponentsAnimation) ? (
|
|
229
233
|
<ProgressBar
|
|
230
|
-
name={"
|
|
234
|
+
name={"audio-docked-layout"}
|
|
231
235
|
content={entry}
|
|
232
236
|
value={value}
|
|
233
237
|
visible
|
|
@@ -240,33 +244,43 @@ export const DockedControls = (props: Props) => {
|
|
|
240
244
|
) : null}
|
|
241
245
|
|
|
242
246
|
<View style={styles.content}>
|
|
243
|
-
<View
|
|
244
|
-
{
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
) : (
|
|
249
|
-
<View
|
|
250
|
-
style={playerDimensionsStyle(
|
|
251
|
-
minimisedHeight,
|
|
252
|
-
isActiveGesture || layoutState.docked
|
|
253
|
-
)}
|
|
254
|
-
/>
|
|
247
|
+
<View
|
|
248
|
+
style={backgroundImageStyle(
|
|
249
|
+
dimensions,
|
|
250
|
+
minimisedHeight,
|
|
251
|
+
isActiveGesture
|
|
255
252
|
)}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
253
|
+
/>
|
|
254
|
+
<TouchableWithoutFeedback onPress={maximazeVideoModal}>
|
|
255
|
+
<View style={styles.touchableArea}>
|
|
256
|
+
{isActiveGesture || layoutState.docked ? (
|
|
257
|
+
<View
|
|
258
|
+
style={{ width: toNumberWithDefault(100, minimisedHeight) }}
|
|
259
|
+
>
|
|
260
|
+
{ImageComponent || null}
|
|
261
|
+
</View>
|
|
262
|
+
) : (
|
|
263
|
+
<View
|
|
264
|
+
style={playerDimensionsStyle(
|
|
265
|
+
minimisedHeight,
|
|
266
|
+
isActiveGesture || layoutState.docked
|
|
267
|
+
)}
|
|
268
|
+
/>
|
|
269
|
+
)}
|
|
270
|
+
<View
|
|
271
|
+
style={[
|
|
272
|
+
styles.contentInfo,
|
|
273
|
+
{ backgroundColor: dockedBackgroundColor },
|
|
274
|
+
]}
|
|
275
|
+
>
|
|
276
|
+
<ContentInfo
|
|
277
|
+
content={{ ...entry, title, summary }}
|
|
278
|
+
value={value}
|
|
279
|
+
docked
|
|
280
|
+
/>
|
|
281
|
+
</View>
|
|
268
282
|
</View>
|
|
269
|
-
</
|
|
283
|
+
</TouchableWithoutFeedback>
|
|
270
284
|
<View
|
|
271
285
|
style={[
|
|
272
286
|
isTablet
|
|
@@ -300,6 +314,6 @@ export const DockedControls = (props: Props) => {
|
|
|
300
314
|
backgroundColor: dockedBackgroundColor,
|
|
301
315
|
}}
|
|
302
316
|
/>
|
|
303
|
-
</
|
|
317
|
+
</AnimationComponent>
|
|
304
318
|
);
|
|
305
319
|
};
|
|
@@ -12,6 +12,7 @@ import { PlayerImage } from "./PlayerImage";
|
|
|
12
12
|
import { Controls } from "./Controls";
|
|
13
13
|
|
|
14
14
|
import { useMobileLayoutImageSize, useTransportInfoHeight } from "./hooks";
|
|
15
|
+
import { DockedControls } from "./DockedControls";
|
|
15
16
|
import { DEBUG, withDebug } from "./debug";
|
|
16
17
|
import {
|
|
17
18
|
BottomDebugSquare,
|
|
@@ -55,7 +56,6 @@ const mobileStyles = ({
|
|
|
55
56
|
imageSize,
|
|
56
57
|
}): ViewStyle => ({
|
|
57
58
|
height: screenHeight - topInset - bottomInset,
|
|
58
|
-
width: "100%",
|
|
59
59
|
|
|
60
60
|
opacity: imageSize ? 1 : 0, // hide content until imageSize is calculated
|
|
61
61
|
|
|
@@ -77,6 +77,7 @@ export function MobileLayout({
|
|
|
77
77
|
onSkipStart,
|
|
78
78
|
onSkipLive,
|
|
79
79
|
onSpeedButtonPress,
|
|
80
|
+
onCloseVideoModal,
|
|
80
81
|
playbackSpeedName,
|
|
81
82
|
configuration,
|
|
82
83
|
dimensions,
|
|
@@ -167,6 +168,7 @@ export function MobileLayout({
|
|
|
167
168
|
value={value}
|
|
168
169
|
configuration={configuration}
|
|
169
170
|
onPlayerSeek={onPlayerSeek}
|
|
171
|
+
onCloseVideoModal={onCloseVideoModal}
|
|
170
172
|
dimensions={dimensions}
|
|
171
173
|
playNextData={playNextData}
|
|
172
174
|
title={title}
|
|
@@ -202,6 +204,19 @@ export function MobileLayout({
|
|
|
202
204
|
/>
|
|
203
205
|
</View>
|
|
204
206
|
</View>
|
|
207
|
+
|
|
208
|
+
<DockedControls
|
|
209
|
+
entry={entry}
|
|
210
|
+
layoutState={layoutState}
|
|
211
|
+
playerState={playerState}
|
|
212
|
+
value={value}
|
|
213
|
+
dimensions={dimensions}
|
|
214
|
+
onCloseVideoModal={onCloseVideoModal}
|
|
215
|
+
onPlayerSeek={onPlayerSeek}
|
|
216
|
+
playNextData={playNextData}
|
|
217
|
+
title={title}
|
|
218
|
+
summary={summary}
|
|
219
|
+
/>
|
|
205
220
|
</View>
|
|
206
221
|
);
|
|
207
222
|
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
|
2
2
|
import { Image, Animated, StyleSheet, ImageStyle } from "react-native";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
useModalAnimationContext,
|
|
6
|
+
PlayerAnimationStateEnum,
|
|
7
|
+
DURATION_TO_MINIMIZE,
|
|
8
|
+
DURATION_TO_MAXIMIZE,
|
|
9
|
+
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
10
|
+
import { PlayerAnimationStateT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
|
|
11
|
+
import { useBackgroundImage } from "@applicaster/zapp-react-native-utils/audioPlayerUtils";
|
|
12
|
+
|
|
13
|
+
import { useChangePlayerState } from "./hooks";
|
|
5
14
|
|
|
6
15
|
const styles = StyleSheet.create({
|
|
7
16
|
container: {
|
|
@@ -15,17 +24,48 @@ type Props = PropsWithChildren<{
|
|
|
15
24
|
entry: ZappEntry;
|
|
16
25
|
style?: ImageStyle | ImageStyle[];
|
|
17
26
|
imageWidth: number;
|
|
27
|
+
docked: boolean;
|
|
18
28
|
}>;
|
|
19
29
|
|
|
20
|
-
export const AnimatedImage = ({ entry, style, imageWidth }: Props) => {
|
|
30
|
+
export const AnimatedImage = ({ entry, style, imageWidth, docked }: Props) => {
|
|
21
31
|
const heightAnim = React.useRef(new Animated.Value(imageWidth)).current;
|
|
22
32
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
const backgroundImageSource = useBackgroundImage(entry);
|
|
34
|
+
|
|
35
|
+
const { minimisedHeight } = useModalAnimationContext();
|
|
36
|
+
|
|
37
|
+
const changePlayerState$ = useChangePlayerState({ docked });
|
|
38
|
+
|
|
39
|
+
React.useEffect(() => {
|
|
40
|
+
const subscription = changePlayerState$.subscribe({
|
|
41
|
+
next: (nextPlayerState: PlayerAnimationStateT) => {
|
|
42
|
+
if (nextPlayerState === PlayerAnimationStateEnum.minimize) {
|
|
43
|
+
Animated.timing(heightAnim, {
|
|
44
|
+
toValue: minimisedHeight,
|
|
45
|
+
duration: DURATION_TO_MINIMIZE,
|
|
46
|
+
useNativeDriver: false, // width/height can't use native driver
|
|
47
|
+
}).start();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (nextPlayerState === PlayerAnimationStateEnum.maximize) {
|
|
51
|
+
Animated.timing(heightAnim, {
|
|
52
|
+
toValue: imageWidth,
|
|
53
|
+
duration: DURATION_TO_MAXIMIZE,
|
|
54
|
+
useNativeDriver: false, // width/height can't use native driver
|
|
55
|
+
}).start();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (nextPlayerState === PlayerAnimationStateEnum.appear_as_docked) {
|
|
59
|
+
// minimize image immediatly
|
|
60
|
+
heightAnim.setValue(minimisedHeight);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
});
|
|
27
64
|
|
|
28
|
-
|
|
65
|
+
return () => {
|
|
66
|
+
subscription.unsubscribe();
|
|
67
|
+
};
|
|
68
|
+
}, [changePlayerState$, minimisedHeight, imageWidth]);
|
|
29
69
|
|
|
30
70
|
return (
|
|
31
71
|
<Animated.View
|
|
@@ -36,7 +76,7 @@ export const AnimatedImage = ({ entry, style, imageWidth }: Props) => {
|
|
|
36
76
|
},
|
|
37
77
|
]}
|
|
38
78
|
>
|
|
39
|
-
<Image resizeMode="cover" style={style} source={
|
|
79
|
+
<Image resizeMode="cover" style={style} source={backgroundImageSource} />
|
|
40
80
|
</Animated.View>
|
|
41
81
|
);
|
|
42
82
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Image, ImageStyle } from "react-native";
|
|
3
|
-
|
|
4
|
-
import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
3
|
+
import { useBackgroundImage } from "@applicaster/zapp-react-native-utils/audioPlayerUtils";
|
|
5
4
|
|
|
6
5
|
type Props = {
|
|
7
6
|
entry: ZappEntry;
|
|
@@ -9,12 +8,9 @@ type Props = {
|
|
|
9
8
|
};
|
|
10
9
|
|
|
11
10
|
export const FlexImage = ({ entry, style }: Props) => {
|
|
12
|
-
const
|
|
13
|
-
() => ({ uri: imageSrcFromMediaItem(entry, undefined) }),
|
|
14
|
-
[entry]
|
|
15
|
-
);
|
|
11
|
+
const backgroundImageSource = useBackgroundImage(entry);
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
return (
|
|
14
|
+
<Image resizeMode="cover" style={style} source={backgroundImageSource} />
|
|
15
|
+
);
|
|
20
16
|
};
|