1- import { playerController , PlayMode , usePlayerStore } from '@flow/player'
2- import { useCallback } from 'react'
3- import { StyleSheet , View } from 'react-native'
1+ import { formatDuration } from '@flow/core'
2+ import { playerController , PlayMode , useDisplayTrack , usePlayerStore } from '@flow/player'
3+ import Slider from '@react-native-community/slider'
4+ import { useCallback , useState } from 'react'
5+ import { Dimensions , StyleSheet , View } from 'react-native'
46import { IconButton , Text , useTheme } from 'react-native-paper'
57import { useSafeAreaInsets } from 'react-native-safe-area-context'
68
9+ const { width : screenWidth } = Dimensions . get ( 'screen' )
10+
711export default function FullPlayerControl ( ) {
812 const { bottom } = useSafeAreaInsets ( )
913 const { colors } = useTheme ( )
14+ const displayTrack = useDisplayTrack ( )
1015 const isPlaying = usePlayerStore . use . isPlaying ( )
1116 const mode = usePlayerStore . use . mode ( )
17+ const position = usePlayerStore . use . position ( )
18+ const [ isSliding , setIsSliding ] = useState ( false )
19+ const [ sliderValue , setSliderValue ] = useState ( 0 )
1220
1321 const handlePlayPause = useCallback ( ( ) => {
1422 if ( isPlaying ) {
@@ -27,8 +35,48 @@ export default function FullPlayerControl() {
2735 playerController . prev ( )
2836 } , [ ] )
2937
38+ const handleSliderChange = useCallback ( ( value : number ) => {
39+ setSliderValue ( value )
40+ } , [ ] )
41+
42+ const handleSliderSlidingComplete = useCallback ( ( value : number ) => {
43+ setIsSliding ( false )
44+ if ( displayTrack ?. duration && displayTrack . duration > 0 ) {
45+ const newPosition = value * displayTrack . duration
46+ playerController . seekTo ( newPosition )
47+ }
48+ } , [ displayTrack ?. duration ] )
49+
50+ const handleSliderSlidingStart = useCallback ( ( ) => {
51+ setIsSliding ( true )
52+ } , [ ] )
53+
54+ // 更新滑块值
55+ const currentSliderValue = isSliding ? sliderValue : ( displayTrack ?. duration && displayTrack . duration > 0 ? position / displayTrack . duration : 0 )
56+
3057 return (
3158 < View style = { [ styles . container , { paddingBottom : bottom + 36 } ] } >
59+ < View >
60+ < Slider
61+ style = { styles . slider }
62+ value = { currentSliderValue }
63+ minimumTrackTintColor = { colors . primary }
64+ maximumTrackTintColor = { colors . outline }
65+ thumbTintColor = { colors . primary }
66+ onValueChange = { handleSliderChange }
67+ onSlidingComplete = { handleSliderSlidingComplete }
68+ onSlidingStart = { handleSliderSlidingStart }
69+ />
70+ < View style = { styles . timeTextContainer } >
71+ < Text style = { [ styles . timeText , { color : colors . onSurfaceVariant } ] } >
72+ { formatDuration ( position ) }
73+ </ Text >
74+ < Text style = { [ styles . timeText , { color : colors . onSurfaceVariant } ] } >
75+ { formatDuration ( displayTrack ?. duration ?? 0 ) }
76+ </ Text >
77+ </ View >
78+ </ View >
79+
3280 < View style = { styles . controls } >
3381 < IconButton
3482 icon = "skip-previous"
@@ -62,6 +110,18 @@ const styles = StyleSheet.create({
62110 container : {
63111 gap : 20 ,
64112 } ,
113+ slider : {
114+ alignSelf : 'center' ,
115+ width : screenWidth - 24 ,
116+ } ,
117+ timeTextContainer : {
118+ flexDirection : 'row' ,
119+ justifyContent : 'space-between' ,
120+ } ,
121+ timeText : {
122+ fontSize : 12 ,
123+ textAlign : 'center' ,
124+ } ,
65125 controls : {
66126 flexDirection : 'row' ,
67127 alignItems : 'center' ,
0 commit comments