@applicaster/quick-brick-player 15.0.0-rc.5 → 15.0.0-rc.52
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 +20 -8
- package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +78 -65
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +1 -6
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +27 -25
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +6 -1
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +5 -8
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +1 -6
- package/src/Player/AudioLayer/utils.ts +1 -27
- package/src/Player/PlayNextOverlay/index.tsx +2 -2
- package/src/Player/PlayerModal/PlayerModal.tsx +16 -15
- package/src/Player/PlayerModal/VideoPlayerModal.tsx +138 -120
- package/src/Player/PlayerModal/consts/index.ts +2 -19
- package/src/Player/PlayerModal/hooks/index.ts +115 -139
- package/src/Player/PlayerModal/styles.ts +5 -0
- package/src/Player/PlayerModal/utils/index.ts +111 -0
- package/src/Player/PlayerView/types.ts +1 -2
- package/src/Player/Utils/index.tsx +9 -9
- package/src/Player/hooks/progressStates/__tests__/utils.test.ts +23 -0
- package/src/Player/hooks/progressStates/useLiveProgressState.tsx +78 -0
- package/src/Player/hooks/progressStates/useProgressState.tsx +30 -0
- package/src/Player/hooks/progressStates/useVodProgressState.tsx +115 -0
- package/src/Player/hooks/progressStates/utils.ts +33 -0
- package/src/Player/index.tsx +559 -357
- package/src/utils/dimensions.ts +29 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/logger.ts +6 -0
- package/src/utils/playerHelpers.ts +11 -0
- package/src/utils/playerStyles.ts +50 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +0 -82
- package/src/Player/AudioLayer/Layout/PlayerImage/hooks/index.ts +0 -1
- package/src/Player/AudioLayer/Layout/PlayerImage/hooks/useChangePlayerState.ts +0 -99
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/quick-brick-player",
|
|
3
|
-
"version": "15.0.0-rc.
|
|
3
|
+
"version": "15.0.0-rc.52",
|
|
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": "
|
|
39
|
-
"@applicaster/quick-brick-tv-transport-controls": "
|
|
40
|
-
"@applicaster/zapp-react-native-tvos-app": "15.0.0-rc.
|
|
41
|
-
"@applicaster/zapp-react-native-ui-components": "15.0.0-rc.
|
|
42
|
-
"@applicaster/zapp-react-native-utils": "15.0.0-rc.
|
|
38
|
+
"@applicaster/quick-brick-mobile-transport-controls": "15.0.0-rc.52",
|
|
39
|
+
"@applicaster/quick-brick-tv-transport-controls": "15.0.0-rc.45",
|
|
40
|
+
"@applicaster/zapp-react-native-tvos-app": "15.0.0-rc.52",
|
|
41
|
+
"@applicaster/zapp-react-native-ui-components": "15.0.0-rc.52",
|
|
42
|
+
"@applicaster/zapp-react-native-utils": "15.0.0-rc.52",
|
|
43
43
|
"query-string": "7.1.3",
|
|
44
44
|
"shaka-player": "4.3.5",
|
|
45
45
|
"typeface-montserrat": "^0.0.54",
|
|
@@ -61,6 +61,7 @@ type Props = {
|
|
|
61
61
|
inline: boolean;
|
|
62
62
|
docked: boolean;
|
|
63
63
|
isModal: boolean;
|
|
64
|
+
pip: boolean;
|
|
64
65
|
};
|
|
65
66
|
playNextData: PlayNextData;
|
|
66
67
|
isTabletPortrait?: boolean;
|
|
@@ -99,11 +100,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
99
100
|
);
|
|
100
101
|
|
|
101
102
|
useEffect(() => {
|
|
102
|
-
|
|
103
|
-
setSpeedManager(new SpeedController(player));
|
|
104
|
-
} else {
|
|
105
|
-
setSpeedManager(null);
|
|
106
|
-
}
|
|
103
|
+
setSpeedManager(player ? new SpeedController(player) : null);
|
|
107
104
|
}, [player]);
|
|
108
105
|
|
|
109
106
|
useEffect(() => {
|
|
@@ -217,7 +214,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
217
214
|
items: speedOptions,
|
|
218
215
|
current_selection: playbackSpeed,
|
|
219
216
|
onPress: onSpeedSelect,
|
|
220
|
-
title: configuration
|
|
217
|
+
title: configuration.playback_speed_title,
|
|
221
218
|
itemProps: getBottomSheetModalItemProps,
|
|
222
219
|
iconProps: getBottomSheetModalIconProps,
|
|
223
220
|
labelProps: getBottomSheetModalLabelProps,
|
|
@@ -233,7 +230,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
233
230
|
],
|
|
234
231
|
},
|
|
235
232
|
});
|
|
236
|
-
}, [playbackSpeed, onSpeedSelect, configuration
|
|
233
|
+
}, [playbackSpeed, onSpeedSelect, configuration.playback_speed_title]);
|
|
237
234
|
|
|
238
235
|
const onPlayerSeek = React.useCallback(
|
|
239
236
|
(targetTime: number) => {
|
|
@@ -250,13 +247,28 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
250
247
|
player?.seekTo(0);
|
|
251
248
|
}, [player]);
|
|
252
249
|
|
|
250
|
+
const layoutStateMemo = React.useMemo(
|
|
251
|
+
() => ({
|
|
252
|
+
inline: layoutState.inline,
|
|
253
|
+
docked: layoutState.docked,
|
|
254
|
+
isModal: layoutState.isModal,
|
|
255
|
+
pip: layoutState.pip,
|
|
256
|
+
}),
|
|
257
|
+
[
|
|
258
|
+
layoutState.inline,
|
|
259
|
+
layoutState.docked,
|
|
260
|
+
layoutState.isModal,
|
|
261
|
+
layoutState.pip,
|
|
262
|
+
]
|
|
263
|
+
);
|
|
264
|
+
|
|
253
265
|
return (
|
|
254
266
|
<SafeAreaView style={[style, Styles.playerContainer]} edges={edges}>
|
|
255
267
|
<View style={Styles.playerContainer} onLayout={onLayout}>
|
|
256
268
|
<Layout
|
|
257
269
|
entry={entry}
|
|
258
270
|
playerState={playerState}
|
|
259
|
-
layoutState={
|
|
271
|
+
layoutState={layoutStateMemo}
|
|
260
272
|
value={value}
|
|
261
273
|
onPlaybackButtonPress={onPlaybackButtonPress}
|
|
262
274
|
onRewindButtonPress={onRewindButtonPress}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { StyleSheet, View
|
|
3
|
-
import * as R from "ramda";
|
|
2
|
+
import { StyleSheet, View } from "react-native";
|
|
4
3
|
import {
|
|
5
4
|
useIsTablet,
|
|
6
5
|
useZStore,
|
|
@@ -16,7 +15,6 @@ import {
|
|
|
16
15
|
|
|
17
16
|
import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
|
|
18
17
|
|
|
19
|
-
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
20
18
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
21
19
|
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
|
|
22
20
|
import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
|
|
@@ -25,24 +23,19 @@ import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/pl
|
|
|
25
23
|
import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
|
|
26
24
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
27
25
|
import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils";
|
|
28
|
-
import {
|
|
26
|
+
import { isBottomTabVisible } from "@applicaster/zapp-react-native-ui-components/Components/Screen/navigationHandler";
|
|
29
27
|
import { usePlugins } from "@applicaster/zapp-react-native-redux";
|
|
28
|
+
import { partial } from "@applicaster/zapp-react-native-utils/utils";
|
|
30
29
|
|
|
31
30
|
const bottomTabBarHeight = getTabBarHeight();
|
|
32
31
|
|
|
33
32
|
type Props = {
|
|
34
33
|
entry: ZappEntry;
|
|
35
34
|
layoutState: QuickBrickPlayer.LayoutState;
|
|
36
|
-
|
|
37
|
-
value: GetValue;
|
|
38
|
-
onCloseVideoModal: () => void;
|
|
39
|
-
onPlayerSeek: (targetTime: number) => void;
|
|
35
|
+
onPlayerSeek?: (targetTime: number) => void;
|
|
40
36
|
playNextData: PlayNextData;
|
|
41
|
-
title: string | number;
|
|
42
|
-
summary: string | number;
|
|
43
37
|
ImageComponent?: React.ReactNode;
|
|
44
38
|
isActiveGesture?: boolean;
|
|
45
|
-
minimisedHeight: number;
|
|
46
39
|
aspectRatio?: number;
|
|
47
40
|
};
|
|
48
41
|
|
|
@@ -51,7 +44,6 @@ const styles = StyleSheet.create({
|
|
|
51
44
|
flex: 1,
|
|
52
45
|
flexDirection: "column",
|
|
53
46
|
alignItems: "stretch",
|
|
54
|
-
marginTop: PROGRESS_BAR_HEIGHT,
|
|
55
47
|
},
|
|
56
48
|
content: {
|
|
57
49
|
flex: 1,
|
|
@@ -94,14 +86,12 @@ const styles = StyleSheet.create({
|
|
|
94
86
|
buttons: {
|
|
95
87
|
marginVertical: 10,
|
|
96
88
|
},
|
|
89
|
+
liveMarginTop: { marginTop: 0 },
|
|
90
|
+
marginTop: { marginTop: PROGRESS_BAR_HEIGHT },
|
|
97
91
|
});
|
|
98
92
|
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
addPadding: boolean
|
|
102
|
-
): ViewStyle => ({
|
|
103
|
-
width: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
|
|
104
|
-
});
|
|
93
|
+
const getValue = (key: string, stylesObj: Record<string, any>) =>
|
|
94
|
+
stylesObj?.[key] ?? null;
|
|
105
95
|
|
|
106
96
|
const controlButtons = (
|
|
107
97
|
live: boolean,
|
|
@@ -167,7 +157,6 @@ export const DockedControls = (props: Props) => {
|
|
|
167
157
|
onPlayerSeek = noop,
|
|
168
158
|
playNextData,
|
|
169
159
|
ImageComponent,
|
|
170
|
-
isActiveGesture = true,
|
|
171
160
|
aspectRatio,
|
|
172
161
|
} = props;
|
|
173
162
|
|
|
@@ -178,18 +167,18 @@ export const DockedControls = (props: Props) => {
|
|
|
178
167
|
const { currentRoute, screenData } = useNavigation();
|
|
179
168
|
|
|
180
169
|
const plugins = usePlugins();
|
|
181
|
-
|
|
170
|
+
|
|
171
|
+
const bottomTabsVisible = isBottomTabVisible(
|
|
172
|
+
currentRoute,
|
|
173
|
+
screenData,
|
|
174
|
+
plugins
|
|
175
|
+
);
|
|
182
176
|
|
|
183
177
|
const { minimised_height: minimisedHeight } = useConfiguration();
|
|
184
178
|
|
|
185
179
|
const configuration = useZStore("playerConfiguration")();
|
|
186
180
|
const playerState = usePlayerState("shared-player-wrapper-docked");
|
|
187
181
|
|
|
188
|
-
const getValue = React.useCallback(
|
|
189
|
-
(key: string, stylesObj: {}) => R.propOr(null, key, stylesObj),
|
|
190
|
-
[]
|
|
191
|
-
);
|
|
192
|
-
|
|
193
182
|
const value = React.useCallback(
|
|
194
183
|
(key: string) => {
|
|
195
184
|
const retVal = getValue(key, configuration);
|
|
@@ -208,7 +197,7 @@ export const DockedControls = (props: Props) => {
|
|
|
208
197
|
|
|
209
198
|
return retVal;
|
|
210
199
|
},
|
|
211
|
-
[...Object.values(configuration), playerState.seekableDuration
|
|
200
|
+
[...Object.values(configuration), playerState.seekableDuration]
|
|
212
201
|
);
|
|
213
202
|
|
|
214
203
|
const { title, summary } = useTitleSummaryOverlay(
|
|
@@ -225,15 +214,65 @@ export const DockedControls = (props: Props) => {
|
|
|
225
214
|
|
|
226
215
|
const insets = useSafeAreaInsets();
|
|
227
216
|
|
|
217
|
+
const progressBarLayoutState = React.useMemo(
|
|
218
|
+
() => ({
|
|
219
|
+
inline: layoutState.inline,
|
|
220
|
+
docked: true,
|
|
221
|
+
isModal: layoutState.isModal,
|
|
222
|
+
pip: layoutState.pip,
|
|
223
|
+
}),
|
|
224
|
+
[layoutState.inline, layoutState.isModal, layoutState.pip]
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
const _controlButtons = React.useMemo(
|
|
228
|
+
() => partial(controlButtons, playerState.isLive && liveButton),
|
|
229
|
+
[playerState.isLive, liveButton]
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const containerStyles = React.useMemo(
|
|
233
|
+
() => ({
|
|
234
|
+
height: minimisedHeight,
|
|
235
|
+
maxHeight: minimisedHeight,
|
|
236
|
+
}),
|
|
237
|
+
[minimisedHeight]
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
const imageComponentWrapperStyles = React.useMemo(
|
|
241
|
+
() => ({
|
|
242
|
+
aspectRatio: aspectRatio,
|
|
243
|
+
height: minimisedHeight,
|
|
244
|
+
}),
|
|
245
|
+
[aspectRatio, minimisedHeight]
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const backgroundColorStyle = React.useMemo(
|
|
249
|
+
() => ({
|
|
250
|
+
backgroundColor: dockedBackgroundColor,
|
|
251
|
+
}),
|
|
252
|
+
[dockedBackgroundColor]
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
const bottomSpacerStyle = React.useMemo(() => {
|
|
256
|
+
const tabBarHeight = bottomTabsVisible ? bottomTabBarHeight : 0;
|
|
257
|
+
const safeAreaBottomInset = insets.bottom || 0;
|
|
258
|
+
|
|
259
|
+
return {
|
|
260
|
+
height: safeAreaBottomInset + tabBarHeight,
|
|
261
|
+
};
|
|
262
|
+
}, [bottomTabsVisible, insets.bottom]);
|
|
263
|
+
|
|
264
|
+
const contentInfoContent = React.useMemo(
|
|
265
|
+
() => ({ ...entry, title, summary }),
|
|
266
|
+
[title, summary, entry]
|
|
267
|
+
);
|
|
268
|
+
|
|
228
269
|
return (
|
|
229
270
|
<>
|
|
230
271
|
<View
|
|
231
272
|
style={[
|
|
232
273
|
styles.container,
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
maxHeight: minimisedHeight,
|
|
236
|
-
},
|
|
274
|
+
containerStyles,
|
|
275
|
+
playerState.isLive ? styles.liveMarginTop : styles.marginTop,
|
|
237
276
|
]}
|
|
238
277
|
>
|
|
239
278
|
{!playerState.isLive ? (
|
|
@@ -242,42 +281,23 @@ export const DockedControls = (props: Props) => {
|
|
|
242
281
|
content={entry}
|
|
243
282
|
value={value}
|
|
244
283
|
visible
|
|
245
|
-
layoutState={
|
|
284
|
+
layoutState={progressBarLayoutState}
|
|
246
285
|
onPlayerSeek={onPlayerSeek}
|
|
247
286
|
playerState={playerState}
|
|
248
|
-
startComponentsAnimation={noop}
|
|
249
287
|
docked
|
|
250
288
|
/>
|
|
251
289
|
) : null}
|
|
252
290
|
|
|
253
291
|
<View style={styles.content}>
|
|
254
292
|
<View style={styles.touchableArea}>
|
|
255
|
-
{
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
>
|
|
259
|
-
{ImageComponent || null}
|
|
260
|
-
</View>
|
|
261
|
-
) : (
|
|
262
|
-
<View
|
|
263
|
-
style={playerDimensionsStyle(
|
|
264
|
-
minimisedHeight,
|
|
265
|
-
isActiveGesture || layoutState.docked
|
|
266
|
-
)}
|
|
267
|
-
/>
|
|
268
|
-
)}
|
|
293
|
+
<View style={imageComponentWrapperStyles}>
|
|
294
|
+
{ImageComponent || null}
|
|
295
|
+
</View>
|
|
269
296
|
<View
|
|
270
297
|
testID="content-info"
|
|
271
|
-
style={[
|
|
272
|
-
styles.contentInfo,
|
|
273
|
-
{ backgroundColor: dockedBackgroundColor },
|
|
274
|
-
]}
|
|
298
|
+
style={[styles.contentInfo, backgroundColorStyle]}
|
|
275
299
|
>
|
|
276
|
-
<ContentInfo
|
|
277
|
-
content={{ ...entry, title, summary }}
|
|
278
|
-
value={value}
|
|
279
|
-
docked
|
|
280
|
-
/>
|
|
300
|
+
<ContentInfo content={contentInfoContent} value={value} docked />
|
|
281
301
|
</View>
|
|
282
302
|
</View>
|
|
283
303
|
<View
|
|
@@ -285,15 +305,13 @@ export const DockedControls = (props: Props) => {
|
|
|
285
305
|
isTablet
|
|
286
306
|
? styles.controlsContainerForTablet
|
|
287
307
|
: styles.controlsContainerForMobile,
|
|
288
|
-
|
|
308
|
+
backgroundColorStyle,
|
|
289
309
|
]}
|
|
290
310
|
>
|
|
291
311
|
<Controls
|
|
292
312
|
value={value}
|
|
293
313
|
visible
|
|
294
|
-
buttons={
|
|
295
|
-
playerState.isLive && liveButton,
|
|
296
|
-
])}
|
|
314
|
+
buttons={_controlButtons}
|
|
297
315
|
style={styles.playPauseButton}
|
|
298
316
|
playNextData={playNextData}
|
|
299
317
|
playerState={playerState}
|
|
@@ -308,12 +326,7 @@ export const DockedControls = (props: Props) => {
|
|
|
308
326
|
</View>
|
|
309
327
|
</View>
|
|
310
328
|
</View>
|
|
311
|
-
<View
|
|
312
|
-
style={{
|
|
313
|
-
height: insets.bottom + (menuVisible ? bottomTabBarHeight : 0),
|
|
314
|
-
backgroundColor: dockedBackgroundColor,
|
|
315
|
-
}}
|
|
316
|
-
/>
|
|
329
|
+
<View style={[bottomSpacerStyle, backgroundColorStyle]} />
|
|
317
330
|
</>
|
|
318
331
|
);
|
|
319
332
|
};
|
|
@@ -151,12 +151,7 @@ export function MobileLayout({
|
|
|
151
151
|
},
|
|
152
152
|
]}
|
|
153
153
|
>
|
|
154
|
-
<PlayerImage
|
|
155
|
-
entry={entry}
|
|
156
|
-
docked={false}
|
|
157
|
-
imageWidth={imageSize}
|
|
158
|
-
configuration={configuration}
|
|
159
|
-
/>
|
|
154
|
+
<PlayerImage entry={entry} configuration={configuration} />
|
|
160
155
|
</View>
|
|
161
156
|
{/* PlayerImage */}
|
|
162
157
|
|
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { LayoutChangeEvent, View } from "react-native";
|
|
2
|
+
import { Animated, LayoutChangeEvent, View } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
5
5
|
import { toBooleanWithDefaultTrue } from "@applicaster/zapp-react-native-utils/booleanUtils";
|
|
6
6
|
|
|
7
|
-
import { AnimatedImage } from "./AnimatedImage";
|
|
8
7
|
import { FlexImage } from "./FlexImage";
|
|
9
8
|
|
|
10
9
|
import { styles } from "./styles";
|
|
11
10
|
import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
11
|
+
import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
12
12
|
|
|
13
13
|
type Props = {
|
|
14
14
|
entry: ZappEntry;
|
|
15
15
|
configuration: QuickBrickPlayer.AudioPlayerProps["configuration"];
|
|
16
|
-
docked
|
|
17
|
-
imageWidth?: Option<number>;
|
|
16
|
+
docked?: boolean;
|
|
18
17
|
onLayoutImage?: (event: LayoutChangeEvent) => void;
|
|
19
18
|
};
|
|
20
19
|
|
|
21
20
|
export const PlayerImage = (props: Props) => {
|
|
22
|
-
const {
|
|
23
|
-
entry,
|
|
24
|
-
docked,
|
|
25
|
-
imageWidth,
|
|
26
|
-
configuration,
|
|
27
|
-
onLayoutImage = noop,
|
|
28
|
-
} = props;
|
|
21
|
+
const { entry, docked = false, configuration, onLayoutImage = noop } = props;
|
|
29
22
|
|
|
30
23
|
const isShadowEnabled = toBooleanWithDefaultTrue(
|
|
31
24
|
configuration?.audio_player_artwork_shadow_enabled
|
|
@@ -37,25 +30,34 @@ export const PlayerImage = (props: Props) => {
|
|
|
37
30
|
configuration.audio_player_artwork_border_radius
|
|
38
31
|
);
|
|
39
32
|
|
|
33
|
+
const { yTranslate } = useModalAnimationContext();
|
|
34
|
+
|
|
35
|
+
const isModalExpanded = yTranslate.current.interpolate({
|
|
36
|
+
inputRange: [0, 1], // this should be end with `1` only when it's in initial state ( 0pos), otherwise `0`
|
|
37
|
+
outputRange: [1, 0],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// do not use styles.shadow when isModalExpanded is 0
|
|
41
|
+
|
|
42
|
+
const animatedStyle = {
|
|
43
|
+
opacity: isModalExpanded,
|
|
44
|
+
};
|
|
45
|
+
|
|
40
46
|
return (
|
|
41
47
|
<View style={styles.alignItemsCenter}>
|
|
48
|
+
{/* Using an Animated.View to apply shadow to the image */}
|
|
49
|
+
<Animated.View
|
|
50
|
+
style={[
|
|
51
|
+
animatedStyle,
|
|
52
|
+
shouldShowShadow ? styles.shadow : undefined,
|
|
53
|
+
{ borderRadius },
|
|
54
|
+
]}
|
|
55
|
+
/>
|
|
42
56
|
<View
|
|
43
57
|
onLayout={onLayoutImage}
|
|
44
|
-
style={[
|
|
58
|
+
style={[styles.defaultImageWrapperView, { borderRadius }]}
|
|
45
59
|
>
|
|
46
|
-
{
|
|
47
|
-
<View style={[styles.defaultImageWrapperView, { borderRadius }]}>
|
|
48
|
-
<FlexImage entry={entry} style={styles.backgroundImageContainer} />
|
|
49
|
-
</View>
|
|
50
|
-
) : (
|
|
51
|
-
// we have imageSize here and now we could animate resizing of this image
|
|
52
|
-
<AnimatedImage
|
|
53
|
-
entry={entry}
|
|
54
|
-
style={[styles.backgroundImageContainer, { borderRadius }]}
|
|
55
|
-
imageWidth={imageWidth}
|
|
56
|
-
docked={docked}
|
|
57
|
-
/>
|
|
58
|
-
)}
|
|
60
|
+
<FlexImage entry={entry} style={styles.backgroundImageContainer} />
|
|
59
61
|
</View>
|
|
60
62
|
</View>
|
|
61
63
|
);
|
|
@@ -23,7 +23,12 @@ export const styles = StyleSheet.create({
|
|
|
23
23
|
overflow: "hidden",
|
|
24
24
|
},
|
|
25
25
|
shadow: {
|
|
26
|
-
|
|
26
|
+
zIndex: 0,
|
|
27
|
+
position: "absolute",
|
|
28
|
+
top: 0,
|
|
29
|
+
left: 0,
|
|
30
|
+
right: 0,
|
|
31
|
+
bottom: 0,
|
|
27
32
|
shadowColor: SHADOW_COLOR,
|
|
28
33
|
shadowOffset: { width: 0, height: 24 },
|
|
29
34
|
shadowOpacity: platformSelect({
|
|
@@ -117,14 +117,11 @@ export function TabletLandscapeLayout({
|
|
|
117
117
|
<View style={[styles.flex, styles.audioPlayerContainerHeightLimit]}>
|
|
118
118
|
{/* PlayerImage non-docked */}
|
|
119
119
|
<View style={[styles.flex, withDebug(styles.debugYellow)]}>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
onLayoutImage={onLayoutImage}
|
|
126
|
-
/>
|
|
127
|
-
) : null}
|
|
120
|
+
<PlayerImage
|
|
121
|
+
entry={entry}
|
|
122
|
+
configuration={configuration}
|
|
123
|
+
onLayoutImage={onLayoutImage}
|
|
124
|
+
/>
|
|
128
125
|
</View>
|
|
129
126
|
{/* PlayerImage */}
|
|
130
127
|
|
|
@@ -144,12 +144,7 @@ export function TabletPortraitLayout({
|
|
|
144
144
|
]}
|
|
145
145
|
onLayout={onLayout}
|
|
146
146
|
>
|
|
147
|
-
<PlayerImage
|
|
148
|
-
entry={entry}
|
|
149
|
-
configuration={configuration}
|
|
150
|
-
docked={docked}
|
|
151
|
-
imageWidth={imageSize}
|
|
152
|
-
/>
|
|
147
|
+
<PlayerImage entry={entry} configuration={configuration} />
|
|
153
148
|
</View>
|
|
154
149
|
|
|
155
150
|
<View
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
2
|
-
|
|
3
|
-
PlayerAnimationStateEnum,
|
|
4
|
-
PlayerAnimationStateT,
|
|
5
|
-
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
|
|
2
|
+
|
|
6
3
|
import { parseJsonIfNeeded } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
7
|
-
import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
8
4
|
|
|
9
5
|
export const NAMESPACE = "audio-player";
|
|
10
6
|
|
|
@@ -36,25 +32,3 @@ export const formatSpeed = (value: number) => {
|
|
|
36
32
|
// Return the formatted string with "speed_" prefix
|
|
37
33
|
return `speed_${formattedValue}`;
|
|
38
34
|
};
|
|
39
|
-
|
|
40
|
-
export const calculateBorderRadius = (
|
|
41
|
-
docked: boolean,
|
|
42
|
-
startComponentsAnimation: boolean,
|
|
43
|
-
isActiveGesture: boolean,
|
|
44
|
-
playerAnimationState: PlayerAnimationStateT,
|
|
45
|
-
configuration: Record<string, any>
|
|
46
|
-
): number => {
|
|
47
|
-
const shouldRemoveBorderRadius =
|
|
48
|
-
(startComponentsAnimation &&
|
|
49
|
-
isActiveGesture &&
|
|
50
|
-
playerAnimationState !== PlayerAnimationStateEnum.maximize) ||
|
|
51
|
-
docked;
|
|
52
|
-
|
|
53
|
-
if (shouldRemoveBorderRadius) {
|
|
54
|
-
return 0;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return toNumberWithDefaultZero(
|
|
58
|
-
configuration.audio_player_artwork_border_radius
|
|
59
|
-
);
|
|
60
|
-
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as R from "ramda";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { usePlugins } from "@applicaster/zapp-react-native-redux";
|
|
5
5
|
import { PlayNextData } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
|
|
6
6
|
|
|
7
7
|
type Props = {
|
|
@@ -32,7 +32,7 @@ export const PlayNextOverlay = ({
|
|
|
32
32
|
playNextData,
|
|
33
33
|
setNextVideoPreloadThresholdPercentage,
|
|
34
34
|
}: Props) => {
|
|
35
|
-
const
|
|
35
|
+
const plugins = usePlugins();
|
|
36
36
|
|
|
37
37
|
const OverlayPlugin = getOverlayPlugin(plugins);
|
|
38
38
|
|
|
@@ -4,8 +4,9 @@ import { Animated, Pressable } from "react-native";
|
|
|
4
4
|
import { PanGestureHandler } from "react-native-gesture-handler";
|
|
5
5
|
import { useStyles } from "./styles";
|
|
6
6
|
import { useVideoModalState } from "./hooks";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { MODAL_COLLAPSE_RATIO, MODAL_RADIUS } from "./consts";
|
|
8
|
+
import { getWindowHeight } from "./utils";
|
|
9
|
+
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
|
9
10
|
|
|
10
11
|
type AnimatedModalProps = {
|
|
11
12
|
content?: ReactElement;
|
|
@@ -16,33 +17,34 @@ export function AnimatedModal({
|
|
|
16
17
|
content,
|
|
17
18
|
collapsedContent,
|
|
18
19
|
}: AnimatedModalProps) {
|
|
19
|
-
const
|
|
20
|
+
const { translateY, collapsed, gestureHandlerProps, expand, offset } =
|
|
21
|
+
useVideoModalState();
|
|
20
22
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
expand,
|
|
27
|
-
} = useVideoModalState(translateYRef);
|
|
23
|
+
const frame = useSafeAreaFrame();
|
|
24
|
+
const collapsedHeight = frame.height - offset.current;
|
|
25
|
+
|
|
26
|
+
const height = getWindowHeight();
|
|
27
|
+
const heightAboveMinimised = height - collapsedHeight;
|
|
28
28
|
|
|
29
29
|
const styles = useStyles({ height: collapsedHeight, type: "audio" });
|
|
30
30
|
|
|
31
|
+
const MODAL_COLLAPSE_START = height * MODAL_COLLAPSE_RATIO;
|
|
32
|
+
|
|
31
33
|
// Interpolated opacities for smooth cross-fade
|
|
32
34
|
const collapsedOpacity = translateY.interpolate({
|
|
33
|
-
inputRange: [MODAL_COLLAPSE_START,
|
|
35
|
+
inputRange: [MODAL_COLLAPSE_START, heightAboveMinimised],
|
|
34
36
|
outputRange: [0, 1],
|
|
35
37
|
extrapolate: "clamp",
|
|
36
38
|
});
|
|
37
39
|
|
|
38
40
|
const expandedOpacity = translateY.interpolate({
|
|
39
|
-
inputRange: [0,
|
|
41
|
+
inputRange: [0, heightAboveMinimised],
|
|
40
42
|
outputRange: [1, 0],
|
|
41
43
|
extrapolate: "clamp",
|
|
42
44
|
});
|
|
43
45
|
|
|
44
46
|
const borderTopRadiusAnimated = translateY.interpolate({
|
|
45
|
-
inputRange: [0,
|
|
47
|
+
inputRange: [0, heightAboveMinimised],
|
|
46
48
|
outputRange: [MODAL_RADIUS, 0],
|
|
47
49
|
extrapolate: "clamp",
|
|
48
50
|
});
|
|
@@ -57,7 +59,7 @@ export function AnimatedModal({
|
|
|
57
59
|
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
58
60
|
borderTopRightRadius: borderTopRadiusAnimated,
|
|
59
61
|
transform: [{ translateY }],
|
|
60
|
-
height:
|
|
62
|
+
height: height,
|
|
61
63
|
},
|
|
62
64
|
]}
|
|
63
65
|
>
|
|
@@ -67,7 +69,6 @@ export function AnimatedModal({
|
|
|
67
69
|
{
|
|
68
70
|
borderTopLeftRadius: borderTopRadiusAnimated,
|
|
69
71
|
borderTopRightRadius: borderTopRadiusAnimated,
|
|
70
|
-
height: SCREEN_HEIGHT,
|
|
71
72
|
},
|
|
72
73
|
]}
|
|
73
74
|
>
|