1
1
/** @jsxImportSource @emotion /react */
2
2
import { css } from '@emotion/react' ;
3
- import React , { useRef } from 'react' ;
3
+ import React , { useEffect , useRef , useState } from 'react' ;
4
4
import ReactPlayer from 'react-player' ;
5
- import { padStart } from 'lodash-es' ;
6
- import { ButtonGroup , Button } from 'react-bootstrap' ;
5
+ import { ButtonGroup , Button , FormControl } from 'react-bootstrap' ;
7
6
import { IPlayingState } from '../models/Player' ;
8
7
import { selectedPlaylistAtom } from '../state/playlist' ;
9
8
import { useAtom , useAtomValue } from 'jotai' ;
@@ -20,22 +19,51 @@ export const MusicPlayer: React.FC<IMusicPlayerProps> = (props) => {
20
19
const { playingState, setCurrentQueueSong } = props ;
21
20
const selectedPlaylist = useAtomValue ( selectedPlaylistAtom ) ;
22
21
const [ isPlaying , setIsPlaying ] = useAtom ( isPlayingAtom ) ;
22
+ const [ inputValue , setInputValue ] = useState (
23
+ playingState . currentQueueSong + 1
24
+ ) ;
25
+
26
+ useEffect ( ( ) => {
27
+ setInputValue ( playingState . currentQueueSong + 1 ) ;
28
+ } , [ playingState . currentQueueSong ] ) ;
23
29
24
30
useEvent ( 'pausevideo' , ( ) => {
25
31
setIsPlaying ( false ) ;
26
32
} ) ;
27
33
28
- const onPreviousQueueSong : ( ) => void = ( ) => {
34
+ const onPreviousQueueSong = ( ) => {
29
35
if ( playingState . currentQueueSong < 1 ) return ;
30
36
setCurrentQueueSong ( playingState . currentQueueSong - 1 ) ;
31
37
} ;
32
38
33
- const onNextQueueSong : ( ) => void = ( ) => {
39
+ const onNextQueueSong = ( ) => {
34
40
if ( playingState . currentQueueSong === playingState . currentQueue . length - 1 )
35
41
return ;
36
42
setCurrentQueueSong ( playingState . currentQueueSong + 1 ) ;
37
43
} ;
38
44
45
+ const handleInputChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
46
+ const userInput = parseInt ( e . target . value , 10 ) ;
47
+ if ( isNaN ( userInput ) ) {
48
+ return ;
49
+ }
50
+ const newInputValue = Math . max (
51
+ 1 ,
52
+ Math . min ( userInput , playingState . currentQueue . length )
53
+ ) ;
54
+ setInputValue ( newInputValue ) ;
55
+ } ;
56
+
57
+ const handleInputBlur = ( ) => {
58
+ setCurrentQueueSong ( inputValue - 1 ) ;
59
+ } ;
60
+
61
+ const handleInputKeyDown = ( e : React . KeyboardEvent < HTMLInputElement > ) => {
62
+ if ( e . key === 'Enter' || e . key === 'Escape' ) {
63
+ ( e . target as HTMLInputElement ) . blur ( ) ;
64
+ }
65
+ } ;
66
+
39
67
return (
40
68
< div >
41
69
< ReactPlayer
@@ -98,22 +126,40 @@ export const MusicPlayer: React.FC<IMusicPlayerProps> = (props) => {
98
126
>
99
127
< i className = "fa fa-step-backward" > </ i >
100
128
</ Button >
101
- < span
129
+ < div
102
130
css = { css `
131
+ display : inline-flex;
132
+ align-items : center;
133
+ padding : 0.25rem 0.5rem ;
103
134
background-color : # 343a40 ;
104
- border-color : # 343a40 ;
105
135
color : white;
106
- padding : 0.25rem 0.5rem ;
107
136
font-size : 0.875rem ;
108
- line-height : 1.5 ;
109
- border : 1px solid transparent;
110
- margin-left : -1px ;
111
137
` }
112
- > { `${ padStart (
113
- ( playingState . currentQueueSong + 1 ) . toString ( ) ,
114
- playingState . currentQueue . length . toString ( ) . length ,
115
- '0'
116
- ) } | ${ playingState . currentQueue . length } `} </ span >
138
+ >
139
+ < FormControl
140
+ type = "text"
141
+ value = { inputValue }
142
+ onChange = { handleInputChange }
143
+ onBlur = { handleInputBlur }
144
+ onKeyDown = { handleInputKeyDown }
145
+ css = { css `
146
+ height : 100% ;
147
+ width : 6ch ;
148
+ padding : 0.25rem ;
149
+ background-color : inherit;
150
+ color : inherit;
151
+ font-size : 0.875rem ;
152
+ text-align : center;
153
+ ` }
154
+ />
155
+ < span
156
+ css = { css `
157
+ margin-left : 5px ;
158
+ ` }
159
+ >
160
+ / { playingState . currentQueue . length }
161
+ </ span >
162
+ </ div >
117
163
< Button
118
164
variant = "outline-primary"
119
165
onClick = { onNextQueueSong }
0 commit comments