import {useReducer, useEffect} from 'react';
import Sound from 'react-sound';
import Main from './Main';
import Queue from './Queue';
import Controls from './Controls';
import MediaSession from './MediaSession.js';
const NO_SOUND = {url: '', playStatus: Sound.status.STOPPED};
const NO_METADATA = {artist: '', album: '', title: '', cover: ''};
const NO_QUEUE = {items: [], pos: -1};
const NO_ERROR = null;
function storeQueue(queue) {
localStorage.setItem('queue', JSON.stringify(queue));
}
function loadQueue() {
const queue = localStorage.getItem('queue');
return queue && JSON.parse(queue);
}
function playTrack(track, status) {
return {
sound: {url: track.url,
position: 0,
playStatus: (status || Sound.status.PLAYING)},
metadata: {
title: track.title,
artist: track.artist,
album: track.album,
cover: track.cover
},
error: NO_ERROR
}
}
function playQueue(state, pos) {
if (pos < 0 || pos >= state.queue.items.length)
return {...state, sound: NO_SOUND, metadata: NO_METADATA};
const queue = {...state.queue, pos}
storeQueue(queue);
return {...state, queue, ...playTrack(state.queue.items[pos])}
}
function playerReducer(state, action) {
switch (action.type) {
case 'ALBUM_PLAY': {
if (!action.payload || !action.payload.tracks) return state;
const queue = {items: action.payload.tracks}
return playQueue({...state, queue}, (action.payload.pos || 0))}
case 'ALBUM_ENQUEUE': {
if (!action.payload) return state;
const queue = {...state.queue, items: state.queue.items.concat(action.payload.tracks)};
return {...state, queue}}
case 'CONTROL_PLAY':
return {...state, sound: {...state.sound, playStatus: Sound.status.PLAYING}}
case 'CONTROL_PAUSE':
return {...state, sound: {...state.sound, playStatus: Sound.status.PAUSED}}
case 'CONTROL_PREV':
return playQueue(state, state.queue.pos - 1);
case 'CONTROL_NEXT':
return playQueue(state, state.queue.pos + 1);
case 'CONTROL_STOP':
return {...state, queue: {...state.queue, pos:-1}, sound: NO_SOUND, metadata: NO_METADATA}
case 'QUEUE_PLAY':
return playQueue(state, action.payload);
case 'QUEUE_LOAD': {
const queue = action.payload;
return {...state, queue, ...playTrack(queue.items[queue.pos], Sound.status.PAUSED)}}
case 'SOUND_ERROR':
return {...state, sound: NO_SOUND, metadata: NO_METADATA, error: action.payload}
case 'SOUND_PLAYING':
return {...state, sound: {...state.sound, ...action.payload}}
case 'SOUND_FINISHED':
return playQueue(state, state.queue.pos + 1);
default: throw new Error(`Unknown action type: ${action.type}`);
}
}
export default function Player() {
const INIT = {sound: NO_SOUND,
error: NO_ERROR,
queue: NO_QUEUE,
metadata: NO_METADATA}
const [state, dispatch] = useReducer(playerReducer, INIT);
useEffect(()=>{
const queue = loadQueue();
if (queue) dispatch({type: 'QUEUE_LOAD', payload: queue});
}, []);
return (
<>
dispatch({type: 'SOUND_ERROR', payload: {code, desc}})}
onPlaying={(payload) => dispatch({type: 'SOUND_PLAYING', payload})}
onFinishedPlaying={() => dispatch({type: 'SOUND_FINISHED'})} />
dispatch({type:'CONTROL_PLAY'})}
onPause={()=>dispatch({type:'CONTROL_PAUSE'})}
onPreviousTrack={()=>dispatch({type:'CONTROL_PREV'})}
onNextTrack={()=>dispatch({type:'CONTROL_NEXT'})}
/>
>
);
}