Skip to content

Commit 7bc05c1

Browse files
Merge pull request #17 from aureliony/source
feat(musicplayer): allow user to input playlist index
2 parents 7849e32 + b1bc4fc commit 7bc05c1

File tree

1 file changed

+62
-16
lines changed

1 file changed

+62
-16
lines changed

src/components/MusicPlayer.tsx

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
/** @jsxImportSource @emotion/react */
22
import { css } from '@emotion/react';
3-
import React, { useRef } from 'react';
3+
import React, { useEffect, useRef, useState } from 'react';
44
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';
76
import { IPlayingState } from '../models/Player';
87
import { selectedPlaylistAtom } from '../state/playlist';
98
import { useAtom, useAtomValue } from 'jotai';
@@ -20,22 +19,51 @@ export const MusicPlayer: React.FC<IMusicPlayerProps> = (props) => {
2019
const { playingState, setCurrentQueueSong } = props;
2120
const selectedPlaylist = useAtomValue(selectedPlaylistAtom);
2221
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]);
2329

2430
useEvent('pausevideo', () => {
2531
setIsPlaying(false);
2632
});
2733

28-
const onPreviousQueueSong: () => void = () => {
34+
const onPreviousQueueSong = () => {
2935
if (playingState.currentQueueSong < 1) return;
3036
setCurrentQueueSong(playingState.currentQueueSong - 1);
3137
};
3238

33-
const onNextQueueSong: () => void = () => {
39+
const onNextQueueSong = () => {
3440
if (playingState.currentQueueSong === playingState.currentQueue.length - 1)
3541
return;
3642
setCurrentQueueSong(playingState.currentQueueSong + 1);
3743
};
3844

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+
3967
return (
4068
<div>
4169
<ReactPlayer
@@ -98,22 +126,40 @@ export const MusicPlayer: React.FC<IMusicPlayerProps> = (props) => {
98126
>
99127
<i className="fa fa-step-backward"></i>
100128
</Button>
101-
<span
129+
<div
102130
css={css`
131+
display: inline-flex;
132+
align-items: center;
133+
padding: 0.25rem 0.5rem;
103134
background-color: #343a40;
104-
border-color: #343a40;
105135
color: white;
106-
padding: 0.25rem 0.5rem;
107136
font-size: 0.875rem;
108-
line-height: 1.5;
109-
border: 1px solid transparent;
110-
margin-left: -1px;
111137
`}
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>
117163
<Button
118164
variant="outline-primary"
119165
onClick={onNextQueueSong}

0 commit comments

Comments
 (0)