2020-02-04 05:26:54 -09:00
|
|
|
import 'react-jinke-music-player/assets/index.css'
|
2020-03-31 10:27:39 -08:00
|
|
|
import subsonic from '../subsonic'
|
2020-02-04 05:26:54 -09:00
|
|
|
|
|
|
|
|
const PLAYER_ADD_TRACK = 'PLAYER_ADD_TRACK'
|
|
|
|
|
const PLAYER_SET_TRACK = 'PLAYER_SET_TRACK'
|
|
|
|
|
const PLAYER_SYNC_QUEUE = 'PLAYER_SYNC_QUEUE'
|
2020-02-05 06:11:42 -09:00
|
|
|
const PLAYER_SCROBBLE = 'PLAYER_SCROBBLE'
|
2020-02-07 13:36:50 -09:00
|
|
|
const PLAYER_PLAY_ALBUM = 'PLAYER_PLAY_ALBUM'
|
2020-02-04 05:26:54 -09:00
|
|
|
|
|
|
|
|
const mapToAudioLists = (item) => ({
|
2020-03-04 06:30:58 -09:00
|
|
|
id: item.id,
|
2020-04-07 07:55:45 -08:00
|
|
|
trackId: item.id,
|
2020-02-04 05:26:54 -09:00
|
|
|
name: item.title,
|
|
|
|
|
singer: item.artist,
|
2020-03-31 10:27:39 -08:00
|
|
|
cover: subsonic.url('getCoverArt', item.id, { size: 300 }),
|
|
|
|
|
musicSrc: subsonic.url('stream', item.id, { ts: true }),
|
2020-05-06 20:28:32 -08:00
|
|
|
scrobbled: false,
|
2020-02-04 05:26:54 -09:00
|
|
|
})
|
|
|
|
|
|
2020-05-05 08:07:50 -08:00
|
|
|
const setTrack = (data) => ({
|
|
|
|
|
type: PLAYER_SET_TRACK,
|
2020-02-04 05:26:54 -09:00
|
|
|
data,
|
|
|
|
|
})
|
|
|
|
|
|
2020-05-07 07:24:28 -08:00
|
|
|
let filterAlbumSongs = function (data, ids) {
|
|
|
|
|
if (!ids) {
|
|
|
|
|
return data
|
|
|
|
|
}
|
|
|
|
|
return ids.reduce((acc, id) => ({ ...acc, [id]: data[id] }), {})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const addTracks = (data, ids) => {
|
|
|
|
|
const songs = filterAlbumSongs(data, ids)
|
|
|
|
|
return {
|
|
|
|
|
type: PLAYER_ADD_TRACK,
|
|
|
|
|
data: songs,
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-04 05:26:54 -09:00
|
|
|
|
2020-04-26 15:15:52 -08:00
|
|
|
const shuffle = (data) => {
|
|
|
|
|
const ids = Object.keys(data)
|
|
|
|
|
for (let i = ids.length - 1; i > 0; i--) {
|
|
|
|
|
let j = Math.floor(Math.random() * (i + 1))
|
|
|
|
|
;[ids[i], ids[j]] = [ids[j], ids[i]]
|
|
|
|
|
}
|
|
|
|
|
const shuffled = {}
|
|
|
|
|
ids.forEach((id) => (shuffled[id] = data[id]))
|
|
|
|
|
return shuffled
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-07 07:24:28 -08:00
|
|
|
const shuffleAlbum = (data, ids) => {
|
|
|
|
|
const songs = filterAlbumSongs(data, ids)
|
|
|
|
|
const shuffled = shuffle(songs)
|
2020-04-26 15:15:52 -08:00
|
|
|
const firstId = Object.keys(shuffled)[0]
|
|
|
|
|
return {
|
|
|
|
|
type: PLAYER_PLAY_ALBUM,
|
|
|
|
|
id: firstId,
|
|
|
|
|
data: shuffled,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-07 07:24:28 -08:00
|
|
|
const playAlbum = (data, ids, selectedId) => {
|
|
|
|
|
const songs = filterAlbumSongs(data, ids)
|
|
|
|
|
return {
|
|
|
|
|
type: PLAYER_PLAY_ALBUM,
|
|
|
|
|
id: selectedId || Object.keys(songs)[0],
|
|
|
|
|
data: songs,
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-07 13:36:50 -09:00
|
|
|
|
2020-04-25 06:30:54 -08:00
|
|
|
const syncQueue = (id, data) => ({
|
2020-02-04 05:26:54 -09:00
|
|
|
type: PLAYER_SYNC_QUEUE,
|
2020-04-25 06:30:54 -08:00
|
|
|
id,
|
2020-02-04 05:26:54 -09:00
|
|
|
data,
|
|
|
|
|
})
|
|
|
|
|
|
2020-04-25 06:30:54 -08:00
|
|
|
const scrobble = (id, submit) => ({
|
2020-02-05 06:11:42 -09:00
|
|
|
type: PLAYER_SCROBBLE,
|
2020-04-25 06:30:54 -08:00
|
|
|
id,
|
|
|
|
|
submit,
|
2020-02-05 06:11:42 -09:00
|
|
|
})
|
|
|
|
|
|
2020-02-04 05:26:54 -09:00
|
|
|
const playQueueReducer = (
|
2020-04-24 16:38:03 -08:00
|
|
|
previousState = { queue: [], clear: true, playing: false },
|
2020-02-07 13:36:50 -09:00
|
|
|
payload
|
2020-02-04 05:26:54 -09:00
|
|
|
) => {
|
2020-02-07 13:36:50 -09:00
|
|
|
let queue
|
|
|
|
|
const { type, data } = payload
|
2020-02-04 05:26:54 -09:00
|
|
|
switch (type) {
|
|
|
|
|
case PLAYER_ADD_TRACK:
|
2020-02-07 13:36:50 -09:00
|
|
|
queue = previousState.queue
|
2020-05-07 07:24:28 -08:00
|
|
|
Object.keys(data).forEach((id) => {
|
|
|
|
|
queue.push(mapToAudioLists(data[id]))
|
2020-05-05 08:07:50 -08:00
|
|
|
})
|
2020-04-24 16:38:03 -08:00
|
|
|
return { ...previousState, queue, clear: false }
|
2020-02-04 05:26:54 -09:00
|
|
|
case PLAYER_SET_TRACK:
|
2020-04-24 16:38:03 -08:00
|
|
|
return {
|
|
|
|
|
...previousState,
|
|
|
|
|
queue: [mapToAudioLists(data)],
|
|
|
|
|
clear: true,
|
|
|
|
|
playing: true,
|
|
|
|
|
}
|
2020-02-04 05:26:54 -09:00
|
|
|
case PLAYER_SYNC_QUEUE:
|
2020-04-25 06:30:54 -08:00
|
|
|
return {
|
|
|
|
|
...previousState,
|
|
|
|
|
queue: data,
|
|
|
|
|
clear: false,
|
|
|
|
|
}
|
2020-02-05 06:11:42 -09:00
|
|
|
case PLAYER_SCROBBLE:
|
|
|
|
|
const newQueue = previousState.queue.map((item) => {
|
|
|
|
|
return {
|
|
|
|
|
...item,
|
2020-04-25 06:30:54 -08:00
|
|
|
scrobbled:
|
|
|
|
|
item.scrobbled || (item.trackId === payload.id && payload.submit),
|
2020-02-05 06:11:42 -09:00
|
|
|
}
|
|
|
|
|
})
|
2020-04-25 06:30:54 -08:00
|
|
|
return {
|
|
|
|
|
...previousState,
|
|
|
|
|
queue: newQueue,
|
|
|
|
|
clear: false,
|
|
|
|
|
playing: true,
|
|
|
|
|
}
|
2020-02-07 13:36:50 -09:00
|
|
|
case PLAYER_PLAY_ALBUM:
|
|
|
|
|
queue = []
|
|
|
|
|
let match = false
|
|
|
|
|
Object.keys(data).forEach((id) => {
|
|
|
|
|
if (id === payload.id) {
|
|
|
|
|
match = true
|
|
|
|
|
}
|
|
|
|
|
if (match) {
|
|
|
|
|
queue.push(mapToAudioLists(data[id]))
|
|
|
|
|
}
|
|
|
|
|
})
|
2020-04-25 06:30:54 -08:00
|
|
|
return {
|
|
|
|
|
...previousState,
|
|
|
|
|
queue,
|
|
|
|
|
clear: true,
|
|
|
|
|
playing: true,
|
|
|
|
|
}
|
2020-02-04 05:26:54 -09:00
|
|
|
default:
|
|
|
|
|
return previousState
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-26 15:15:52 -08:00
|
|
|
export {
|
2020-05-05 08:07:50 -08:00
|
|
|
addTracks,
|
2020-04-26 15:15:52 -08:00
|
|
|
setTrack,
|
|
|
|
|
playAlbum,
|
|
|
|
|
syncQueue,
|
|
|
|
|
scrobble,
|
|
|
|
|
shuffleAlbum,
|
|
|
|
|
playQueueReducer,
|
|
|
|
|
}
|