123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- import * as action from '../../actions'
- import { useEffect, useState, useCallback } from 'react';
- import { connect } from 'react-redux';
- import { useDropzone } from 'react-dropzone'
- import { sortableContainer, sortableElement } from 'react-sortable-hoc';
- import { arrayMoveImmutable } from 'array-move';
- import { faPlay, faPause} from "@fortawesome/free-solid-svg-icons";
- import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
- const Track = ({ track, playlist, player, setTrack, playTrack, pauseTrack }) => {
- let [_player, setPlayer] = useState()
- let [isPlay, setPlay] = useState(true)
- useEffect(() => setPlayer(player), [player])
- return (
- <li className={isPlay && _player?.isPlaying && _player.track?._id === track._id ? 'playlist__track highlightPaleGreen' : 'playlist__track'}>
- {isPlay && _player?.isPlaying && _player.track?._id === track._id ?
- <button
- className='highlightYellow'
- onClick={() => { pauseTrack(); setPlay(false) }}
- ><FontAwesomeIcon style={{pointerEvents:'none'}} icon={faPause} /></button> :
- <button
- className='highlightGreen'
- onClick={() => {
- if (track?._id !== _player?.track?._id) setTrack(track, playlist)
- playTrack()
- setPlay(true)
- }}
- ><FontAwesomeIcon style={{pointerEvents:'none'}} icon={faPlay} /></button>
- }
- <div>
- <small className='artist'>{track.id3.artist || 'Artist: unknown'}</small>
- <small className='album'>{track.id3.album || 'Album: unknown'}</small>
- <small className='title'>{track.id3.title || track.originalFileName}</small>
- </div>
- </li>
- )
- }
- const TrackConnect = connect(
- state => ({
- player: state.player || {},
- }),
- {
- setTrack: action.setTrack,
- pauseTrack: action.pauseTrack,
- playTrack: action.playTrack
- }
- )(Track)
- const SortableItem = sortableElement(TrackConnect);
- const SortableContainer = sortableContainer(({ children }) => <ul>{children}</ul> );
- const Playlist = ({ player, playlist, setPlaylist, updPlaylist, setIndex }) => {
- let [_tracks, setTracks] = useState()
- let [_player, setPlayer] = useState()
- useEffect(() => setPlayer(player), [player])
- useEffect(() => setTracks(playlist[0]?.tracks), [playlist])
- const onSortEnd = ({ oldIndex, newIndex }) => {
- let newArr = arrayMoveImmutable(_tracks, oldIndex, newIndex)
- setTracks(newArr)
- updPlaylist(playlist[0]._id, newArr.map(track => ({ _id: track._id })))
- if(_player?.playlist?._id === playlist[0]?._id) {
- setPlaylist({..._player.playlist, 'tracks': newArr})
- if (_player?.track) setIndex(newArr.map((item) => item._id).indexOf(_player?.track?._id))
- }
- };
- return (
- <>
- <h2 className='highlightGreen'>{playlist[0]?.name || 'Playlist'}</h2>
- <SortableContainer onSortEnd={onSortEnd}>
- { (_tracks || []).map((track, index) => <SortableItem key={track._id} index={index} track={track} playlist={playlist[0]} />) }
- </SortableContainer>
- </>
- )
- }
- export const PlaylistConnect = connect(
- state => ({
- playlist: state.promise.playlistTracks?.payload || [],
- player: state.player || {}
- }),
- {
- updPlaylist: action.actionUpdatePlaylist,
- setPlaylist: action.setPlaylist,
- setIndex: action.setIndex
- }
- )(Playlist)
- const PlaylistTrackDropzone = ({ playlist, uploadTrack }) => {
- let [playlistId, setPlaylistId] = useState()
- useEffect(() => {
- setPlaylistId(playlist[0]?._id)
- }, [playlist])
- const onDrop = useCallback(acceptedFiles => {
- if(acceptedFiles[0].type === 'audio/mpeg') uploadTrack(acceptedFiles[0], playlistId)
- }, [uploadTrack, playlistId])
- const { getRootProps, isDragActive } = useDropzone({ onDrop })
- return (
- <div
- {...getRootProps()}
- className='playlist'
- style={{ border: `${isDragActive ? '1px solid yellow' : '1px solid transparent'}` }}
- >
- <small className='lightText'>{isDragActive ? '...drop here' : 'to upload: drag and drop track here'}</small>
- <PlaylistConnect />
- </div>
- )
- }
- const PlaylistTrackDropzoneConnect = connect(
- state => ({ playlist: state.promise.playlistTracks?.payload || [] }),
- { uploadTrack: action.actionUploadUserTrack }
- )(PlaylistTrackDropzone)
- const PlaylistPage = ({ match: { params: { _id } }, getTracks }) => {
- useEffect(() => { getTracks(_id.substring(1)) }, [_id, getTracks])
- return (<PlaylistTrackDropzoneConnect />)
- }
- export const PlaylistPageConnect = connect(null, { getTracks: action.actionGetPlaylistById })(PlaylistPage)
- const UserTracks = ({ user, tracks }) => {
- let tracksRev = [...tracks].reverse()
- return (
- <>
- <h2 className='highlightYellow'>{user.login || 'My'} uploaded tracks:</h2>
- <ul>{(tracksRev || []).map(track => <TrackConnect key={track._id} track={track} playlist={tracksRev} />)}</ul>
- </>
- )
- }
- const UserTracksConnect = connect(state => ({
- tracks: state.promise.userTracks?.payload || [],
- user: state.promise.userData?.payload || {}
- })
- )(UserTracks)
- const UserTracksDropzone = ({ onLoad }) => {
- const onDrop = useCallback(acceptedFiles => {
- if(acceptedFiles[0].type === 'audio/mpeg') onLoad(acceptedFiles[0])
- }, [onLoad])
-
- const { getRootProps, isDragActive } = useDropzone({ onDrop })
- return (
- <div
- {...getRootProps()}
- className='playlist'
- style={{ height: 'fit-content', border: `${isDragActive ? '1px solid yellow' : '1px solid black'}` }}
- >
- <small className='lightText'>{isDragActive ? '...drop here' : 'to upload: drag and drop track here'}</small>
- <UserTracksConnect />
- </div>
- )
- }
- export const UserTrackDropzoneConnect = connect(null, { onLoad: action.actionUploadUserTrack })(UserTracksDropzone)
- const UserTracksPage = ({ match: { params: { _id } }, getUserTracks }) => {
- useEffect(() => { getUserTracks() }, [_id, getUserTracks])
- return (<UserTrackDropzoneConnect />)
- }
- export const UserTracksPageConnect = connect(null, { getUserTracks: action.actionGetUserTracks })(UserTracksPage)
|