import { action as playerAction } from '@/store/modules/player' import { action as commonAction } from '@/store/modules/common' import { findMusic } from '@/utils/music' import { getAllListData, saveList, removeList, saveListAllSort, clearMusicUrlAndLyric, saveListScrollPosition, saveListSort, } from '@/utils/tools' import { list as listSync } from '@/plugins/sync' import { log } from '@/utils/log' export const TYPES = { initList: null, setList: null, listAdd: null, listMove: null, listAddMultiple: null, listMoveMultiple: null, listRemove: null, listRemoveMultiple: null, listClear: null, updateMusicInfo: null, createUserList: null, removeUserList: null, setUserListName: null, setUserListPosition: null, setMusicPosition: null, setOtherSource: null, clearCache: null, jumpPosition: null, setSyncList: null, } for (const key of Object.keys(TYPES)) { TYPES[key] = `list__${key}` } export const initList = listData => async(dispatch, getState) => { let defaultList let loveList let userList let listPosition let listSort if (listData) { defaultList = listData.defaultList loveList = listData.loveList userList = listData.userList listSort = listData.listSort || {} } else { try { listData = await getAllListData() } catch (err) { log.error(err.stack) return } defaultList = listData.defaultList loveList = listData.loveList userList = listData.userList listPosition = listData.listPosition listSort = listData.listSort } global.listScrollPosition = listPosition || {} global.listSort = listSort let isNeedSaveSortInfo = false userList.sort((a, b) => { if (listSort[a.id] == null) return listSort[b.id] == null ? -1 : 1 return listSort[b.id] == null ? 1 : listSort[a.id] - listSort[b.id] }) userList.forEach((list, index) => { if (listSort[list.id] == null) { isNeedSaveSortInfo = true listSort[list.id] = index delete list.location } }) if (isNeedSaveSortInfo) await saveListAllSort(listSort) // console.log(userList.map(l => `${listSort[l.id]} - ${l.name}`)) dispatch({ type: TYPES.initList, payload: { defaultList, loveList, userList }, }) // if (listData.isSync) { // const keys = Object.keys(global.allList) // dispatch(playerAction.checkPlayList(keys)) // saveList(keys) // } else { // listSync.sendListAction('init_list', { defaultList, loveList, userList }) // } } export const setSyncList = ({ defaultList, loveList, userList }) => async(dispatch, getState) => { const state = getState() const userListIds = userList.map(l => l.id) const removeUserListIds = state.list.userList.filter(l => !userListIds.includes(l.id)).map(l => l.id) if (removeUserListIds.includes(state.common.setting.list.prevSelectListId)) { dispatch(commonAction.setPrevSelectListId(state.list.defaultList.id)) } dispatch({ type: TYPES.setSyncList, payload: { defaultList, loveList, userList }, }) await removeList(removeUserListIds) const listPosition = {} userList.forEach((list, index) => { listPosition[list.id] = index delete list.location }) global.listScrollPosition = listPosition await saveListAllSort(listPosition) dispatch(playerAction.checkPlayList([...Object.keys(global.allList), ...removeUserListIds])) saveList([defaultList, loveList, ...userList]) } export const setList = ({ id, list, name, location, source, sourceListId, isSync }) => async(dispatch, getState) => { const targetList = global.allList[id] if (targetList) { if (name && targetList.name === name) { if (!isSync) listSync.sendListAction('set_list', { id, list, name, location, source, sourceListId }) dispatch({ type: TYPES.listClear, payload: id, }) dispatch(listAddMultiple({ id, list, isSync: true })) return } id += '_' + Math.random() } if (!isSync) listSync.sendListAction('set_list', { id, list, name, location, source, sourceListId }) await dispatch(createUserList({ id, list, name, location, source, sourceListId, isSync: true })) } export const listAdd = ({ musicInfo, id, addMusicLocationType, isSync }) => (dispatch, getState) => { if (!addMusicLocationType) addMusicLocationType = getState().common.setting.list.addMusicLocationType if (!isSync) { listSync.sendListAction('list_add', { id, musicInfo, addMusicLocationType }) } dispatch({ type: TYPES.listAdd, payload: { musicInfo, id, addMusicLocationType, }, }) dispatch(playerAction.checkPlayList([id])) saveList(global.allList[id]) } export const listMove = ({ fromId, musicInfo, toId, isSync }) => (dispatch, getState) => { if (!isSync) { listSync.sendListAction('list_move', { fromId, musicInfo, toId }) } dispatch({ type: TYPES.listMove, payload: { fromId, musicInfo, toId }, }) dispatch(playerAction.checkPlayList([fromId, toId])) saveList([global.allList[fromId], global.allList[toId]]) } export const listAddMultiple = ({ id, list, addMusicLocationType, isSync }) => (dispatch, getState) => { if (!addMusicLocationType) addMusicLocationType = getState().common.setting.list.addMusicLocationType if (!isSync) { listSync.sendListAction('list_add_multiple', { id, list, addMusicLocationType }) } dispatch({ type: TYPES.listAddMultiple, payload: { id, list, addMusicLocationType }, }) dispatch(playerAction.checkPlayList([id])) saveList(global.allList[id]) } export const listMoveMultiple = ({ fromId, toId, list, isSync }) => (dispatch, getState) => { if (!isSync) { listSync.sendListAction('list_move_multiple', { fromId, toId, list }) } dispatch({ type: TYPES.listRemoveMultiple, payload: { id: fromId, ids: list.map(s => s.songmid) }, }) dispatch({ type: TYPES.listAddMultiple, payload: { id: toId, list }, }) dispatch(playerAction.checkPlayList([fromId, toId])) saveList([global.allList[fromId], global.allList[toId]]) } export const listRemove = ({ listId, id, isSync }) => (dispatch, getState) => { if (!isSync) { listSync.sendListAction('list_remove', { listId, id }) } dispatch({ type: TYPES.listRemove, payload: { listId, id }, }) dispatch(playerAction.checkPlayList([listId])) saveList(global.allList[listId]) } export const listRemoveMultiple = ({ listId, ids, isSync }) => (dispatch, getState) => { if (!isSync) { listSync.sendListAction('list_remove_multiple', { listId, ids }) } dispatch({ type: TYPES.listRemoveMultiple, payload: { listId, ids }, }) dispatch(playerAction.checkPlayList([listId])) saveList(global.allList[listId]) } export const listClear = ({ id, isSync }) => (dispatch, getState) => { if (!isSync) { listSync.sendListAction('list_clear', { id }) } dispatch({ type: TYPES.listClear, payload: id, }) dispatch(playerAction.checkPlayList([id])) saveList(global.allList[id]) } export const updateMusicInfo = ({ listId, id, data, isSync }) => (dispatch, getState) => { if (!isSync) { listSync.sendListAction('update_music_info', { listId, id, data }) } dispatch({ type: TYPES.updateMusicInfo, payload: { listId, id, data }, }) saveList(global.allList[listId]) } export const createUserList = ({ name, id = `userlist_${Date.now()}`, list = [], source, sourceListId, isSync }) => async(dispatch, getState) => { if (!isSync) { listSync.sendListAction('create_user_list', { name, id, list, source, sourceListId }) } dispatch({ type: TYPES.createUserList, payload: { name, id, source, sourceListId }, }) dispatch(listAddMultiple({ id, list, isSync: true })) await saveList(global.allList[id]) const state = getState() await saveListSort(id, state.list.userList.length) await saveListScrollPosition(id, 0) } export const removeUserList = ({ id, isSync }) => async(dispatch, getState) => { if (!isSync) { listSync.sendListAction('remove_user_list', { id }) } const { list, common } = getState() const index = list.userList.findIndex(l => l.id === id) if (index < 0) return if (common.setting.list.prevSelectListId == id) { dispatch(commonAction.setPrevSelectListId(list.defaultList.id)) } dispatch({ type: TYPES.removeUserList, payload: index, }) await removeList(id) console.log(common.setting.list.prevSelectListId, id) dispatch(playerAction.checkPlayList([id])) } const getOtherSourcePromises = new Map() export const getOtherSource = ({ musicInfo, id }) => (dispatch, getState) => { if (musicInfo.otherSource?.length) return Promise.resolve(musicInfo.otherSource) let key = `${musicInfo.source}_${musicInfo.songmid}` if (getOtherSourcePromises.has(key)) return getOtherSourcePromises.get(key) const promise = findMusic(musicInfo).then(otherSource => { const targetList = global.allList[id] if (targetList) { const index = targetList.indexOf(musicInfo) if (index > -1) { dispatch({ type: TYPES.setOtherSource, payload: { otherSource, id, index }, }) } } if (getOtherSourcePromises.has(key)) getOtherSourcePromises.delete(key) return otherSource }) getOtherSourcePromises.set(key, promise) return promise } export const setUserListName = ({ id, name, isSync }) => async(dispatch, getState) => { if (!isSync) { listSync.sendListAction('set_user_list_name', { id, name }) } dispatch({ type: TYPES.setUserListName, payload: { id, name }, }) const targetList = global.allList[id] await saveList(targetList) } export const setUserListPosition = ({ id, position }) => async(dispatch, getState) => { dispatch({ type: TYPES.setUserListPosition, payload: { id, position }, }) await saveList(global.allList[id]) } export const setMusicPosition = ({ id, position, list, isSync }) => async(dispatch, getState) => { if (!isSync) { listSync.sendListAction('set_music_position', { id, position, list }) } // const targetList = global.allList[id] // if (!targetList) return dispatch({ type: TYPES.listRemoveMultiple, payload: { listId: id, ids: list.map(m => m.songmid) }, }) dispatch({ type: TYPES.setMusicPosition, payload: { id, position, list }, }) dispatch(playerAction.checkPlayList([id])) await saveList(global.allList[id]) } export const setJumpPosition = isJumpPosition => async(dispatch, getState) => { dispatch({ type: TYPES.jumpPosition, payload: isJumpPosition, }) } export const clearCache = () => async(dispatch, getState) => { dispatch({ type: TYPES.clearCache, payload: null, }) await saveList(Object.values(global.allList)) await clearMusicUrlAndLyric() }