import path from 'path' import music from '../../utils/music' import { getRandom, checkPath } from '../../utils' // state const state = { listInfo: { list: [], id: null, }, playIndex: -1, changePlay: false, isShowPlayerDetail: false, playedList: [], playMusicInfo: null, tempPlayList: [], } let urlRequest // let picRequest // let lrcRequest const filterList = async({ playedList, listInfo, savePath, commit }) => { // if (this.list.listName === null) return let list let canPlayList = [] const filteredPlayedList = playedList.filter(({ listId, isTempPlay }) => listInfo.id === listId && !isTempPlay).map(({ musicInfo }) => musicInfo) if (listInfo.id == 'download') { list = [] for (const item of listInfo.list) { const filePath = path.join(savePath, item.fileName) if (!await checkPath(filePath) || !item.isComplate || /\.ape$/.test(filePath)) continue canPlayList.push(item) // 排除已播放音乐 let index = filteredPlayedList.indexOf(item) if (index > -1) { filteredPlayedList.splice(index, 1) continue } list.push(item) } } else { list = listInfo.list.filter(s => { // if (!assertApiSupport(s.source)) return false canPlayList.push(s) let index = filteredPlayedList.indexOf(s) if (index > -1) { filteredPlayedList.splice(index, 1) return false } return true }) } if (!list.length && playedList.length) { commit('clearPlayedList') return canPlayList } return list } const getPic = function(musicInfo, retryedSource = [], originMusic) { // console.log(musicInfo.source) return music[musicInfo.source].getPic(musicInfo).promise.catch(err => { if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source) return this.dispatch('list/getOtherSource', musicInfo).then(otherSource => { if (!originMusic) originMusic = musicInfo console.log('find otherSource', otherSource) if (otherSource.length) { for (const item of otherSource) { if (retryedSource.includes(item.source)) continue console.log('try toggle to: ', item.source, item.name, item.singer, item.interval) return getPic.call(this, item, retryedSource, originMusic) } } return Promise.reject(err) }) }) } const getLyric = function(musicInfo, retryedSource = [], originMusic) { return music[musicInfo.source].getLyric(musicInfo).promise.catch(err => { if (!retryedSource.includes(musicInfo.source)) retryedSource.push(musicInfo.source) return this.dispatch('list/getOtherSource', musicInfo).then(otherSource => { if (!originMusic) originMusic = musicInfo console.log('find otherSource', otherSource) if (otherSource.length) { for (const item of otherSource) { if (retryedSource.includes(item.source)) continue console.log('try toggle to: ', item.source, item.name, item.singer, item.interval) return getLyric.call(this, item, retryedSource, originMusic) } } return Promise.reject(err) }) }) } // getters const getters = { list: state => state.listInfo.list, changePlay: satte => satte.changePlay, playInfo(state) { if (state.playMusicInfo == null) return { listId: null, playIndex: -1, playListId: null, listPlayIndex: -1, isPlayList: false, musicInfo: null } const playListId = state.listInfo.id let listId = state.playMusicInfo.listId const isTempPlay = !!state.playMusicInfo.isTempPlay const isPlayList = listId === playListId let playIndex = -1 let listPlayIndex = state.playIndex if (listId != '__temp__') { if (isPlayList) { playIndex = state.listInfo.list.indexOf(state.playMusicInfo.musicInfo) if (!isTempPlay) listPlayIndex = playIndex } else { let list = window.allList[listId] if (list) playIndex = list.list.indexOf(state.playMusicInfo.musicInfo) } } // console.log({ // listId, // playIndex, // playListId, // listPlayIndex, // isPlayList, // isTempPlay, // musicInfo: state.playMusicInfo.musicInfo, // }) return { listId, playIndex, playListId, listPlayIndex, isPlayList, isTempPlay, musicInfo: state.playMusicInfo.musicInfo, } }, isShowPlayerDetail: state => state.isShowPlayerDetail, playMusicInfo: state => state.playMusicInfo, playedList: state => state.playedList, tempPlayList: state => state.tempPlayList, } // actions const actions = { getUrl({ commit, state }, { musicInfo, originMusic, type, isRefresh }) { if (!musicInfo._types[type]) { // 兼容旧版酷我源搜索列表过滤128k音质的bug if (!(musicInfo.source == 'kw' && type == '128k')) return Promise.reject(new Error('该歌曲没有可播放的音频')) // return Promise.reject(new Error('该歌曲没有可播放的音频')) } if (urlRequest && urlRequest.cancelHttp) urlRequest.cancelHttp() if (musicInfo.typeUrl[type] && !isRefresh) return Promise.resolve(musicInfo.typeUrl[type]) try { urlRequest = music[musicInfo.source].getMusicUrl(musicInfo, type) } catch (err) { return Promise.reject(err) } return urlRequest.promise.then(({ url }) => { if (originMusic) commit('setUrl', { musicInfo: originMusic, url, type }) commit('setUrl', { musicInfo, url, type }) urlRequest = null return url }).catch(err => { urlRequest = null return Promise.reject(err) }) }, getPic({ commit, state }, musicInfo) { // if (picRequest && picRequest.cancelHttp) picRequest.cancelHttp() // picRequest = music[musicInfo.source].getPic(musicInfo) return getPic.call(this, musicInfo).then(url => { // picRequest = null commit('getPic', { musicInfo, url }) }).catch(err => { // picRequest = null return Promise.reject(err) }) }, getLrc({ commit, state }, musicInfo) { // if (lrcRequest && lrcRequest.cancelHttp) lrcRequest.cancelHttp() if (musicInfo.lrc && musicInfo.tlrc != null) { if (musicInfo.lrc.startsWith('\ufeff[id:$00000000]')) { let str = musicInfo.lrc.replace('\ufeff[id:$00000000]\n', '') commit('setLrc', { musicInfo, lyric: str, tlyric: musicInfo.tlrc, lxlyric: musicInfo.tlrc }) } else if (musicInfo.lrc.startsWith('[id:$00000000]')) { let str = musicInfo.lrc.replace('[id:$00000000]\n', '') commit('setLrc', { musicInfo, lyric: str, tlyric: musicInfo.tlrc, lxlyric: musicInfo.tlrc }) } if ((musicInfo.lxlrc == null && musicInfo.source != 'kg') || musicInfo.lxlrc != null) { return Promise.resolve() } } // lrcRequest = music[musicInfo.source].getLyric(musicInfo) return getLyric.call(this, musicInfo).then(({ lyric, tlyric, lxlyric }) => { // lrcRequest = null commit('setLrc', { musicInfo, lyric, tlyric, lxlyric }) }).catch(err => { // lrcRequest = null return Promise.reject(err) }) }, async playPrev({ state, rootState, commit, getters }) { const currentListId = state.listInfo.id const currentList = state.listInfo.list if (state.playedList.length) { // 从已播放列表移除播放列表已删除的歌曲 let index for (index = state.playedList.indexOf(state.playMusicInfo) - 1; index > -1; index--) { const playMusicInfo = state.playedList[index] if (playMusicInfo.listId == currentListId && !currentList.includes(playMusicInfo.musicInfo)) { commit('removePlayedList', index) continue } break } if (index > -1) { commit('setPlayMusicInfo', state.playedList[index]) return } } let filteredList = await filterList({ listInfo: state.listInfo, playedList: state.playedList, savePath: rootState.setting.download.savePath, commit, }) if (!filteredList.length) return commit('setPlayMusicInfo', null) const playInfo = getters.playInfo let currentIndex = filteredList.indexOf(currentList[playInfo.listPlayIndex]) if (currentIndex == -1) currentIndex = 0 let nextIndex = currentIndex if (!playInfo.isTempPlay) { switch (rootState.setting.player.togglePlayMethod) { case 'random': nextIndex = getRandom(0, filteredList.length) break case 'listLoop': case 'list': nextIndex = currentIndex === 0 ? filteredList.length - 1 : currentIndex - 1 break case 'singleLoop': break default: nextIndex = -1 return } if (nextIndex < 0) return } commit('setPlayMusicInfo', { musicInfo: filteredList[nextIndex], listId: currentListId, }) }, async playNext({ state, rootState, commit, getters }) { if (state.tempPlayList.length) { const playMusicInfo = state.tempPlayList[0] commit('removeTempPlayList', 0) commit('setPlayMusicInfo', playMusicInfo) return } const currentListId = state.listInfo.id const currentList = state.listInfo.list if (state.playedList.length) { // 从已播放列表移除播放列表已删除的歌曲 let index for (index = state.playedList.indexOf(state.playMusicInfo) + 1; index < state.playedList.length; index++) { const playMusicInfo = state.playedList[index] if (playMusicInfo.listId == currentListId && !currentList.includes(playMusicInfo.musicInfo)) { commit('removePlayedList', index) continue } break } if (index < state.playedList.length) { commit('setPlayMusicInfo', state.playedList[index]) return } } let filteredList = await filterList({ listInfo: state.listInfo, playedList: state.playedList, savePath: rootState.setting.download.savePath, commit, }) if (!filteredList.length) return commit('setPlayMusicInfo', null) const playInfo = getters.playInfo const currentIndex = filteredList.indexOf(currentList[playInfo.listPlayIndex]) let nextIndex = currentIndex switch (rootState.setting.player.togglePlayMethod) { case 'listLoop': nextIndex = currentIndex === filteredList.length - 1 ? 0 : currentIndex + 1 break case 'random': nextIndex = getRandom(0, filteredList.length) break case 'list': nextIndex = currentIndex === filteredList.length - 1 ? -1 : currentIndex + 1 break case 'singleLoop': break default: nextIndex = -1 return } if (nextIndex < 0) return commit('setPlayMusicInfo', { musicInfo: filteredList[nextIndex], listId: currentListId, }) }, } // mitations const mutations = { setUrl(state, datas) { datas.musicInfo.typeUrl = Object.assign({}, datas.musicInfo.typeUrl, { [datas.type]: datas.url }) }, getPic(state, datas) { datas.musicInfo.img = datas.url }, setLrc(state, datas) { datas.musicInfo.lrc = datas.lyric datas.musicInfo.tlrc = datas.tlyric datas.musicInfo.lxlrc = datas.lxlyric }, setList(state, { list, index }) { state.playMusicInfo = { musicInfo: list.list[index], listId: list.id, } state.listInfo = list state.playIndex = index state.changePlay = true // console.log(state.playMusicInfo) if (state.playedList.length) this.commit('player/clearPlayedList') if (state.tempPlayList.length) this.commit('player/clearTempPlayeList') }, setPlayIndex(state, index) { state.playIndex = index }, setChangePlay(state) { state.changePlay = true }, resetChangePlay(state) { state.changePlay = false }, setPlayedList(state, item) { // console.log(item) if (state.playedList.includes(item)) return state.playedList.push(item) }, removePlayedList(state, index) { state.playedList.splice(index, 1) }, clearPlayedList(state) { state.playedList.splice(0, state.playedList.length) }, visiblePlayerDetail(state, visible) { state.isShowPlayerDetail = visible }, setTempPlayList(state, list) { state.tempPlayList.push(...list.map(({ musicInfo, listId }) => ({ musicInfo, listId, isTempPlay: true }))) if (!state.playMusicInfo) this.commit('player/playNext') }, removeTempPlayList(state, index) { state.tempPlayList.splice(index, 1) }, clearTempPlayeList(state) { state.tempPlayList.splice(0, state.tempPlayList.length) }, setPlayMusicInfo(state, playMusicInfo) { let playIndex = state.playIndex if (playMusicInfo == null) { playIndex = -1 } else { let listId = playMusicInfo.listId if (listId != '__temp__' && listId === state.listInfo.id) playIndex = state.listInfo.list.indexOf(state.playMusicInfo.musicInfo) } state.playMusicInfo = playMusicInfo state.playIndex = playIndex state.changePlay = true }, } export default { namespaced: true, state, getters, actions, mutations, }