11import * as React from "react" ;
2- import { Text , View , StyleSheet , TouchableHighlight } from "react-native" ;
2+ import {
3+ Text ,
4+ View ,
5+ TouchableHighlight ,
6+ StyleProp ,
7+ StyleSheet ,
8+ } from "react-native" ;
39import { Audio , AVPlaybackStatus , AVPlaybackSource } from "expo-av" ;
410import { AntDesign } from "@expo/vector-icons" ;
511import Slider from "@react-native-community/slider" ;
612
713import type { Sound } from "expo-av/build/Audio/Sound" ;
814
15+ interface Props {
16+ source : AVPlaybackSource ;
17+ style ?: StyleProp < any > ;
18+ sliderColor ?: string ;
19+ completedTrackColor ?: string ;
20+ remainingTrackColor ?: string ;
21+ playSize ?: number ;
22+ playColor ?: string ;
23+ }
24+
925function formatDuration ( duration : number ) {
1026 if ( duration === 0 || duration === 1 ) return "00:00" ;
1127
@@ -24,17 +40,59 @@ function formatDuration(duration: number) {
2440 return renderedMinutes + ":" + renderedSeconds ;
2541}
2642
27- export default function AudioPlayer ( { source } : { source : AVPlaybackSource } ) {
43+ export default function AudioPlayer ( {
44+ source,
45+ style = { } ,
46+ sliderColor = "black" ,
47+ completedTrackColor = "black" ,
48+ remainingTrackColor = "black" ,
49+ playSize = 24 ,
50+ playColor = "black" ,
51+ } : Props ) {
2852 const [ sound , setSound ] = React . useState < Sound > ( ) ;
2953 const [ playing , setPlay ] = React . useState ( false ) ;
3054 const [ loading , setLoading ] = React . useState ( false ) ;
31- const [ durationMillis , setDurationMillis ] = React . useState ( 1 ) ;
55+ const [ durationMillis , setDurationMillis ] = React . useState <
56+ number | undefined
57+ > ( 1 ) ;
3258 const [ isDraggingSlider , setIsDraggingSlider ] = React . useState ( false ) ;
3359 const [ sliderPositionMillis , setSliderPositionMillis ] = React . useState ( 0 ) ;
3460
61+ const {
62+ color,
63+ fontFamily,
64+ fontWeight,
65+ fontSize,
66+ lineHeight,
67+ letterSpacing,
68+ textTransform,
69+ textAlign,
70+ textDecorationLine,
71+ textDecorationColor,
72+ textDecorationStyle,
73+ ...viewStyles
74+ } = StyleSheet . flatten ( style || { } ) ;
75+
76+ const textStyles = {
77+ color,
78+ fontFamily,
79+ fontWeight,
80+ fontSize,
81+ lineHeight,
82+ letterSpacing,
83+ textTransform,
84+ textAlign,
85+ textDecorationLine,
86+ textDecorationColor,
87+ textDecorationStyle,
88+ } ;
89+
3590 const onPlaybackStatusUpdate = async ( status : AVPlaybackStatus ) => {
3691 if ( status . isLoaded ) {
37- if ( status . isPlaying && ! isDraggingSlider ) {
92+ if ( durationMillis !== status ?. durationMillis ) {
93+ setDurationMillis ( status ?. durationMillis || 1 ) ;
94+ }
95+ if ( status . isPlaying ) {
3896 setSliderPositionMillis ( status . positionMillis ) ;
3997 }
4098
@@ -120,19 +178,19 @@ export default function AudioPlayer({ source }: { source: AVPlaybackSource }) {
120178 const iconName = loading ? "loading1" : ! sound || ! playing ? "play" : "pause" ;
121179
122180 return (
123- < View style = { styles . container } >
181+ < View style = { [ styles . container , viewStyles ] } >
124182 < TouchableHighlight onPress = { playSound } style = { { marginRight : 8 } } >
125- < AntDesign name = { iconName } size = { 24 } />
183+ < AntDesign name = { iconName } size = { playSize } color = { playColor } />
126184 </ TouchableHighlight >
127- < Text style = { { marginRight : 8 } } >
128- { formatDuration ( sliderPositionMillis || 0 ) } /{ " " }
185+ < Text style = { { marginRight : 8 , ... textStyles } } >
186+ { formatDuration ( sliderPositionMillis ?? 0 ) } /{ " " }
129187 { formatDuration ( durationMillis || 0 ) }
130188 </ Text >
131189 < Slider
132190 style = { { flex : 1 } }
133- minimumTrackTintColor = "#333"
134- maximumTrackTintColor = "#000000"
135- thumbTintColor = "black"
191+ minimumTrackTintColor = { completedTrackColor }
192+ maximumTrackTintColor = { remainingTrackColor }
193+ thumbTintColor = { sliderColor }
136194 minimumValue = { 0 }
137195 value = { sliderPositionMillis }
138196 maximumValue = { durationMillis }
@@ -145,10 +203,6 @@ export default function AudioPlayer({ source }: { source: AVPlaybackSource }) {
145203
146204const styles = StyleSheet . create ( {
147205 container : {
148- backgroundColor : "#eee" ,
149- paddingHorizontal : 16 ,
150- paddingVertical : 8 ,
151- borderRadius : 24 ,
152206 flexDirection : "row" ,
153207 alignItems : "center" ,
154208 } ,
0 commit comments