@applicaster/quick-brick-player 14.0.0-alpha.5974411329 → 14.0.0-alpha.6000342231
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/Controls/index.tsx +8 -18
- package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +117 -94
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +1 -6
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +5 -23
- 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/PlayerModal/PlayerModal.tsx +16 -15
- package/src/Player/PlayerModal/VideoPlayerModal.tsx +136 -124
- package/src/Player/PlayerModal/consts/index.ts +2 -19
- package/src/Player/PlayerModal/context/index.ts +6 -0
- package/src/Player/PlayerModal/hooks/index.ts +94 -127
- package/src/Player/PlayerModal/index.web.ts +5 -0
- package/src/Player/PlayerModal/styles.ts +54 -46
- package/src/Player/PlayerModal/utils/index.ts +89 -0
- package/src/Player/PlayerView/types.ts +1 -2
- package/src/Player/index.tsx +559 -366
- package/src/QuickBrickPlayer.tsx +16 -10
- 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": "14.0.0-alpha.
|
|
3
|
+
"version": "14.0.0-alpha.6000342231",
|
|
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-rc.
|
|
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.83",
|
|
39
|
+
"@applicaster/quick-brick-tv-transport-controls": "14.0.0-rc.71",
|
|
40
|
+
"@applicaster/zapp-react-native-tvos-app": "14.0.0-alpha.6000342231",
|
|
41
|
+
"@applicaster/zapp-react-native-ui-components": "14.0.0-alpha.6000342231",
|
|
42
|
+
"@applicaster/zapp-react-native-utils": "14.0.0-alpha.6000342231",
|
|
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,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { StyleSheet } from "react-native";
|
|
2
|
+
import { StyleSheet, View } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
|
|
5
5
|
import {
|
|
@@ -12,11 +12,6 @@ import {
|
|
|
12
12
|
} from "@applicaster/quick-brick-mobile-transport-controls";
|
|
13
13
|
import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils";
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
AnimationComponent,
|
|
17
|
-
ComponentAnimationType,
|
|
18
|
-
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
19
|
-
|
|
20
15
|
import { AudioDescription } from "../../AudioDescription";
|
|
21
16
|
import { isValidDate } from "../../../Utils";
|
|
22
17
|
import { VerticalGutter } from "./VerticalGutter";
|
|
@@ -103,8 +98,6 @@ export const Controls = (props: Props) => {
|
|
|
103
98
|
onSkipLive,
|
|
104
99
|
onSpeedButtonPress,
|
|
105
100
|
maxWidth = 320,
|
|
106
|
-
|
|
107
|
-
docked,
|
|
108
101
|
} = props;
|
|
109
102
|
|
|
110
103
|
const configuration = useZStore("playerConfiguration");
|
|
@@ -229,15 +222,8 @@ export const Controls = (props: Props) => {
|
|
|
229
222
|
isLiveShowFullControls,
|
|
230
223
|
]);
|
|
231
224
|
|
|
232
|
-
if (docked) {
|
|
233
|
-
return null;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
225
|
return (
|
|
237
|
-
<
|
|
238
|
-
animationType={ComponentAnimationType.componentFade}
|
|
239
|
-
style={isTablet ? styles.nonFlex : styles.flex}
|
|
240
|
-
>
|
|
226
|
+
<View style={isTablet ? styles.nonFlex : styles.flex}>
|
|
241
227
|
<VerticalGutter />
|
|
242
228
|
|
|
243
229
|
<AudioDescription
|
|
@@ -257,7 +243,11 @@ export const Controls = (props: Props) => {
|
|
|
257
243
|
content={entry}
|
|
258
244
|
value={value}
|
|
259
245
|
visible
|
|
260
|
-
layoutState={
|
|
246
|
+
layoutState={{
|
|
247
|
+
...layoutState,
|
|
248
|
+
docked: false, // always use non-docked layout for audio (to show time labels
|
|
249
|
+
inline: true, // always use inline layout for audio (to show time labels)
|
|
250
|
+
}}
|
|
261
251
|
onPlayerSeek={onPlayerSeek}
|
|
262
252
|
playerState={playerState}
|
|
263
253
|
disableFullscreen
|
|
@@ -286,6 +276,6 @@ export const Controls = (props: Props) => {
|
|
|
286
276
|
}}
|
|
287
277
|
playerState={playerState}
|
|
288
278
|
/>
|
|
289
|
-
</
|
|
279
|
+
</View>
|
|
290
280
|
);
|
|
291
281
|
};
|
|
@@ -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,30 +15,27 @@ 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";
|
|
19
|
+
import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
|
|
21
20
|
import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
|
|
22
21
|
import { useTitleSummaryOverlay } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerTitleSummaryOverlay";
|
|
23
22
|
import { usePlayerState } from "@applicaster/zapp-react-native-utils/appUtils/playerManager/usePlayerState";
|
|
24
23
|
import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
|
|
25
24
|
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
26
25
|
import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils";
|
|
26
|
+
import { isMenuVisible } from "@applicaster/zapp-react-native-ui-components/Components/Screen/navigationHandler";
|
|
27
|
+
import { usePlugins } from "@applicaster/zapp-react-native-redux";
|
|
28
|
+
import { partial } from "@applicaster/zapp-react-native-utils/utils";
|
|
27
29
|
|
|
28
30
|
const bottomTabBarHeight = getTabBarHeight();
|
|
29
31
|
|
|
30
32
|
type Props = {
|
|
31
33
|
entry: ZappEntry;
|
|
32
34
|
layoutState: QuickBrickPlayer.LayoutState;
|
|
33
|
-
|
|
34
|
-
value: GetValue;
|
|
35
|
-
onCloseVideoModal: () => void;
|
|
36
|
-
onPlayerSeek: (targetTime: number) => void;
|
|
35
|
+
onPlayerSeek?: (targetTime: number) => void;
|
|
37
36
|
playNextData: PlayNextData;
|
|
38
|
-
title: string | number;
|
|
39
|
-
summary: string | number;
|
|
40
37
|
ImageComponent?: React.ReactNode;
|
|
41
38
|
isActiveGesture?: boolean;
|
|
42
|
-
minimisedHeight: number;
|
|
43
39
|
aspectRatio?: number;
|
|
44
40
|
};
|
|
45
41
|
|
|
@@ -48,7 +44,6 @@ const styles = StyleSheet.create({
|
|
|
48
44
|
flex: 1,
|
|
49
45
|
flexDirection: "column",
|
|
50
46
|
alignItems: "stretch",
|
|
51
|
-
marginTop: PROGRESS_BAR_HEIGHT,
|
|
52
47
|
},
|
|
53
48
|
content: {
|
|
54
49
|
flex: 1,
|
|
@@ -91,14 +86,12 @@ const styles = StyleSheet.create({
|
|
|
91
86
|
buttons: {
|
|
92
87
|
marginVertical: 10,
|
|
93
88
|
},
|
|
89
|
+
liveMarginTop: { marginTop: 0 },
|
|
90
|
+
marginTop: { marginTop: PROGRESS_BAR_HEIGHT },
|
|
94
91
|
});
|
|
95
92
|
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
addPadding: boolean
|
|
99
|
-
): ViewStyle => ({
|
|
100
|
-
width: addPadding ? toNumberWithDefault(100, minimisedHeight) : 0,
|
|
101
|
-
});
|
|
93
|
+
const getValue = (key: string, stylesObj: Record<string, any>) =>
|
|
94
|
+
stylesObj?.[key] ?? null;
|
|
102
95
|
|
|
103
96
|
const controlButtons = (
|
|
104
97
|
live: boolean,
|
|
@@ -164,7 +157,6 @@ export const DockedControls = (props: Props) => {
|
|
|
164
157
|
onPlayerSeek = noop,
|
|
165
158
|
playNextData,
|
|
166
159
|
ImageComponent,
|
|
167
|
-
isActiveGesture = true,
|
|
168
160
|
aspectRatio,
|
|
169
161
|
} = props;
|
|
170
162
|
|
|
@@ -172,14 +164,16 @@ export const DockedControls = (props: Props) => {
|
|
|
172
164
|
playerManager.close();
|
|
173
165
|
}, []);
|
|
174
166
|
|
|
167
|
+
const { currentRoute, screenData } = useNavigation();
|
|
168
|
+
|
|
169
|
+
const plugins = usePlugins();
|
|
170
|
+
const menuVisible = isMenuVisible(currentRoute, screenData, plugins);
|
|
171
|
+
|
|
175
172
|
const { minimised_height: minimisedHeight } = useConfiguration();
|
|
176
173
|
|
|
177
174
|
const configuration = useZStore("playerConfiguration")();
|
|
178
175
|
const playerState = usePlayerState("shared-player-wrapper-docked");
|
|
179
176
|
|
|
180
|
-
const getValue = (key: string, stylesObj: {}) =>
|
|
181
|
-
R.propOr(null, key, stylesObj);
|
|
182
|
-
|
|
183
177
|
const value = React.useCallback(
|
|
184
178
|
(key: string) => {
|
|
185
179
|
const retVal = getValue(key, configuration);
|
|
@@ -198,7 +192,7 @@ export const DockedControls = (props: Props) => {
|
|
|
198
192
|
|
|
199
193
|
return retVal;
|
|
200
194
|
},
|
|
201
|
-
[...Object.values(configuration), playerState]
|
|
195
|
+
[...Object.values(configuration), playerState.seekableDuration]
|
|
202
196
|
);
|
|
203
197
|
|
|
204
198
|
const { title, summary } = useTitleSummaryOverlay(
|
|
@@ -215,90 +209,119 @@ export const DockedControls = (props: Props) => {
|
|
|
215
209
|
|
|
216
210
|
const insets = useSafeAreaInsets();
|
|
217
211
|
|
|
212
|
+
const progressBarLayoutState = React.useMemo(
|
|
213
|
+
() => ({
|
|
214
|
+
inline: layoutState.inline,
|
|
215
|
+
docked: true,
|
|
216
|
+
isModal: layoutState.isModal,
|
|
217
|
+
pip: layoutState.pip,
|
|
218
|
+
}),
|
|
219
|
+
[layoutState.inline, layoutState.isModal, layoutState.pip]
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
const _controlButtons = React.useMemo(
|
|
223
|
+
() => partial(controlButtons, playerState.isLive && liveButton),
|
|
224
|
+
[playerState.isLive, liveButton]
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
const containerStyles = React.useMemo(
|
|
228
|
+
() => ({
|
|
229
|
+
height: minimisedHeight,
|
|
230
|
+
maxHeight: minimisedHeight,
|
|
231
|
+
}),
|
|
232
|
+
[minimisedHeight]
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
const imageComponentWrapperStyles = React.useMemo(
|
|
236
|
+
() => ({
|
|
237
|
+
aspectRatio: aspectRatio,
|
|
238
|
+
height: minimisedHeight,
|
|
239
|
+
}),
|
|
240
|
+
[aspectRatio, minimisedHeight]
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
const backgroundColorStyle = React.useMemo(
|
|
244
|
+
() => ({
|
|
245
|
+
backgroundColor: dockedBackgroundColor,
|
|
246
|
+
}),
|
|
247
|
+
[dockedBackgroundColor]
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
const bottomSpacerStyle = React.useMemo(() => {
|
|
251
|
+
const tabBarHeight = menuVisible ? bottomTabBarHeight : 0;
|
|
252
|
+
const safeAreaBottomInset = insets.bottom || 0;
|
|
253
|
+
|
|
254
|
+
return {
|
|
255
|
+
height: safeAreaBottomInset + tabBarHeight,
|
|
256
|
+
};
|
|
257
|
+
}, [menuVisible, insets.bottom]);
|
|
258
|
+
|
|
259
|
+
const contentInfoContent = React.useMemo(
|
|
260
|
+
() => ({ ...entry, title, summary }),
|
|
261
|
+
[title, summary, entry]
|
|
262
|
+
);
|
|
263
|
+
|
|
218
264
|
return (
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
{isActiveGesture || layoutState.docked ? (
|
|
244
|
-
<View style={{ aspectRatio: aspectRatio, height: minimisedHeight }}>
|
|
265
|
+
<>
|
|
266
|
+
<View
|
|
267
|
+
style={[
|
|
268
|
+
styles.container,
|
|
269
|
+
containerStyles,
|
|
270
|
+
playerState.isLive ? styles.liveMarginTop : styles.marginTop,
|
|
271
|
+
]}
|
|
272
|
+
>
|
|
273
|
+
{!playerState.isLive ? (
|
|
274
|
+
<ProgressBar
|
|
275
|
+
name={"shared-docked-layout"}
|
|
276
|
+
content={entry}
|
|
277
|
+
value={value}
|
|
278
|
+
visible
|
|
279
|
+
layoutState={progressBarLayoutState}
|
|
280
|
+
onPlayerSeek={onPlayerSeek}
|
|
281
|
+
playerState={playerState}
|
|
282
|
+
docked
|
|
283
|
+
/>
|
|
284
|
+
) : null}
|
|
285
|
+
|
|
286
|
+
<View style={styles.content}>
|
|
287
|
+
<View style={styles.touchableArea}>
|
|
288
|
+
<View style={imageComponentWrapperStyles}>
|
|
245
289
|
{ImageComponent || null}
|
|
246
290
|
</View>
|
|
247
|
-
) : (
|
|
248
291
|
<View
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
292
|
+
testID="content-info"
|
|
293
|
+
style={[styles.contentInfo, backgroundColorStyle]}
|
|
294
|
+
>
|
|
295
|
+
<ContentInfo content={contentInfoContent} value={value} docked />
|
|
296
|
+
</View>
|
|
297
|
+
</View>
|
|
255
298
|
<View
|
|
256
|
-
testID="content-info"
|
|
257
299
|
style={[
|
|
258
|
-
|
|
259
|
-
|
|
300
|
+
isTablet
|
|
301
|
+
? styles.controlsContainerForTablet
|
|
302
|
+
: styles.controlsContainerForMobile,
|
|
303
|
+
backgroundColorStyle,
|
|
260
304
|
]}
|
|
261
305
|
>
|
|
262
|
-
<
|
|
263
|
-
|
|
306
|
+
<Controls
|
|
307
|
+
value={value}
|
|
308
|
+
visible
|
|
309
|
+
buttons={_controlButtons}
|
|
310
|
+
style={styles.playPauseButton}
|
|
311
|
+
playNextData={playNextData}
|
|
312
|
+
playerState={playerState}
|
|
313
|
+
/>
|
|
314
|
+
<Button
|
|
315
|
+
icon={"close_mini"}
|
|
316
|
+
size={"medium"}
|
|
264
317
|
value={value}
|
|
265
|
-
|
|
318
|
+
onPress={onCloseVideoModal}
|
|
319
|
+
style={styles.buttons}
|
|
266
320
|
/>
|
|
267
321
|
</View>
|
|
268
322
|
</View>
|
|
269
|
-
<View
|
|
270
|
-
style={[
|
|
271
|
-
isTablet
|
|
272
|
-
? styles.controlsContainerForTablet
|
|
273
|
-
: styles.controlsContainerForMobile,
|
|
274
|
-
{ backgroundColor: dockedBackgroundColor },
|
|
275
|
-
]}
|
|
276
|
-
>
|
|
277
|
-
<Controls
|
|
278
|
-
value={value}
|
|
279
|
-
visible
|
|
280
|
-
buttons={R.partial(controlButtons, [
|
|
281
|
-
playerState.isLive && liveButton,
|
|
282
|
-
])}
|
|
283
|
-
style={styles.playPauseButton}
|
|
284
|
-
playNextData={playNextData}
|
|
285
|
-
playerState={playerState}
|
|
286
|
-
/>
|
|
287
|
-
<Button
|
|
288
|
-
icon={"close_mini"}
|
|
289
|
-
size={"medium"}
|
|
290
|
-
value={value}
|
|
291
|
-
onPress={onCloseVideoModal}
|
|
292
|
-
style={styles.buttons}
|
|
293
|
-
/>
|
|
294
|
-
</View>
|
|
295
323
|
</View>
|
|
296
|
-
<View
|
|
297
|
-
|
|
298
|
-
height: insets.bottom + bottomTabBarHeight,
|
|
299
|
-
backgroundColor: dockedBackgroundColor,
|
|
300
|
-
}}
|
|
301
|
-
/>
|
|
302
|
-
</View>
|
|
324
|
+
<View style={[bottomSpacerStyle, backgroundColorStyle]} />
|
|
325
|
+
</>
|
|
303
326
|
);
|
|
304
327
|
};
|
|
@@ -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
|
|
|
@@ -4,7 +4,6 @@ import { LayoutChangeEvent, View } from "react-native";
|
|
|
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";
|
|
@@ -13,19 +12,12 @@ import { toNumberWithDefaultZero } from "@applicaster/zapp-react-native-utils/nu
|
|
|
13
12
|
type Props = {
|
|
14
13
|
entry: ZappEntry;
|
|
15
14
|
configuration: QuickBrickPlayer.AudioPlayerProps["configuration"];
|
|
16
|
-
docked
|
|
17
|
-
imageWidth?: Option<number>;
|
|
15
|
+
docked?: boolean;
|
|
18
16
|
onLayoutImage?: (event: LayoutChangeEvent) => void;
|
|
19
17
|
};
|
|
20
18
|
|
|
21
19
|
export const PlayerImage = (props: Props) => {
|
|
22
|
-
const {
|
|
23
|
-
entry,
|
|
24
|
-
docked,
|
|
25
|
-
imageWidth,
|
|
26
|
-
configuration,
|
|
27
|
-
onLayoutImage = noop,
|
|
28
|
-
} = props;
|
|
20
|
+
const { entry, docked = false, configuration, onLayoutImage = noop } = props;
|
|
29
21
|
|
|
30
22
|
const isShadowEnabled = toBooleanWithDefaultTrue(
|
|
31
23
|
configuration?.audio_player_artwork_shadow_enabled
|
|
@@ -43,19 +35,9 @@ export const PlayerImage = (props: Props) => {
|
|
|
43
35
|
onLayout={onLayoutImage}
|
|
44
36
|
style={[shouldShowShadow ? styles.shadow : undefined, { borderRadius }]}
|
|
45
37
|
>
|
|
46
|
-
{
|
|
47
|
-
<
|
|
48
|
-
|
|
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
|
-
)}
|
|
38
|
+
<View style={[styles.defaultImageWrapperView, { borderRadius }]}>
|
|
39
|
+
<FlexImage entry={entry} style={styles.backgroundImageContainer} />
|
|
40
|
+
</View>
|
|
59
41
|
</View>
|
|
60
42
|
</View>
|
|
61
43
|
);
|
|
@@ -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
|
-
};
|
|
@@ -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
|
>
|