@applicaster/quick-brick-player 15.0.0-rc.4 → 15.0.0-rc.40

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.
Files changed (30) hide show
  1. package/package.json +6 -6
  2. package/src/Player/AudioLayer/AudioPlayerWrapper.tsx +20 -8
  3. package/src/Player/AudioLayer/Layout/DockedControls/index.tsx +71 -63
  4. package/src/Player/AudioLayer/Layout/MobileLayout.tsx +1 -6
  5. package/src/Player/AudioLayer/Layout/PlayerImage/index.tsx +27 -25
  6. package/src/Player/AudioLayer/Layout/PlayerImage/styles.ts +6 -1
  7. package/src/Player/AudioLayer/Layout/TabletLandscapeLayout.tsx +5 -8
  8. package/src/Player/AudioLayer/Layout/TabletPortraitLayout.tsx +1 -6
  9. package/src/Player/AudioLayer/utils.ts +1 -27
  10. package/src/Player/PlayerModal/PlayerModal.tsx +16 -15
  11. package/src/Player/PlayerModal/VideoPlayerModal.tsx +138 -120
  12. package/src/Player/PlayerModal/consts/index.ts +2 -19
  13. package/src/Player/PlayerModal/hooks/index.ts +117 -141
  14. package/src/Player/PlayerModal/styles.ts +5 -0
  15. package/src/Player/PlayerModal/utils/index.ts +111 -0
  16. package/src/Player/PlayerView/types.ts +1 -2
  17. package/src/Player/hooks/progressStates/__tests__/utils.test.ts +23 -0
  18. package/src/Player/hooks/progressStates/useLiveProgressState.tsx +78 -0
  19. package/src/Player/hooks/progressStates/useProgressState.tsx +30 -0
  20. package/src/Player/hooks/progressStates/useVodProgressState.tsx +115 -0
  21. package/src/Player/hooks/progressStates/utils.ts +33 -0
  22. package/src/Player/index.tsx +559 -357
  23. package/src/utils/dimensions.ts +29 -0
  24. package/src/utils/index.ts +12 -0
  25. package/src/utils/logger.ts +6 -0
  26. package/src/utils/playerHelpers.ts +11 -0
  27. package/src/utils/playerStyles.ts +50 -0
  28. package/src/Player/AudioLayer/Layout/PlayerImage/AnimatedImage.tsx +0 -82
  29. package/src/Player/AudioLayer/Layout/PlayerImage/hooks/index.ts +0 -1
  30. package/src/Player/AudioLayer/Layout/PlayerImage/hooks/useChangePlayerState.ts +0 -99
@@ -1,153 +1,132 @@
1
1
  import { useCallback, useEffect, useMemo, useRef } from "react";
2
- import { useSafeAreaInsets } from "react-native-safe-area-context";
2
+
3
3
  import { State } from "react-native-gesture-handler";
4
- import { Animated } from "react-native";
5
4
 
6
5
  import { VideoModalMode } from "@applicaster/zapp-react-native-ui-components/Components/PlayerContainer/PlayerContainer";
7
- import { useConfiguration } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
8
- import { getTabBarHeight } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/getTabBarHeight";
6
+ import { useAnimationStateStore } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/utils";
9
7
  import { useNavigation } from "@applicaster/zapp-react-native-utils/reactHooks/navigation/useNavigation";
10
- import { isMenuVisible } from "@applicaster/zapp-react-native-ui-components/Components/Screen/navigationHandler";
11
8
  import {
12
9
  ANIMATION_DURATION,
13
10
  DRAG_TO_COLLAPSE,
14
11
  DRAG_TO_EXPAND,
15
- SCREEN_HEIGHT,
16
12
  } from "../consts";
17
- import { PROGRESS_BAR_HEIGHT } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation/utils";
18
- import { usePlugins } from "@applicaster/zapp-react-native-redux";
19
-
20
- const bottomTabBarHeight = getTabBarHeight();
13
+ import { Animated } from "react-native";
14
+ import { useModalAnimationContext } from "@applicaster/zapp-react-native-ui-components/Components/VideoModal/ModalAnimation";
21
15
 
22
- export const useVideoModalState = (
23
- translateYRef: React.MutableRefObject<Animated.Value>
24
- ) => {
25
- const { minimised_height: minimisedHeight } = useConfiguration();
16
+ const getAnimatedValue = (animatedValue: Animated.Value): number => {
17
+ return (animatedValue as any).__getValue() as number;
18
+ };
26
19
 
20
+ export const useVideoModalState = () => {
27
21
  const {
28
- maximiseVideoModal,
29
- minimiseVideoModal,
30
- videoModalState,
31
- currentRoute,
32
- screenData,
33
- } = useNavigation();
34
-
35
- const plugins = usePlugins();
36
-
37
- const menuVisible = isMenuVisible(currentRoute, screenData, plugins);
38
-
39
- const collapsed = videoModalState.mode === VideoModalMode.MINIMIZED;
40
-
41
- const { bottom } = useSafeAreaInsets();
42
-
43
- const initialBottomOffset = useRef(bottom).current;
44
-
45
- const collapsedHeight =
46
- minimisedHeight +
47
- initialBottomOffset +
48
- (menuVisible ? bottomTabBarHeight : 0) +
49
- PROGRESS_BAR_HEIGHT;
50
-
51
- const translateY = translateYRef.current;
52
-
53
- const handleExpand = useCallback(
54
- (toValue: number) => {
55
- return Animated.timing(translateYRef.current, {
22
+ yTranslate,
23
+ offset,
24
+ heightAboveMinimised,
25
+ gestureTranslationRef,
26
+ offsetAnimatedValueRef,
27
+ } = useModalAnimationContext();
28
+
29
+ const modalAnimatedValue = offsetAnimatedValueRef.current;
30
+ const gestureTranslation = gestureTranslationRef.current;
31
+
32
+ const updateModalTranslation = useCallback(
33
+ (toValue: number, duration: number = ANIMATION_DURATION) =>
34
+ Animated.timing(modalAnimatedValue, {
56
35
  toValue,
57
- duration: ANIMATION_DURATION,
36
+ duration,
58
37
  useNativeDriver: true,
59
- });
60
- },
61
- [translateYRef]
38
+ }),
39
+ [modalAnimatedValue]
62
40
  );
63
41
 
64
- const handleCollapse = useCallback(
65
- (toValue: number) => {
66
- return Animated.timing(translateYRef.current, {
67
- toValue,
68
- duration: ANIMATION_DURATION,
69
- useNativeDriver: true,
70
- });
71
- },
72
- [translateYRef]
73
- );
42
+ const translateY = yTranslate.current;
74
43
 
75
- const offset = useRef(SCREEN_HEIGHT - collapsedHeight);
44
+ const { maximiseVideoModal, minimiseVideoModal, videoModalState } =
45
+ useNavigation();
76
46
 
77
- // Gesture handler for modal
78
- const onGestureEvent = useCallback(
79
- (event: any) => {
80
- if (event.nativeEvent.state === State.ACTIVE) {
81
- const y = event.nativeEvent.translationY;
82
- let newY = offset.current + y;
83
- if (newY < 0) newY = 0;
47
+ const videoModalMode = videoModalState.mode;
84
48
 
85
- if (newY > SCREEN_HEIGHT - collapsedHeight) {
86
- newY = SCREEN_HEIGHT - collapsedHeight;
87
- }
49
+ const prevModeStateRef = useRef(videoModalMode); // keep track of last non-PIP mode
50
+ const gestureStateRef = useRef<any>(State.UNDETERMINED); // keep track of gesture state
88
51
 
89
- translateY.setValue(newY);
90
- }
91
- },
92
- [collapsedHeight, translateY]
52
+ // Track last non-PIP mode
53
+ if (videoModalMode !== prevModeStateRef.current) {
54
+ if (["MAXIMIZED", "MINIMIZED"].includes(videoModalMode)) {
55
+ prevModeStateRef.current = videoModalMode;
56
+ }
57
+ }
58
+
59
+ const collapsed =
60
+ videoModalState.visible &&
61
+ ((prevModeStateRef.current === "MINIMIZED" &&
62
+ videoModalState.mode === "PIP") || // If STILL in PIP mode, check if last non-PIP mode was MINIMIZED
63
+ videoModalState.mode === VideoModalMode.MINIMIZED); // Or if currently in MINIMIZED mode
64
+
65
+ // Gesture handler for modal
66
+ const onGestureEvent = useMemo(
67
+ () =>
68
+ Animated.event([{ nativeEvent: { translationY: gestureTranslation } }], {
69
+ useNativeDriver: true,
70
+ }),
71
+ // eslint-disable-next-line react-hooks/exhaustive-deps
72
+ []
93
73
  );
94
74
 
95
75
  const onHandlerStateChange = useCallback(
96
76
  (event: any) => {
97
- if (event.nativeEvent.oldState === State.ACTIVE) {
98
- const { translationY } = event.nativeEvent;
99
- let newY = offset.current + translationY;
100
- if (newY < 0) newY = 0;
77
+ const { state: newState, oldState, translationY } = event.nativeEvent;
101
78
 
102
- if (newY > SCREEN_HEIGHT - collapsedHeight) {
103
- newY = SCREEN_HEIGHT - collapsedHeight;
104
- }
79
+ if (newState === State.ACTIVE || oldState === State.ACTIVE) {
80
+ useAnimationStateStore.setState({
81
+ isAnimationInProgress: newState === State.ACTIVE,
82
+ });
83
+ }
105
84
 
106
- const shouldCollapse =
107
- translationY > (SCREEN_HEIGHT - collapsedHeight) * DRAG_TO_COLLAPSE;
108
-
109
- const shouldExpand =
110
- translationY < -(SCREEN_HEIGHT - collapsedHeight) * DRAG_TO_EXPAND;
111
-
112
- if (!collapsed && shouldCollapse) {
113
- // Collapse
114
- Animated.timing(translateY, {
115
- toValue: SCREEN_HEIGHT - collapsedHeight,
116
- duration: ANIMATION_DURATION,
117
- useNativeDriver: true,
118
- }).start(() => {
119
- minimiseVideoModal();
120
- offset.current = SCREEN_HEIGHT - collapsedHeight;
121
- });
122
- } else if (collapsed && shouldExpand) {
123
- // Expand
124
- Animated.timing(translateY, {
125
- toValue: 0,
126
- duration: ANIMATION_DURATION,
127
- useNativeDriver: true,
128
- }).start(() => {
129
- maximiseVideoModal();
130
- offset.current = 0;
131
- translateY.setValue(0);
132
- });
133
- } else {
134
- // Snap back to current state
135
- Animated.spring(translateY, {
136
- toValue: collapsed ? SCREEN_HEIGHT - collapsedHeight : 0,
137
- useNativeDriver: true,
138
- }).start(() => {
139
- offset.current = collapsed ? SCREEN_HEIGHT - collapsedHeight : 0;
140
- translateY.setValue(offset.current);
141
- });
85
+ // Update gesture state tracking
86
+ gestureStateRef.current = newState;
87
+
88
+ if (translationY !== 0) {
89
+ if (newState === State.BEGAN) {
90
+ // clean up gesture translation
91
+ gestureTranslation.setValue(0);
92
+ } else if (
93
+ newState === State.END ||
94
+ newState === State.FAILED ||
95
+ newState === State.CANCELLED
96
+ ) {
97
+ const newY = getAnimatedValue(gestureTranslation);
98
+
99
+ // clean up gesture translation
100
+ gestureTranslation.setValue(0);
101
+
102
+ const v = getAnimatedValue(modalAnimatedValue);
103
+
104
+ // store current offset
105
+ modalAnimatedValue.setValue(v + newY);
106
+
107
+ const shouldCollapse = newY > offset.current * DRAG_TO_COLLAPSE;
108
+
109
+ const shouldExpand = newY < offset.current * DRAG_TO_EXPAND;
110
+
111
+ if (!collapsed && shouldCollapse) {
112
+ // Collapse
113
+ updateModalTranslation(offset.current).start(() => {
114
+ minimiseVideoModal();
115
+ });
116
+ } else if (collapsed && shouldExpand) {
117
+ // Expand
118
+ updateModalTranslation(0).start(() => {
119
+ maximiseVideoModal();
120
+ });
121
+ } else {
122
+ // Snap back to current state
123
+ updateModalTranslation(collapsed ? offset.current : 0).start();
124
+ }
142
125
  }
143
- } else if (event.nativeEvent.state === State.BEGAN) {
144
- // Gesture started, set offset
145
- translateY.stopAnimation((value: number) => {
146
- offset.current = value;
147
- });
148
126
  }
149
127
  },
150
- [collapsedHeight, translateY, collapsed, videoModalState]
128
+ // eslint-disable-next-line react-hooks/exhaustive-deps
129
+ [collapsed]
151
130
  );
152
131
 
153
132
  const gestureHandlerProps = useMemo(() => {
@@ -157,37 +136,34 @@ export const useVideoModalState = (
157
136
  };
158
137
  }, [onGestureEvent, onHandlerStateChange]);
159
138
 
139
+ // Track video modal state changes & calling updateAnimatedPosition
160
140
  useEffect(() => {
161
- if (videoModalState.mode === VideoModalMode.MAXIMIZED) {
162
- handleExpand(0).start(() => {
163
- maximiseVideoModal();
164
- offset.current = 0;
165
- translateY.setValue(0);
166
- });
167
- } else if (videoModalState.mode === VideoModalMode.MINIMIZED) {
168
- handleCollapse(SCREEN_HEIGHT - collapsedHeight).start(() => {
169
- minimiseVideoModal();
170
- offset.current = SCREEN_HEIGHT - collapsedHeight;
171
- translateY.setValue(SCREEN_HEIGHT - collapsedHeight);
172
- });
141
+ if (videoModalState.visible) {
142
+ const mode =
143
+ videoModalMode === "PIP" ? prevModeStateRef.current : videoModalMode;
144
+
145
+ // Prevent changes during active gesture states to avoid interference
146
+ if ([State.ACTIVE].includes(gestureStateRef.current)) {
147
+ return;
148
+ }
149
+
150
+ if (mode === VideoModalMode.MAXIMIZED) {
151
+ updateModalTranslation(0).start();
152
+ } else if (mode === VideoModalMode.MINIMIZED) {
153
+ updateModalTranslation(heightAboveMinimised).start();
154
+ }
173
155
  }
174
- }, [videoModalState.visible, videoModalState.mode, collapsedHeight]);
156
+ // eslint-disable-next-line react-hooks/exhaustive-deps
157
+ }, [videoModalState.visible, videoModalState.mode, heightAboveMinimised]);
175
158
 
176
159
  return useMemo(
177
160
  () => ({
178
161
  collapsed,
179
- collapsedHeight,
180
162
  offset,
181
163
  gestureHandlerProps,
182
164
  translateY,
183
165
  expand: maximiseVideoModal,
184
166
  }),
185
- [
186
- collapsed,
187
- collapsedHeight,
188
- gestureHandlerProps,
189
- translateY,
190
- maximiseVideoModal,
191
- ]
167
+ [collapsed, offset, gestureHandlerProps, translateY, maximiseVideoModal]
192
168
  );
193
169
  };
@@ -63,6 +63,7 @@ export const useStyles = ({ height }: { height: number }) => {
63
63
  backgroundColor,
64
64
  elevation: 10,
65
65
  zIndex: 100,
66
+ height: "100%",
66
67
  overflow: "hidden",
67
68
  },
68
69
  modalWrapper: {
@@ -75,6 +76,10 @@ export const useStyles = ({ height }: { height: number }) => {
75
76
  flex: 1,
76
77
  alignItems: "center",
77
78
  },
79
+ modalContentPiP: {
80
+ flex: 1,
81
+ alignItems: "flex-start",
82
+ },
78
83
  expandedContentContainer: {
79
84
  justifyContent: "flex-start",
80
85
  backgroundColor: BG_COLOR_DEFAULT_TRANSPARENT,
@@ -0,0 +1,111 @@
1
+ import { StyleSheet, Dimensions, ViewStyle } from "react-native";
2
+
3
+ import {
4
+ isAndroidPlatform,
5
+ isAndroidVersionAtLeast,
6
+ isTV,
7
+ } from "@applicaster/zapp-react-native-utils/reactUtils";
8
+ import { useIsTablet as getIsTablet } from "@applicaster/zapp-react-native-utils/reactHooks";
9
+
10
+ const SAFE_AREA_BREAKING_API_VERSION = 35;
11
+
12
+ export const isOldAndroidDevice =
13
+ isAndroidPlatform() &&
14
+ !isAndroidVersionAtLeast(SAFE_AREA_BREAKING_API_VERSION);
15
+
16
+ export const getWindowHeight = (
17
+ isTablet: boolean,
18
+ landscape: boolean
19
+ ): number => {
20
+ const windowDimensions = Dimensions.get("window");
21
+
22
+ if (isTablet && landscape) {
23
+ return windowDimensions.height;
24
+ }
25
+
26
+ if (windowDimensions.width > windowDimensions.height) {
27
+ return windowDimensions.width;
28
+ }
29
+
30
+ return windowDimensions.height;
31
+ };
32
+
33
+ export const getScreenHeight = (): number => {
34
+ const screenDimensions = Dimensions.get("screen");
35
+
36
+ return screenDimensions.height;
37
+ };
38
+
39
+ export const getWindowWidth = (
40
+ isTablet: boolean,
41
+ landscape: boolean
42
+ ): number => {
43
+ const windowDimensions = Dimensions.get("window");
44
+
45
+ if (isTablet && landscape) {
46
+ return windowDimensions.width;
47
+ }
48
+
49
+ if (windowDimensions.width > windowDimensions.height) {
50
+ return windowDimensions.height;
51
+ }
52
+
53
+ return windowDimensions.width;
54
+ };
55
+
56
+ const getIsTabletLandscape = (isTabletPortrait: boolean): boolean => {
57
+ return !isTV() && getIsTablet() && !isTabletPortrait;
58
+ };
59
+
60
+ export const getInsetsOffset = (
61
+ insets: { top: number; bottom: number },
62
+ isTabletPortrait: boolean
63
+ ): number => {
64
+ const isTabletLandscape = getIsTabletLandscape(isTabletPortrait);
65
+
66
+ return getIsTablet() && isTabletLandscape
67
+ ? isOldAndroidDevice
68
+ ? insets.top / 2
69
+ : 0
70
+ : insets.top / 2;
71
+ };
72
+
73
+ const orientationStyles = StyleSheet.create({
74
+ landscape: { flexDirection: "row" },
75
+ portrait: { flexDirection: "column" },
76
+ });
77
+
78
+ export const directionStyles = (isTabletPortrait: boolean): ViewStyle => {
79
+ const isTabletLandscape = getIsTabletLandscape(isTabletPortrait);
80
+
81
+ return isTabletLandscape
82
+ ? orientationStyles.landscape
83
+ : orientationStyles.portrait;
84
+ };
85
+
86
+ export const getScaledPos = (
87
+ height,
88
+ vidHeight,
89
+ minimisedHeight,
90
+ isTabletPortrait
91
+ ) => {
92
+ const isTabletLandscape = getIsTabletLandscape(isTabletPortrait);
93
+
94
+ const SCALE_FACTOR = minimisedHeight / vidHeight; // Scale factor for expanded content
95
+
96
+ return (
97
+ ((isTabletLandscape ? height : vidHeight) - vidHeight * SCALE_FACTOR) / 2
98
+ );
99
+ };
100
+
101
+ export const getExtraContentPadding = (insets: {
102
+ top: number;
103
+ bottom: number;
104
+ }): ViewStyle => {
105
+ const isTablet = getIsTablet(); // not a hook, just a utility function
106
+
107
+ return {
108
+ paddingTop: isTablet ? insets.top : 0,
109
+ paddingBottom: insets.bottom,
110
+ };
111
+ };
@@ -10,9 +10,8 @@ export interface PlayNextOverlayProps {
10
10
  }
11
11
 
12
12
  export interface PlayerComponentProps {
13
- ref: React.RefObject<any>;
13
+ ref: React.Ref<any>;
14
14
  listener: Record<string, any>;
15
- configuration: Record<string, any>;
16
15
  style: ViewStyle;
17
16
  }
18
17
 
@@ -0,0 +1,23 @@
1
+ import { calculateLiveProgressBarTime } from "../utils";
2
+
3
+ describe("Utils", () => {
4
+ describe("calculateLiveProgressBarTime", () => {
5
+ it("Should return 0", () => {
6
+ expect(calculateLiveProgressBarTime(68, 1)).toBe(0);
7
+
8
+ expect(calculateLiveProgressBarTime(68, 0)).toBe(0);
9
+
10
+ expect(calculateLiveProgressBarTime(68, -1)).toBe(0);
11
+
12
+ expect(calculateLiveProgressBarTime(68, -5)).toBe(0);
13
+ });
14
+
15
+ it("Should return equal duration", () => {
16
+ expect(calculateLiveProgressBarTime(68, -100)).toBe(-68);
17
+
18
+ expect(calculateLiveProgressBarTime(68, -68)).toBe(-68);
19
+
20
+ expect(calculateLiveProgressBarTime(68, -105)).toBe(-68);
21
+ });
22
+ });
23
+ });
@@ -0,0 +1,78 @@
1
+ import * as React from "react";
2
+
3
+ import { calculateLiveProgressBarTime, formatTimeDisplay } from "./utils";
4
+ import { ProgressState } from "./useProgressState";
5
+
6
+ // TODO: Must Add check RTL support
7
+ const getSliderValues = (seekableDuration: number, time: number) => {
8
+ const value = calculateLiveProgressBarTime(seekableDuration, time);
9
+
10
+ return {
11
+ minimumValue: -seekableDuration,
12
+ maximumValue: 0,
13
+ value: Math.min(0, value),
14
+ };
15
+ };
16
+
17
+ const prepareNewState = ({ seekableDuration, time }) => {
18
+ const sliderValues = getSliderValues(seekableDuration, time);
19
+
20
+ const getProgress = (
21
+ seekableDuration: number,
22
+ currentTime: number
23
+ ): number => {
24
+ return Math.round((currentTime / seekableDuration) * 100);
25
+ };
26
+
27
+ const getElapsedTime = (currentTime: number): string => {
28
+ return currentTime === 0
29
+ ? ""
30
+ : `-${formatTimeDisplay(Math.abs(currentTime))}`;
31
+ };
32
+
33
+ const getLiveOffsetPercent = (): number =>
34
+ (100 * (sliderValues.value - sliderValues.minimumValue)) /
35
+ (sliderValues.maximumValue - sliderValues.minimumValue);
36
+
37
+ return {
38
+ progress: getProgress(seekableDuration, sliderValues.value),
39
+ liveOffsetPercent: getLiveOffsetPercent(),
40
+ time: [getElapsedTime(sliderValues.value), null],
41
+ currentTime: sliderValues.value,
42
+ duration: Math.max(0, seekableDuration),
43
+ sliderValues,
44
+ };
45
+ };
46
+
47
+ // TODO: Add for `NOW` localization
48
+ export const useLiveProgressState = ({
49
+ playerState: { currentTime, seekableDuration },
50
+ }): [ProgressState, (seek: number) => void] => {
51
+ const stateRef = React.useRef<ProgressState>({
52
+ progress: 0,
53
+ liveOffsetPercent: 0,
54
+ time: ["--:--", "--:--"],
55
+ currentTime: 0,
56
+ duration: 0,
57
+ sliderValues: {
58
+ minimumValue: 0,
59
+ maximumValue: 0,
60
+ value: 0,
61
+ },
62
+ });
63
+
64
+ const updateState = React.useCallback(
65
+ (seekTime: number): void => {
66
+ if (seekTime == null || seekableDuration == null) {
67
+ return;
68
+ }
69
+
70
+ stateRef.current = prepareNewState({ seekableDuration, time: -seekTime });
71
+ },
72
+ [seekableDuration]
73
+ );
74
+
75
+ updateState(currentTime);
76
+
77
+ return [stateRef.current, updateState];
78
+ };
@@ -0,0 +1,30 @@
1
+ import { useLiveProgressState } from "./useLiveProgressState";
2
+ import { useVodProgressState } from "./useVodProgressState";
3
+
4
+ export type ProgressState = {
5
+ liveOffsetPercent?: number;
6
+ progress: number;
7
+ time: string[];
8
+ currentTime: number;
9
+ duration: number;
10
+ sliderValues: { minimumValue: number; maximumValue: number; value: number };
11
+ };
12
+
13
+ // TODO: Try refactor to remove code duplication
14
+ export const useProgressState = ({
15
+ playerState: { seekableDuration, duration, isLive },
16
+ remainingTimeDisplay = false,
17
+ currentTime,
18
+ }): [ProgressState, (seek) => void] => {
19
+ const liveData: [ProgressState, (seek: number) => void] =
20
+ useLiveProgressState({
21
+ playerState: { currentTime, seekableDuration },
22
+ });
23
+
24
+ const vodData: [ProgressState, (seek) => void] = useVodProgressState({
25
+ playerState: { currentTime, duration },
26
+ remainingTimeDisplay,
27
+ });
28
+
29
+ return isLive ? liveData : vodData;
30
+ };