160 lines
3.7 KiB
JavaScript
160 lines
3.7 KiB
JavaScript
import { v4 as uuidv4 } from 'uuid'
|
|
import subsonic from '../subsonic'
|
|
import config from '../config'
|
|
|
|
import {
|
|
PLAYER_CLEAR_QUEUE,
|
|
PLAYER_SET_VOLUME,
|
|
PLAYER_CURRENT,
|
|
PLAYER_ADD_TRACKS,
|
|
PLAYER_PLAY_NEXT,
|
|
PLAYER_SET_TRACK,
|
|
PLAYER_SYNC_QUEUE,
|
|
PLAYER_SCROBBLE,
|
|
PLAYER_PLAY_TRACKS,
|
|
} from '../actions'
|
|
|
|
const mapToAudioLists = (item) => {
|
|
// If item comes from a playlist, id is mediaFileId
|
|
const id = item.mediaFileId || item.id
|
|
return {
|
|
trackId: id,
|
|
name: item.title,
|
|
singer: item.artist,
|
|
album: item.album,
|
|
albumId: item.albumId,
|
|
artistId: item.albumArtistId,
|
|
duration: item.duration,
|
|
suffix: item.suffix,
|
|
bitRate: item.bitRate,
|
|
musicSrc: subsonic.streamUrl(id),
|
|
cover: subsonic.getCoverArtUrl(
|
|
{
|
|
coverArtId: config.devFastAccessCoverArt ? item.albumId : id,
|
|
updatedAt: item.updatedAt,
|
|
},
|
|
300
|
|
),
|
|
scrobbled: false,
|
|
uuid: uuidv4(),
|
|
}
|
|
}
|
|
|
|
const initialState = {
|
|
queue: [],
|
|
clear: true,
|
|
current: {},
|
|
volume: 1,
|
|
playIndex: 0,
|
|
}
|
|
|
|
export const playQueueReducer = (previousState = initialState, payload) => {
|
|
let queue, current
|
|
let newQueue
|
|
const { type, data } = payload
|
|
switch (type) {
|
|
case PLAYER_CLEAR_QUEUE:
|
|
return initialState
|
|
case PLAYER_SET_VOLUME:
|
|
return {
|
|
...previousState,
|
|
playIndex: undefined,
|
|
volume: data.volume,
|
|
}
|
|
case PLAYER_CURRENT:
|
|
queue = previousState.queue
|
|
current = data.ended
|
|
? {}
|
|
: {
|
|
trackId: data.trackId,
|
|
uuid: data.uuid,
|
|
paused: data.paused,
|
|
}
|
|
return {
|
|
...previousState,
|
|
current,
|
|
playIndex: undefined,
|
|
volume: data.volume,
|
|
}
|
|
case PLAYER_ADD_TRACKS:
|
|
queue = previousState.queue
|
|
Object.keys(data).forEach((id) => {
|
|
queue.push(mapToAudioLists(data[id]))
|
|
})
|
|
return { ...previousState, queue, clear: false, playIndex: undefined }
|
|
case PLAYER_PLAY_NEXT:
|
|
current = previousState.current?.uuid || ''
|
|
newQueue = []
|
|
let foundPos = false
|
|
previousState.queue.forEach((item) => {
|
|
newQueue.push(item)
|
|
if (item.uuid === current) {
|
|
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 {
|
|
...previousState,
|
|
queue: newQueue,
|
|
clear: true,
|
|
playIndex: undefined,
|
|
}
|
|
case PLAYER_SET_TRACK:
|
|
return {
|
|
...previousState,
|
|
queue: [mapToAudioLists(data)],
|
|
clear: true,
|
|
playIndex: 0,
|
|
}
|
|
case PLAYER_SYNC_QUEUE:
|
|
current = data.length > 0 ? previousState.current : {}
|
|
return {
|
|
...previousState,
|
|
queue: data,
|
|
clear: false,
|
|
playIndex: undefined,
|
|
current,
|
|
}
|
|
case PLAYER_SCROBBLE:
|
|
newQueue = previousState.queue.map((item) => {
|
|
return {
|
|
...item,
|
|
scrobbled:
|
|
item.scrobbled || (item.trackId === payload.id && payload.submit),
|
|
}
|
|
})
|
|
return {
|
|
...previousState,
|
|
queue: newQueue,
|
|
playIndex: undefined,
|
|
clear: false,
|
|
}
|
|
case PLAYER_PLAY_TRACKS:
|
|
queue = []
|
|
let match = false
|
|
Object.keys(data).forEach((id) => {
|
|
if (id === payload.id) {
|
|
match = true
|
|
}
|
|
if (match) {
|
|
queue.push(mapToAudioLists(data[id]))
|
|
}
|
|
})
|
|
return {
|
|
...previousState,
|
|
queue,
|
|
playIndex: 0,
|
|
clear: true,
|
|
}
|
|
default:
|
|
return previousState
|
|
}
|
|
}
|