@applicaster/quick-brick-player 13.0.0-alpha.2886020207 → 13.0.0-alpha.3003916059
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 +5 -5
- package/src/Player/AudioLayer/AudioDescription.tsx +1 -1
- package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +28 -75
- package/src/Player/AudioLayer/Layout/Controls/index.tsx +15 -49
- package/src/Player/AudioLayer/Layout/Controls/utils.ts +2 -2
- package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +24 -7
- package/src/Player/AudioLayer/Layout/MobileLayout.tsx +0 -8
- package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +38 -34
- package/src/Player/AudioLayer/Layout/PlayerImage/FlexImage.tsx +4 -9
- package/src/Player/AudioLayer/Layout/PlayerImage/hooks/index.ts +1 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/hooks/useChangePlayerState.ts +99 -0
- package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +18 -18
- package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +8 -1
- package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +44 -46
- package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +0 -8
- package/src/Player/AudioLayer/SleepTimerManager.ts +22 -11
- package/src/Player/AudioLayer/components/SleepTimerModalHeader/SleepTimerModalHeader.tsx +66 -0
- package/src/Player/AudioLayer/components/SleepTimerModalHeader/index.ts +1 -0
- package/src/Player/AudioLayer/useSleepTimerModal.ts +109 -0
- package/src/Player/Const/sleepTimerOptions.ts +7 -5
- package/src/Player/Utils/index.tsx +6 -0
- package/src/Player/hooks/useIsCasting.tsx +1 -1
- package/src/Player/index.tsx +52 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applicaster/quick-brick-player",
|
|
3
|
-
"version": "13.0.0-alpha.
|
|
3
|
+
"version": "13.0.0-alpha.3003916059",
|
|
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": "13.0.0-rc.
|
|
38
|
+
"@applicaster/quick-brick-mobile-transport-controls": "13.0.0-rc.124",
|
|
39
39
|
"@applicaster/quick-brick-tv-transport-controls": "13.0.0-rc.56",
|
|
40
|
-
"@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.
|
|
41
|
-
"@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.
|
|
42
|
-
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.
|
|
40
|
+
"@applicaster/zapp-react-native-tvos-app": "13.0.0-alpha.3003916059",
|
|
41
|
+
"@applicaster/zapp-react-native-ui-components": "13.0.0-alpha.3003916059",
|
|
42
|
+
"@applicaster/zapp-react-native-utils": "13.0.0-alpha.3003916059",
|
|
43
43
|
"query-string": "7.1.3",
|
|
44
44
|
"react-native-web-linear-gradient": "1.1.2",
|
|
45
45
|
"shaka-player": "4.3.5",
|
|
@@ -37,14 +37,13 @@ import {
|
|
|
37
37
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
38
38
|
import { PADDING_HORIZONTAL } from "./Layout/const";
|
|
39
39
|
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
40
|
-
|
|
41
|
-
SLEEP_TIMER_OFF,
|
|
42
|
-
SleepTimerController,
|
|
43
|
-
SleepTimerState,
|
|
44
|
-
} from "./SleepTimerManager";
|
|
40
|
+
|
|
45
41
|
import { DEFAULT_SPEED, PlaybackSpeed, SpeedController } from "./SpeedManager";
|
|
46
|
-
import {
|
|
47
|
-
|
|
42
|
+
import {
|
|
43
|
+
dismissModal as dismissBottomSheetModal,
|
|
44
|
+
openBottomSheetModal,
|
|
45
|
+
useModalStoreState,
|
|
46
|
+
} from "@applicaster/zapp-react-native-utils/modalState";
|
|
48
47
|
import { speedOptions } from "../Const/speedOptions";
|
|
49
48
|
|
|
50
49
|
const { log_debug } = createLogger({
|
|
@@ -61,7 +60,6 @@ type Dimensions = {
|
|
|
61
60
|
|
|
62
61
|
type Configuration = {
|
|
63
62
|
[key: string]: any;
|
|
64
|
-
audio_player_background_image_query?: string;
|
|
65
63
|
audio_player_background_image_default_color?: string;
|
|
66
64
|
tablet_landscape_sidebar_width?: string;
|
|
67
65
|
tablet_landscape_player_container_background_color?: string;
|
|
@@ -103,6 +101,8 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
103
101
|
const player = usePlayer();
|
|
104
102
|
const playerState = usePlayerState("audio-player-wrapper");
|
|
105
103
|
|
|
104
|
+
const modalBottomSheetState = useModalStoreState();
|
|
105
|
+
|
|
106
106
|
const {
|
|
107
107
|
configuration,
|
|
108
108
|
style,
|
|
@@ -123,30 +123,39 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
123
123
|
configuration?.audio_live_player_update_interval
|
|
124
124
|
);
|
|
125
125
|
|
|
126
|
-
const [sleepTimerManager, setSleepTimerManager] =
|
|
127
|
-
useState<SleepTimerController | null>(null);
|
|
128
|
-
|
|
129
126
|
const [speedManager, setSpeedManager] = useState<SpeedController | null>(
|
|
130
127
|
null
|
|
131
128
|
);
|
|
132
129
|
|
|
133
130
|
useEffect(() => {
|
|
134
131
|
if (player) {
|
|
135
|
-
setSleepTimerManager(new SleepTimerController(player));
|
|
136
132
|
setSpeedManager(new SpeedController(player));
|
|
137
133
|
} else {
|
|
138
|
-
setSleepTimerManager(null);
|
|
139
134
|
setSpeedManager(null);
|
|
140
135
|
}
|
|
141
136
|
}, [player]);
|
|
142
137
|
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
if (!player) return;
|
|
140
|
+
|
|
141
|
+
const unsubscribe = player.addListener({
|
|
142
|
+
id: "audio-player-wrapper-bottom-sheet-modal",
|
|
143
|
+
listener: {
|
|
144
|
+
onVideoEnd: () => {
|
|
145
|
+
// Dismiss the bottom sheet modal when the video ends to avoid audio breaks and app freeze
|
|
146
|
+
if (modalBottomSheetState.visible) {
|
|
147
|
+
dismissBottomSheetModal();
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
return () => unsubscribe?.();
|
|
154
|
+
}, [player, modalBottomSheetState.visible]);
|
|
155
|
+
|
|
143
156
|
const [playbackSpeed, setPlaybackSpeed] =
|
|
144
157
|
useState<PlaybackSpeed>(DEFAULT_SPEED);
|
|
145
158
|
|
|
146
|
-
const [sleepTimerState, setSleepTimerState] = useState<SleepTimerState>(
|
|
147
|
-
new SleepTimerState(SLEEP_TIMER_OFF, 0)
|
|
148
|
-
);
|
|
149
|
-
|
|
150
159
|
const [defaultDimensions, setDefaultDimensions] =
|
|
151
160
|
React.useState<Dimensions>(undefined);
|
|
152
161
|
|
|
@@ -169,17 +178,13 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
169
178
|
};
|
|
170
179
|
|
|
171
180
|
useEffect(() => {
|
|
172
|
-
const sleepSubscription =
|
|
173
|
-
sleepTimerManager?.sleepTimerState$.subscribe(setSleepTimerState);
|
|
174
|
-
|
|
175
181
|
const speedSubscription =
|
|
176
182
|
speedManager?.playbackSpeed$.subscribe(setPlaybackSpeed);
|
|
177
183
|
|
|
178
184
|
return () => {
|
|
179
|
-
sleepSubscription?.unsubscribe();
|
|
180
185
|
speedSubscription?.unsubscribe();
|
|
181
186
|
};
|
|
182
|
-
}, [
|
|
187
|
+
}, [speedManager]);
|
|
183
188
|
|
|
184
189
|
useEffect(() => {
|
|
185
190
|
if (!playerState.isReadyToPlay) {
|
|
@@ -187,8 +192,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
187
192
|
}
|
|
188
193
|
|
|
189
194
|
void speedManager?.loadSpeed();
|
|
190
|
-
|
|
191
|
-
}, [playerState.isReadyToPlay, speedManager, sleepTimerManager]);
|
|
195
|
+
}, [playerState.isReadyToPlay, speedManager]);
|
|
192
196
|
|
|
193
197
|
const getValue = (key: string, stylesObj: {}) =>
|
|
194
198
|
R.propOr(null, key, stylesObj);
|
|
@@ -236,13 +240,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
236
240
|
[speedManager]
|
|
237
241
|
);
|
|
238
242
|
|
|
239
|
-
const onSleepSelect = React.useCallback(
|
|
240
|
-
async (item) => {
|
|
241
|
-
await sleepTimerManager?.setSleepTimer(item);
|
|
242
|
-
},
|
|
243
|
-
[sleepTimerManager]
|
|
244
|
-
);
|
|
245
|
-
|
|
246
243
|
const onSpeedButtonPress = React.useCallback(() => {
|
|
247
244
|
openBottomSheetModal({
|
|
248
245
|
modalBottomSheetContentProps: {
|
|
@@ -267,42 +264,6 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
267
264
|
});
|
|
268
265
|
}, [playbackSpeed, onSpeedSelect, configuration["playback_speed_title"]]);
|
|
269
266
|
|
|
270
|
-
const onSleepButtonPress = React.useCallback(() => {
|
|
271
|
-
openBottomSheetModal({
|
|
272
|
-
modalBottomSheetContentProps: {
|
|
273
|
-
items: getSleepTimerOptions(configuration),
|
|
274
|
-
current_selection: sleepTimerState.timer,
|
|
275
|
-
onPress: onSleepSelect,
|
|
276
|
-
title: configuration["playback_sleep_title"],
|
|
277
|
-
itemProps: getBottomSheetModalItemProps,
|
|
278
|
-
iconProps: getBottomSheetModalIconProps,
|
|
279
|
-
labelProps: getBottomSheetModalLabelProps,
|
|
280
|
-
getSelectedItemIcon: getBottomSheetModalSelectedItemIcon,
|
|
281
|
-
iconPlacement: "right",
|
|
282
|
-
},
|
|
283
|
-
options: {
|
|
284
|
-
supportedOrientations: [
|
|
285
|
-
"portrait",
|
|
286
|
-
"landscape",
|
|
287
|
-
"portrait-upside-down",
|
|
288
|
-
],
|
|
289
|
-
},
|
|
290
|
-
});
|
|
291
|
-
}, [
|
|
292
|
-
sleepTimerState.timer,
|
|
293
|
-
configuration["playback_sleep_title"],
|
|
294
|
-
configuration["playback_sleep_off_label"],
|
|
295
|
-
onSleepSelect,
|
|
296
|
-
]);
|
|
297
|
-
|
|
298
|
-
// This method does not actually cancel the sleep timer
|
|
299
|
-
// (and should not to avoid race condition),
|
|
300
|
-
// it just performs the cleanup when timer expires
|
|
301
|
-
// TODO: rename it in code above
|
|
302
|
-
const cancelSleepTimer = React.useCallback(() => {
|
|
303
|
-
sleepTimerManager?.onTimerExpired();
|
|
304
|
-
}, [sleepTimerManager]);
|
|
305
|
-
|
|
306
267
|
const onCloseVideoModal = React.useCallback(() => {
|
|
307
268
|
playerManager.close();
|
|
308
269
|
}, [playerManager]);
|
|
@@ -342,15 +303,7 @@ export const AudioPlayerWrapper: React.FC<Props> = (props: Props) => {
|
|
|
342
303
|
onPlayerSeek={onPlayerSeek}
|
|
343
304
|
onSkipStart={onSkipStart}
|
|
344
305
|
onSpeedButtonPress={onSpeedButtonPress}
|
|
345
|
-
onSleepButtonPress={onSleepButtonPress}
|
|
346
306
|
playbackSpeedName={formatSpeed(playbackSpeed.value)}
|
|
347
|
-
playbackSleepName={
|
|
348
|
-
sleepTimerState.timer.value === 0
|
|
349
|
-
? "sleep_timer"
|
|
350
|
-
: "sleep_timer_active"
|
|
351
|
-
}
|
|
352
|
-
sleepTimerDate={sleepTimerState.timerDate}
|
|
353
|
-
cancelSleepTimer={cancelSleepTimer}
|
|
354
307
|
onSkipLive={onSkipLive}
|
|
355
308
|
onCloseVideoModal={onCloseVideoModal}
|
|
356
309
|
maximiseVideoModal={maximiseVideoModal}
|
|
@@ -2,7 +2,10 @@ import * as React from "react";
|
|
|
2
2
|
import { StyleSheet } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { dayjs } from "@applicaster/zapp-react-native-utils/dateUtils";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
useIsTablet,
|
|
7
|
+
useZStore,
|
|
8
|
+
} from "@applicaster/zapp-react-native-utils/reactHooks";
|
|
6
9
|
import {
|
|
7
10
|
Controls as MobileTransportControls,
|
|
8
11
|
ProgressBar,
|
|
@@ -27,6 +30,7 @@ import {
|
|
|
27
30
|
sleepButton,
|
|
28
31
|
speedButton,
|
|
29
32
|
} from "./utils";
|
|
33
|
+
import { useSleepTimerModal } from "../../useSleepTimerModal";
|
|
30
34
|
|
|
31
35
|
const styles = StyleSheet.create({
|
|
32
36
|
flex: {
|
|
@@ -64,11 +68,8 @@ type Props = {
|
|
|
64
68
|
value: GetValue;
|
|
65
69
|
title: string | number;
|
|
66
70
|
summary: string | number;
|
|
67
|
-
sleepTimerDate: number;
|
|
68
|
-
cancelSleepTimer: Callback;
|
|
69
71
|
|
|
70
72
|
playbackSpeedName: string;
|
|
71
|
-
playbackSleepName: string;
|
|
72
73
|
|
|
73
74
|
onPlaybackButtonPress: Callback;
|
|
74
75
|
onRewindButtonPress: Callback;
|
|
@@ -77,7 +78,6 @@ type Props = {
|
|
|
77
78
|
onSkipStart: Callback;
|
|
78
79
|
onSkipLive: Callback;
|
|
79
80
|
onSpeedButtonPress: Callback;
|
|
80
|
-
onSleepButtonPress: Callback;
|
|
81
81
|
|
|
82
82
|
maxWidth?: number;
|
|
83
83
|
|
|
@@ -92,11 +92,8 @@ export const Controls = (props: Props) => {
|
|
|
92
92
|
value,
|
|
93
93
|
title,
|
|
94
94
|
summary,
|
|
95
|
-
sleepTimerDate,
|
|
96
|
-
cancelSleepTimer,
|
|
97
95
|
|
|
98
96
|
playbackSpeedName,
|
|
99
|
-
playbackSleepName,
|
|
100
97
|
|
|
101
98
|
onPlaybackButtonPress,
|
|
102
99
|
onRewindButtonPress,
|
|
@@ -105,12 +102,21 @@ export const Controls = (props: Props) => {
|
|
|
105
102
|
onSkipStart,
|
|
106
103
|
onSkipLive,
|
|
107
104
|
onSpeedButtonPress,
|
|
108
|
-
onSleepButtonPress,
|
|
109
105
|
maxWidth = 320,
|
|
110
106
|
|
|
111
107
|
docked,
|
|
112
108
|
} = props;
|
|
113
109
|
|
|
110
|
+
const configuration = useZStore("playerConfiguration");
|
|
111
|
+
|
|
112
|
+
const { sleepTimerState, onSleepButtonPress } = useSleepTimerModal(
|
|
113
|
+
playerManager.getActivePlayer(),
|
|
114
|
+
configuration
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const playbackSleepName =
|
|
118
|
+
sleepTimerState.timer.value === 0 ? "sleep_timer" : "sleep_timer_active";
|
|
119
|
+
|
|
114
120
|
const isTablet = useIsTablet();
|
|
115
121
|
const controller = playerManager.getActivePlayer();
|
|
116
122
|
let showFullControls = !controller?.isAd();
|
|
@@ -124,45 +130,6 @@ export const Controls = (props: Props) => {
|
|
|
124
130
|
showFullControls = !!(controller?.hasSeekableDuration?.() && seekEnabled);
|
|
125
131
|
}
|
|
126
132
|
|
|
127
|
-
const [timeLeft, setTimeLeft] = React.useState(
|
|
128
|
-
sleepTimerDate !== 0 ? sleepTimerDate - Date.now() : 0
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
const showCounter = React.useMemo(() => sleepTimerDate > 0, [sleepTimerDate]);
|
|
132
|
-
|
|
133
|
-
const countDownOptions = React.useMemo(() => {
|
|
134
|
-
return {
|
|
135
|
-
showCounter: showCounter && timeLeft >= 0,
|
|
136
|
-
timeLeft,
|
|
137
|
-
};
|
|
138
|
-
}, [showCounter, timeLeft]);
|
|
139
|
-
|
|
140
|
-
React.useEffect(() => {
|
|
141
|
-
if (showCounter && sleepTimerDate !== 0) {
|
|
142
|
-
setTimeLeft(sleepTimerDate - Date.now());
|
|
143
|
-
|
|
144
|
-
const intervalId = setInterval(() => {
|
|
145
|
-
setTimeLeft(() => {
|
|
146
|
-
const newTimeLeft = sleepTimerDate - Date.now();
|
|
147
|
-
|
|
148
|
-
if (newTimeLeft <= 0) {
|
|
149
|
-
clearInterval(intervalId);
|
|
150
|
-
|
|
151
|
-
cancelSleepTimer();
|
|
152
|
-
|
|
153
|
-
return 0;
|
|
154
|
-
} else {
|
|
155
|
-
return newTimeLeft;
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
}, 1000);
|
|
159
|
-
|
|
160
|
-
return () => clearInterval(intervalId);
|
|
161
|
-
} else {
|
|
162
|
-
setTimeLeft(0);
|
|
163
|
-
}
|
|
164
|
-
}, [sleepTimerDate, showCounter, cancelSleepTimer]);
|
|
165
|
-
|
|
166
133
|
const startTime = entry.extensions?.live?.start_time;
|
|
167
134
|
const endTime = entry.extensions?.live?.end_time;
|
|
168
135
|
|
|
@@ -295,7 +262,6 @@ export const Controls = (props: Props) => {
|
|
|
295
262
|
isDateBasedLiveContent={isDateBasedLiveContent}
|
|
296
263
|
onSkipLive={onSkipLive}
|
|
297
264
|
progressBarStyles={styles.progressBar}
|
|
298
|
-
countDownOptions={countDownOptions}
|
|
299
265
|
thumbStyles={styles.progressBarThumbStyles}
|
|
300
266
|
thumbStylesPressed={styles.progressBarThumbStyles_pressed}
|
|
301
267
|
trackStyles={styles.progressBarTrackStyles}
|
|
@@ -99,7 +99,7 @@ export const skipToLiveButton = (props: ButtonsProps): ControlsButton =>
|
|
|
99
99
|
skipButtonByName({ ...props, name: "skip_live" });
|
|
100
100
|
|
|
101
101
|
export const speedButton = (props: ButtonsProps): ControlsButton =>
|
|
102
|
-
speedButtonByName(
|
|
102
|
+
speedButtonByName(props);
|
|
103
103
|
|
|
104
104
|
export const sleepButton = (props: ButtonsProps): ControlsButton =>
|
|
105
|
-
sleepButtonByName(
|
|
105
|
+
sleepButtonByName(props);
|
|
@@ -24,6 +24,10 @@ import {
|
|
|
24
24
|
useModalAnimationContext,
|
|
25
25
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
26
26
|
import { toNumberWithDefault } from "@applicaster/zapp-react-native-utils/numberUtils";
|
|
27
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
28
|
+
import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
|
|
29
|
+
|
|
30
|
+
const bottomTabBarHeight = getTabBarHeight();
|
|
27
31
|
|
|
28
32
|
type Props = {
|
|
29
33
|
entry: ZappEntry;
|
|
@@ -88,10 +92,6 @@ const styles = StyleSheet.create({
|
|
|
88
92
|
},
|
|
89
93
|
});
|
|
90
94
|
|
|
91
|
-
const backgroundColorStyle = (value: GetValue): ViewStyle => ({
|
|
92
|
-
backgroundColor: value("docked_player_background_color"),
|
|
93
|
-
});
|
|
94
|
-
|
|
95
95
|
const playerDimensionsStyle = (
|
|
96
96
|
minimisedHeight: number,
|
|
97
97
|
addPadding: boolean
|
|
@@ -208,6 +208,10 @@ export const DockedControls = (props: Props) => {
|
|
|
208
208
|
[]
|
|
209
209
|
);
|
|
210
210
|
|
|
211
|
+
const dockedBackgroundColor = value("docked_player_background_color");
|
|
212
|
+
|
|
213
|
+
const insets = useSafeAreaInsets();
|
|
214
|
+
|
|
211
215
|
if (!layoutState.docked && !startComponentsAnimation) return null;
|
|
212
216
|
|
|
213
217
|
return (
|
|
@@ -219,7 +223,9 @@ export const DockedControls = (props: Props) => {
|
|
|
219
223
|
isActiveGesture || layoutState.docked,
|
|
220
224
|
progressBarHeight
|
|
221
225
|
),
|
|
222
|
-
{
|
|
226
|
+
{
|
|
227
|
+
height: minimisedHeight + bottomTabBarHeight + insets.bottom,
|
|
228
|
+
},
|
|
223
229
|
]}
|
|
224
230
|
>
|
|
225
231
|
{!playerState.isLive &&
|
|
@@ -261,7 +267,12 @@ export const DockedControls = (props: Props) => {
|
|
|
261
267
|
)}
|
|
262
268
|
/>
|
|
263
269
|
)}
|
|
264
|
-
<View
|
|
270
|
+
<View
|
|
271
|
+
style={[
|
|
272
|
+
styles.contentInfo,
|
|
273
|
+
{ backgroundColor: dockedBackgroundColor },
|
|
274
|
+
]}
|
|
275
|
+
>
|
|
265
276
|
<ContentInfo
|
|
266
277
|
content={{ ...entry, title, summary }}
|
|
267
278
|
value={value}
|
|
@@ -275,7 +286,7 @@ export const DockedControls = (props: Props) => {
|
|
|
275
286
|
isTablet
|
|
276
287
|
? styles.controlsContainerForTablet
|
|
277
288
|
: styles.controlsContainerForMobile,
|
|
278
|
-
|
|
289
|
+
{ backgroundColor: dockedBackgroundColor },
|
|
279
290
|
]}
|
|
280
291
|
>
|
|
281
292
|
<Controls
|
|
@@ -297,6 +308,12 @@ export const DockedControls = (props: Props) => {
|
|
|
297
308
|
/>
|
|
298
309
|
</View>
|
|
299
310
|
</View>
|
|
311
|
+
<View
|
|
312
|
+
style={{
|
|
313
|
+
height: insets.bottom + bottomTabBarHeight,
|
|
314
|
+
backgroundColor: dockedBackgroundColor,
|
|
315
|
+
}}
|
|
316
|
+
/>
|
|
300
317
|
</AnimationComponent>
|
|
301
318
|
);
|
|
302
319
|
};
|
|
@@ -77,15 +77,11 @@ export function MobileLayout({
|
|
|
77
77
|
onSkipStart,
|
|
78
78
|
onSkipLive,
|
|
79
79
|
onSpeedButtonPress,
|
|
80
|
-
onSleepButtonPress,
|
|
81
80
|
onCloseVideoModal,
|
|
82
81
|
playbackSpeedName,
|
|
83
|
-
playbackSleepName,
|
|
84
82
|
configuration,
|
|
85
83
|
dimensions,
|
|
86
84
|
playNextData,
|
|
87
|
-
cancelSleepTimer,
|
|
88
|
-
sleepTimerDate,
|
|
89
85
|
title,
|
|
90
86
|
summary,
|
|
91
87
|
}: Props) {
|
|
@@ -196,10 +192,7 @@ export function MobileLayout({
|
|
|
196
192
|
value={value}
|
|
197
193
|
title={title}
|
|
198
194
|
summary={summary}
|
|
199
|
-
sleepTimerDate={sleepTimerDate}
|
|
200
|
-
cancelSleepTimer={cancelSleepTimer}
|
|
201
195
|
playbackSpeedName={playbackSpeedName}
|
|
202
|
-
playbackSleepName={playbackSleepName}
|
|
203
196
|
onPlaybackButtonPress={onPlaybackButtonPress}
|
|
204
197
|
onRewindButtonPress={onRewindButtonPress}
|
|
205
198
|
onForwardButtonPress={onForwardButtonPress}
|
|
@@ -207,7 +200,6 @@ export function MobileLayout({
|
|
|
207
200
|
onSkipStart={onSkipStart}
|
|
208
201
|
onSkipLive={onSkipLive}
|
|
209
202
|
onSpeedButtonPress={onSpeedButtonPress}
|
|
210
|
-
onSleepButtonPress={onSleepButtonPress}
|
|
211
203
|
docked={docked}
|
|
212
204
|
/>
|
|
213
205
|
</View>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { PropsWithChildren } from "react";
|
|
2
|
-
import { Image, Animated, StyleSheet,
|
|
2
|
+
import { Image, Animated, StyleSheet, ImageStyle } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
5
5
|
import {
|
|
@@ -8,31 +8,26 @@ import {
|
|
|
8
8
|
DURATION_TO_MINIMIZE,
|
|
9
9
|
DURATION_TO_MAXIMIZE,
|
|
10
10
|
} from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
|
|
11
|
+
import { PlayerAnimationStateT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/ModalAnimationContext";
|
|
12
|
+
|
|
13
|
+
import { useChangePlayerState } from "./hooks";
|
|
11
14
|
|
|
12
15
|
const styles = StyleSheet.create({
|
|
13
16
|
container: {
|
|
14
17
|
// we have to specify flex:0 and dimensions to make animation work
|
|
15
18
|
flex: 0,
|
|
16
19
|
aspectRatio: 1,
|
|
17
|
-
overflow: "hidden",
|
|
18
20
|
},
|
|
19
21
|
});
|
|
20
22
|
|
|
21
23
|
type Props = PropsWithChildren<{
|
|
22
24
|
entry: ZappEntry;
|
|
23
|
-
style?:
|
|
24
|
-
imageStyle?: { [K: string]: any };
|
|
25
|
-
wrapperViewStyle?: ViewStyle;
|
|
25
|
+
style?: ImageStyle | ImageStyle[];
|
|
26
26
|
imageWidth: number;
|
|
27
|
+
docked: boolean;
|
|
27
28
|
}>;
|
|
28
29
|
|
|
29
|
-
export const AnimatedImage = ({
|
|
30
|
-
entry,
|
|
31
|
-
style,
|
|
32
|
-
imageStyle,
|
|
33
|
-
wrapperViewStyle,
|
|
34
|
-
imageWidth,
|
|
35
|
-
}: Props) => {
|
|
30
|
+
export const AnimatedImage = ({ entry, style, imageWidth, docked }: Props) => {
|
|
36
31
|
const heightAnim = React.useRef(new Animated.Value(imageWidth)).current;
|
|
37
32
|
|
|
38
33
|
const source = React.useMemo(
|
|
@@ -40,27 +35,40 @@ export const AnimatedImage = ({
|
|
|
40
35
|
[entry]
|
|
41
36
|
);
|
|
42
37
|
|
|
43
|
-
const {
|
|
38
|
+
const { minimisedHeight } = useModalAnimationContext();
|
|
39
|
+
|
|
40
|
+
const changePlayerState$ = useChangePlayerState({ docked });
|
|
44
41
|
|
|
45
42
|
React.useEffect(() => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
const subscription = changePlayerState$.subscribe({
|
|
44
|
+
next: (nextPlayerState: PlayerAnimationStateT) => {
|
|
45
|
+
if (nextPlayerState === PlayerAnimationStateEnum.minimize) {
|
|
46
|
+
Animated.timing(heightAnim, {
|
|
47
|
+
toValue: minimisedHeight,
|
|
48
|
+
duration: DURATION_TO_MINIMIZE,
|
|
49
|
+
useNativeDriver: false, // width/height can't use native driver
|
|
50
|
+
}).start();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (nextPlayerState === PlayerAnimationStateEnum.maximize) {
|
|
54
|
+
Animated.timing(heightAnim, {
|
|
55
|
+
toValue: imageWidth,
|
|
56
|
+
duration: DURATION_TO_MAXIMIZE,
|
|
57
|
+
useNativeDriver: false, // width/height can't use native driver
|
|
58
|
+
}).start();
|
|
59
|
+
}
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
if (nextPlayerState === PlayerAnimationStateEnum.appear_as_docked) {
|
|
62
|
+
// minimize image immediatly
|
|
63
|
+
heightAnim.setValue(minimisedHeight);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
});
|
|
55
67
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
useNativeDriver: false, // width/height can't use native driver
|
|
61
|
-
}).start();
|
|
62
|
-
}
|
|
63
|
-
}, [playerAnimationState, imageWidth]);
|
|
68
|
+
return () => {
|
|
69
|
+
subscription.unsubscribe();
|
|
70
|
+
};
|
|
71
|
+
}, [changePlayerState$, minimisedHeight, imageWidth]);
|
|
64
72
|
|
|
65
73
|
if (!source) return null;
|
|
66
74
|
|
|
@@ -68,16 +76,12 @@ export const AnimatedImage = ({
|
|
|
68
76
|
<Animated.View
|
|
69
77
|
style={[
|
|
70
78
|
styles.container,
|
|
71
|
-
wrapperViewStyle,
|
|
72
|
-
imageStyle,
|
|
73
79
|
{
|
|
74
80
|
width: heightAnim,
|
|
75
81
|
},
|
|
76
82
|
]}
|
|
77
83
|
>
|
|
78
|
-
<Image resizeMode="cover" style={style} source={source}
|
|
79
|
-
{null}
|
|
80
|
-
</Image>
|
|
84
|
+
<Image resizeMode="cover" style={style} source={source} />
|
|
81
85
|
</Animated.View>
|
|
82
86
|
);
|
|
83
87
|
};
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { Image } from "react-native";
|
|
2
|
+
import { Image, ImageStyle } from "react-native";
|
|
3
3
|
|
|
4
4
|
import { imageSrcFromMediaItem } from "@applicaster/zapp-react-native-utils/configurationUtils";
|
|
5
5
|
|
|
6
6
|
type Props = {
|
|
7
7
|
entry: ZappEntry;
|
|
8
|
-
style?:
|
|
9
|
-
imageStyle?: { [K: string]: any };
|
|
8
|
+
style?: ImageStyle;
|
|
10
9
|
};
|
|
11
10
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
export const FlexImage = ({ entry, imageStyle }: Props) => {
|
|
11
|
+
export const FlexImage = ({ entry, style }: Props) => {
|
|
15
12
|
const source = React.useMemo(
|
|
16
13
|
() => ({ uri: imageSrcFromMediaItem(entry, undefined) }),
|
|
17
14
|
[entry]
|
|
@@ -19,7 +16,5 @@ export const FlexImage = ({ entry, imageStyle }: Props) => {
|
|
|
19
16
|
|
|
20
17
|
if (!source) return null;
|
|
21
18
|
|
|
22
|
-
return
|
|
23
|
-
<Image resizeMode="cover" style={[style, imageStyle]} source={source} />
|
|
24
|
-
);
|
|
19
|
+
return <Image resizeMode="cover" style={style} source={source} />;
|
|
25
20
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useChangePlayerState } from "./useChangePlayerState";
|