177 lines
3.8 KiB
JavaScript
177 lines
3.8 KiB
JavaScript
import { v4 as uuidv4 } from 'uuid'
|
|
import subsonic from '../subsonic'
|
|
import {
|
|
PLAYER_ADD_TRACKS,
|
|
PLAYER_CLEAR_QUEUE,
|
|
PLAYER_CURRENT,
|
|
PLAYER_PLAY_NEXT,
|
|
PLAYER_PLAY_TRACKS,
|
|
PLAYER_SET_TRACK,
|
|
PLAYER_SET_VOLUME,
|
|
PLAYER_SYNC_QUEUE,
|
|
} from '../actions'
|
|
import config from '../config'
|
|
|
|
const initialState = {
|
|
queue: [],
|
|
current: {},
|
|
clear: false,
|
|
volume: config.defaultUIVolume / 100,
|
|
savedPlayIndex: 0,
|
|
}
|
|
|
|
const timestampRegex =
|
|
/(\[([0-9]{1,2}:)?([0-9]{1,2}:)([0-9]{1,2})(\.[0-9]{1,2})?\])/g
|
|
|
|
const mapToAudioLists = (item) => {
|
|
// If item comes from a playlist, trackId is mediaFileId
|
|
const trackId = item.mediaFileId || item.id
|
|
|
|
if (item.isRadio) {
|
|
return {
|
|
trackId,
|
|
uuid: uuidv4(),
|
|
name: item.name,
|
|
song: item,
|
|
musicSrc: item.streamUrl,
|
|
cover: item.cover,
|
|
isRadio: true,
|
|
}
|
|
}
|
|
|
|
const { lyrics } = item
|
|
return {
|
|
trackId,
|
|
uuid: uuidv4(),
|
|
song: item,
|
|
name: item.title,
|
|
lyric: timestampRegex.test(lyrics) ? lyrics : '',
|
|
singer: item.artist,
|
|
duration: item.duration,
|
|
musicSrc: subsonic.streamUrl(trackId),
|
|
cover: subsonic.getCoverArtUrl(
|
|
{
|
|
id: trackId,
|
|
updatedAt: item.updatedAt,
|
|
album: item.album,
|
|
},
|
|
300
|
|
),
|
|
}
|
|
}
|
|
|
|
const reduceClearQueue = () => ({ ...initialState, clear: true })
|
|
|
|
const reducePlayTracks = (state, { data, id }) => {
|
|
let playIndex = 0
|
|
const queue = Object.keys(data).map((key, idx) => {
|
|
if (key === id) {
|
|
playIndex = idx
|
|
}
|
|
return mapToAudioLists(data[key])
|
|
})
|
|
return {
|
|
...state,
|
|
queue,
|
|
playIndex,
|
|
clear: true,
|
|
}
|
|
}
|
|
|
|
const reduceSetTrack = (state, { data }) => {
|
|
return {
|
|
...state,
|
|
queue: [mapToAudioLists(data)],
|
|
playIndex: 0,
|
|
clear: true,
|
|
}
|
|
}
|
|
|
|
const reduceAddTracks = (state, { data }) => {
|
|
const queue = state.queue
|
|
Object.keys(data).forEach((id) => {
|
|
queue.push(mapToAudioLists(data[id]))
|
|
})
|
|
return { ...state, queue, clear: false }
|
|
}
|
|
|
|
const reducePlayNext = (state, { data }) => {
|
|
const newQueue = []
|
|
const current = state.current || {}
|
|
let foundPos = false
|
|
state.queue.forEach((item) => {
|
|
newQueue.push(item)
|
|
if (item.uuid === current.uuid) {
|
|
foundPos = true
|
|
Object.keys(data).forEach((id) => {
|
|
newQueue.push(mapToAudioLists(data[id]))
|
|
})
|
|
}
|
|
})
|
|
if (!foundPos) {
|
|
Object.keys(data).forEach((id) => {
|
|
newQueue.push(mapToAudioLists(data[id]))
|
|
})
|
|
}
|
|
|
|
return {
|
|
...state,
|
|
queue: newQueue,
|
|
clear: true,
|
|
}
|
|
}
|
|
|
|
const reduceSetVolume = (state, { data: { volume } }) => {
|
|
return {
|
|
...state,
|
|
volume,
|
|
}
|
|
}
|
|
|
|
const reduceSyncQueue = (state, { data: { audioInfo, audioLists } }) => {
|
|
return {
|
|
...state,
|
|
queue: audioLists,
|
|
clear: false,
|
|
playIndex: undefined,
|
|
}
|
|
}
|
|
|
|
const reduceCurrent = (state, { data }) => {
|
|
const current = data.ended ? {} : data
|
|
const savedPlayIndex = state.queue.findIndex(
|
|
(item) => item.uuid === current.uuid
|
|
)
|
|
return {
|
|
...state,
|
|
current,
|
|
playIndex: undefined,
|
|
savedPlayIndex,
|
|
volume: data.volume,
|
|
}
|
|
}
|
|
|
|
export const playerReducer = (previousState = initialState, payload) => {
|
|
const { type } = payload
|
|
switch (type) {
|
|
case PLAYER_CLEAR_QUEUE:
|
|
return reduceClearQueue()
|
|
case PLAYER_PLAY_TRACKS:
|
|
return reducePlayTracks(previousState, payload)
|
|
case PLAYER_SET_TRACK:
|
|
return reduceSetTrack(previousState, payload)
|
|
case PLAYER_ADD_TRACKS:
|
|
return reduceAddTracks(previousState, payload)
|
|
case PLAYER_PLAY_NEXT:
|
|
return reducePlayNext(previousState, payload)
|
|
case PLAYER_SET_VOLUME:
|
|
return reduceSetVolume(previousState, payload)
|
|
case PLAYER_SYNC_QUEUE:
|
|
return reduceSyncQueue(previousState, payload)
|
|
case PLAYER_CURRENT:
|
|
return reduceCurrent(previousState, payload)
|
|
default:
|
|
return previousState
|
|
}
|
|
}
|