172 lines
4.6 KiB
TypeScript
172 lines
4.6 KiB
TypeScript
import type { BackendError, Track } from '~/types'
|
|
import type { RootState } from '~/store/index'
|
|
import type { Module } from 'vuex'
|
|
|
|
import { useQueue } from '~/composables/audio/queue'
|
|
import { usePlayer } from '~/composables/audio/player'
|
|
import { CLIENT_RADIOS } from '~/utils/clientRadios'
|
|
|
|
import axios from 'axios'
|
|
|
|
import useLogger from '~/composables/useLogger'
|
|
|
|
export interface State {
|
|
current: null | CurrentRadio
|
|
running: boolean
|
|
populating: boolean
|
|
}
|
|
|
|
export interface ObjectId {
|
|
username: string
|
|
fullUsername: string
|
|
}
|
|
|
|
export interface CurrentRadio {
|
|
clientOnly: boolean
|
|
session: null
|
|
type: 'account'
|
|
customRadioId: number
|
|
config: RadioConfig
|
|
objectId: ObjectId | null
|
|
}
|
|
|
|
export type RadioConfig = { type: 'tag', names: string[] } | { type: 'artist' | 'playlist', ids: string[] }
|
|
|
|
const logger = useLogger()
|
|
|
|
const store: Module<State, RootState> = {
|
|
namespaced: true,
|
|
state: {
|
|
current: null,
|
|
running: false,
|
|
populating: false
|
|
},
|
|
getters: {
|
|
types: () => {
|
|
return {
|
|
'actor-content': {
|
|
name: 'Your content',
|
|
description: 'Picks from your own libraries'
|
|
},
|
|
random: {
|
|
name: 'Random',
|
|
description: "Totally random picks, maybe you'll discover new things?"
|
|
},
|
|
random_library: {
|
|
name: 'Random',
|
|
description: 'Random picks from your library, be surprise by yourself ?'
|
|
},
|
|
favorites: {
|
|
name: 'Favorites',
|
|
description: 'Play your favorites tunes in a never-ending happiness loop.'
|
|
},
|
|
'less-listened': {
|
|
name: 'Less listened',
|
|
description: "Listen to tracks you usually don't. It's time to restore some balance."
|
|
},
|
|
'less-listened_library': {
|
|
name: 'Less listened',
|
|
description: "Listen to tracks from your library you usually don't. It's time to restore some balance."
|
|
},
|
|
'recently-added': {
|
|
name: 'Recently Added',
|
|
description: 'Newest content on the network. Get some fresh air.'
|
|
}
|
|
}
|
|
}
|
|
},
|
|
mutations: {
|
|
reset (state) {
|
|
state.running = false
|
|
state.current = null
|
|
state.populating = false
|
|
},
|
|
current: (state, value) => {
|
|
state.current = value
|
|
},
|
|
running: (state, value) => {
|
|
state.running = value
|
|
}
|
|
},
|
|
actions: {
|
|
start ({ commit, dispatch }, { type, objectId, customRadioId, clientOnly, config }) {
|
|
const params = {
|
|
radio_type: type,
|
|
related_object_id: objectId,
|
|
custom_radio: customRadioId,
|
|
config
|
|
}
|
|
|
|
if (clientOnly) {
|
|
commit('current', { type, objectId, customRadioId, clientOnly, config })
|
|
commit('running', true)
|
|
dispatch('populateQueue', true)
|
|
return
|
|
}
|
|
|
|
return axios.post('radios/sessions/', params).then((response) => {
|
|
logger.info('Successfully started radio ', type)
|
|
commit('current', { type, objectId, session: response.data.id, customRadioId })
|
|
commit('running', true)
|
|
dispatch('populateQueue', true)
|
|
}, () => {
|
|
logger.error('Error while starting radio', type)
|
|
})
|
|
},
|
|
stop ({ commit, state }) {
|
|
if (state.current?.clientOnly) {
|
|
CLIENT_RADIOS[state.current.type].stop()
|
|
}
|
|
|
|
commit('current', null)
|
|
commit('running', false)
|
|
},
|
|
async populateQueue ({ commit, state }, playNow) {
|
|
if (!state.running || state.populating) {
|
|
return
|
|
}
|
|
|
|
state.populating = true
|
|
|
|
const { enqueue, playTrack, tracks } = useQueue()
|
|
const { isPlaying } = usePlayer()
|
|
|
|
const params = { session: state.current?.session }
|
|
|
|
try {
|
|
logger.info('Adding track to queue from radio')
|
|
|
|
const track = state.current?.clientOnly
|
|
? await CLIENT_RADIOS[state.current.type].fetchNextTrack(state.current)
|
|
: await axios.post('radios/tracks/', params).then(response => response.data.track as Track)
|
|
|
|
if (track === undefined) {
|
|
isPlaying.value = false
|
|
return
|
|
}
|
|
|
|
await enqueue(track)
|
|
|
|
if (playNow) {
|
|
await playTrack(tracks.value.length - 1)
|
|
isPlaying.value = true
|
|
}
|
|
} catch (error) {
|
|
if ((error as BackendError).backendErrors?.[0] === 'Radio doesn\'t have more candidates') {
|
|
commit('ui/addMessage', {
|
|
content: (error as BackendError).backendErrors?.[0]
|
|
}, { root: true })
|
|
} else {
|
|
logger.error('Error while adding track to queue from radio', error)
|
|
}
|
|
|
|
commit('reset')
|
|
} finally {
|
|
state.populating = false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export default store
|