diff --git a/src/components/VideoPlayer/VideoPlayerControls/ProgressBar/index.js b/src/components/VideoPlayer/VideoPlayerControls/ProgressBar/index.tsx similarity index 68% rename from src/components/VideoPlayer/VideoPlayerControls/ProgressBar/index.js rename to src/components/VideoPlayer/VideoPlayerControls/ProgressBar/index.tsx index c6eb1a179726..f9dd09db59f4 100644 --- a/src/components/VideoPlayer/VideoPlayerControls/ProgressBar/index.js +++ b/src/components/VideoPlayer/VideoPlayerControls/ProgressBar/index.tsx @@ -1,25 +1,27 @@ -import PropTypes from 'prop-types'; import React, {useEffect, useState} from 'react'; +import type {LayoutChangeEvent, ViewStyle} from 'react-native'; +import type {GestureStateChangeEvent, GestureUpdateEvent, PanGestureChangeEventPayload, PanGestureHandlerEventPayload} from 'react-native-gesture-handler'; import {Gesture, GestureDetector} from 'react-native-gesture-handler'; import Animated, {runOnJS, useAnimatedStyle, useSharedValue} from 'react-native-reanimated'; import {usePlaybackContext} from '@components/VideoPlayerContexts/PlaybackContext'; import useThemeStyles from '@hooks/useThemeStyles'; -const propTypes = { - duration: PropTypes.number.isRequired, +type ProgressBarProps = { + /** Total duration of a video. */ + duration: number; - position: PropTypes.number.isRequired, + /** Position of progress pointer on the bar. */ + position: number; - seekPosition: PropTypes.func.isRequired, + /** Function to seek to a specific position in the video. */ + seekPosition: (newPosition: number) => void; }; -const defaultProps = {}; - -function getProgress(currentPosition, maxPosition) { +function getProgress(currentPosition: number, maxPosition: number): number { return Math.min(Math.max((currentPosition / maxPosition) * 100, 0), 100); } -function ProgressBar({duration, position, seekPosition}) { +function ProgressBar({duration, position, seekPosition}: ProgressBarProps) { const styles = useThemeStyles(); const {pauseVideo, playVideo, checkVideoPlaying} = usePlaybackContext(); const [sliderWidth, setSliderWidth] = useState(1); @@ -27,18 +29,18 @@ function ProgressBar({duration, position, seekPosition}) { const progressWidth = useSharedValue(0); const wasVideoPlayingOnCheck = useSharedValue(false); - const onCheckVideoPlaying = (isPlaying) => { + const onCheckVideoPlaying = (isPlaying: boolean) => { wasVideoPlayingOnCheck.value = isPlaying; }; - const progressBarInteraction = (event) => { + const progressBarInteraction = (event: GestureUpdateEvent | GestureStateChangeEvent) => { const progress = getProgress(event.x, sliderWidth); progressWidth.value = progress; runOnJS(seekPosition)((progress * duration) / 100); }; - const onSliderLayout = (e) => { - setSliderWidth(e.nativeEvent.layout.width); + const onSliderLayout = (event: LayoutChangeEvent) => { + setSliderWidth(event.nativeEvent.layout.width); }; const pan = Gesture.Pan() @@ -66,7 +68,7 @@ function ProgressBar({duration, position, seekPosition}) { progressWidth.value = getProgress(position, duration); }, [duration, isSliderPressed, position, progressWidth]); - const progressBarStyle = useAnimatedStyle(() => ({width: `${progressWidth.value}%`})); + const progressBarStyle: ViewStyle = useAnimatedStyle(() => ({width: `${progressWidth.value}%`})); return ( @@ -85,8 +87,6 @@ function ProgressBar({duration, position, seekPosition}) { ); } -ProgressBar.propTypes = propTypes; -ProgressBar.defaultProps = defaultProps; ProgressBar.displayName = 'ProgressBar'; export default ProgressBar; diff --git a/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js b/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.tsx similarity index 81% rename from src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js rename to src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.tsx index 45f47eb87c36..011391ed4c71 100644 --- a/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js +++ b/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.tsx @@ -1,6 +1,7 @@ -import PropTypes from 'prop-types'; import React, {memo, useCallback, useState} from 'react'; +import type {LayoutChangeEvent, StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; +import type {GestureStateChangeEvent, GestureUpdateEvent, PanGestureChangeEventPayload, PanGestureHandlerEventPayload} from 'react-native-gesture-handler'; import {Gesture, GestureDetector} from 'react-native-gesture-handler'; import Animated, {runOnJS, useAnimatedStyle, useDerivedValue} from 'react-native-reanimated'; import Hoverable from '@components/Hoverable'; @@ -10,18 +11,16 @@ import {useVolumeContext} from '@components/VideoPlayerContexts/VolumeContext'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as NumberUtils from '@libs/NumberUtils'; -import stylePropTypes from '@styles/stylePropTypes'; -const propTypes = { - style: stylePropTypes.isRequired, - small: PropTypes.bool, -}; +type VolumeButtonProps = { + /** Style for the volume button. */ + style?: StyleProp; -const defaultProps = { - small: false, + /** Is button icon small. */ + small?: boolean; }; -const getVolumeIcon = (volume) => { +const getVolumeIcon = (volume: number) => { if (volume === 0) { return Expensicons.Mute; } @@ -31,7 +30,7 @@ const getVolumeIcon = (volume) => { return Expensicons.VolumeHigh; }; -function VolumeButton({style, small}) { +function VolumeButton({style, small = false}: VolumeButtonProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const {updateVolume, volume} = useVolumeContext(); @@ -39,12 +38,12 @@ function VolumeButton({style, small}) { const [volumeIcon, setVolumeIcon] = useState({icon: getVolumeIcon(volume.value)}); const [isSliderBeingUsed, setIsSliderBeingUsed] = useState(false); - const onSliderLayout = useCallback((e) => { - setSliderHeight(e.nativeEvent.layout.height); + const onSliderLayout = useCallback((event: LayoutChangeEvent) => { + setSliderHeight(event.nativeEvent.layout.height); }, []); const changeVolumeOnPan = useCallback( - (event) => { + (event: GestureStateChangeEvent | GestureUpdateEvent) => { const val = NumberUtils.roundToTwoDecimalPlaces(1 - event.y / sliderHeight); volume.value = NumberUtils.clamp(val, 0, 1); }, @@ -65,7 +64,7 @@ function VolumeButton({style, small}) { const progressBarStyle = useAnimatedStyle(() => ({height: `${volume.value * 100}%`})); - const updateIcon = useCallback((vol) => { + const updateIcon = useCallback((vol: number) => { setVolumeIcon({icon: getVolumeIcon(vol)}); }, []); @@ -98,7 +97,6 @@ function VolumeButton({style, small}) { tooltipText={volume.value === 0 ? translate('videoPlayer.unmute') : translate('videoPlayer.mute')} onPress={() => updateVolume(volume.value === 0 ? 1 : 0)} src={volumeIcon.icon} - fill={styles.white} small={small} shouldForceRenderingTooltipBelow /> @@ -108,8 +106,6 @@ function VolumeButton({style, small}) { ); } -VolumeButton.propTypes = propTypes; -VolumeButton.defaultProps = defaultProps; VolumeButton.displayName = 'VolumeButton'; export default memo(VolumeButton); diff --git a/src/components/VideoPlayer/VideoPlayerControls/index.js b/src/components/VideoPlayer/VideoPlayerControls/index.tsx similarity index 75% rename from src/components/VideoPlayer/VideoPlayerControls/index.js rename to src/components/VideoPlayer/VideoPlayerControls/index.tsx index 262613ce0797..7c61721b67b7 100644 --- a/src/components/VideoPlayer/VideoPlayerControls/index.js +++ b/src/components/VideoPlayer/VideoPlayerControls/index.tsx @@ -1,55 +1,58 @@ -import PropTypes from 'prop-types'; +import type {Video} from 'expo-av'; +import type {MutableRefObject} from 'react'; import React, {useCallback, useMemo, useState} from 'react'; +import type {GestureResponderEvent, LayoutChangeEvent, StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import Animated from 'react-native-reanimated'; import * as Expensicons from '@components/Icon/Expensicons'; -import refPropTypes from '@components/refPropTypes'; import Text from '@components/Text'; import IconButton from '@components/VideoPlayer/IconButton'; import {convertMillisecondsToTime} from '@components/VideoPlayer/utils'; import {usePlaybackContext} from '@components/VideoPlayerContexts/PlaybackContext'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import stylePropTypes from '@styles/stylePropTypes'; import CONST from '@src/CONST'; import ProgressBar from './ProgressBar'; import VolumeButton from './VolumeButton'; -const propTypes = { - duration: PropTypes.number.isRequired, +type VideoPlayerControlsProps = { + /** Duration of a video. */ + duration: number; - position: PropTypes.number.isRequired, + /** Position of progress pointer. */ + position: number; - url: PropTypes.string.isRequired, + /** Url of a video. */ + url: string; - videoPlayerRef: refPropTypes.isRequired, + /** Ref for video player. */ + videoPlayerRef: MutableRefObject