import music from '@/utils/music' const cache = new Map() const LIST_LOAD_LIMIT = 30 export const TYPES = { setTags: null, setList: null, clearList: null, setListDetail: null, setVisibleListDetail: null, setSelectListInfo: null, setListLoading: null, setListDetailLoading: null, setListEnd: null, setListDetailEnd: null, } for (const key of Object.keys(TYPES)) { TYPES[key] = `list__${key}` } export const getTags = () => (dispatch, getState) => { const state = getState() let source = state.common.setting.songList.source if (state.songList.tags[source]) return Promise.resolve() return music[source].songList.getTags().then(result => dispatch(setTags({ tags: result, source }))) } export const getList = ({ page = 1, isRefresh = false }) => (dispatch, getState) => { const allState = getState() const rootState = allState.common let source = rootState.setting.songList.source let tabId = rootState.setting.songList.tagInfo.id let sortId = rootState.setting.songList.sortId let listKey = `slist__${source}__${sortId}__${tabId}` let pageKey = `slist__${source}__${sortId}__${tabId}__${page}` if (isRefresh && cache.has(listKey)) cache.delete(listKey) if (!cache.has(listKey)) cache.set(listKey, new Map()) const listCache = cache.get(listKey) if (listCache.has(pageKey)) return Promise.resolve(listCache.get(pageKey)).then(result => dispatch(setList({ result, pageKey, listKey, page }))) dispatch(setListEnd(false)) dispatch(setListLoading(true)) return music[source].songList.getList(sortId, tabId, page).then(result => { dispatch(setList({ result, pageKey, listKey, page })) listCache.set(pageKey, result) }).finally(() => { const state = getState().songList if (state.list.pageKey != pageKey) return dispatch(setListLoading(false)) }) } const getListDetailLimit = ({ source, id, page }) => { const listKey = `sdetail__${source}__${id}` const prevPageKey = `sdetail__${source}__${id}__${page - 1}` const tempListKey = `sdetail__${source}__${id}__temp` const listCache = cache.get(listKey) let sourcePage = 0 if (listCache.has(prevPageKey)) { sourcePage = listCache.get(prevPageKey).sourcePage } return music[source].songList.getListDetail(id, sourcePage + 1).then(result => { let p = page if (listCache.has(tempListKey)) { const list = listCache.get(tempListKey) listCache.delete(tempListKey) listCache.set(`sdetail__${source}__${id}__${p}`, { data: { ...result, list: [...list, ...result.list.splice(0, LIST_LOAD_LIMIT - list.length)], page: p, limit: LIST_LOAD_LIMIT, }, sourcePage, }) p++ } sourcePage++ do { if (result.list.length < LIST_LOAD_LIMIT && sourcePage < Math.ceil(result.total / result.limit)) { listCache.set(tempListKey, result.list.splice(0, LIST_LOAD_LIMIT)) break } listCache.set(`sdetail__${source}__${id}__${p}`, { data: { ...result, list: result.list.splice(0, LIST_LOAD_LIMIT), page: p, limit: LIST_LOAD_LIMIT, }, sourcePage, }) p++ } while (result.list.length > 0) return listCache.get(`sdetail__${source}__${id}__${page}`).data }) } export const getListDetail = ({ id, page, isRefresh = false }) => (dispatch, getState) => { const allState = getState() const rootState = allState.common let source = rootState.setting.songList.source let listKey = `sdetail__${source}__${id}` let pageKey = `sdetail__${source}__${id}__${page}` if (isRefresh && cache.has(listKey)) cache.delete(listKey) if (!cache.has(listKey)) cache.set(listKey, new Map()) const listCache = cache.get(listKey) if (listCache.has(pageKey)) { return Promise.resolve(listCache.get(pageKey).data).then(result => dispatch(setListDetail({ result, listKey, pageKey, source, id, page }))) } dispatch(setListDetailEnd(false)) dispatch(setListDetailLoading(true)) return getListDetailLimit({ source, id, page }).then(result => { dispatch(setListDetail({ result, listKey, pageKey, source, id, page })) // listCache.set(pageKey, result) }).finally(() => { const state = getState().songList if (state.listDetail.pageKey != pageKey) return dispatch(setListDetailLoading(false)) }) } export const getListDetailAll = id => (dispatch, getState) => { const allState = getState() const rootState = allState.common let source = rootState.setting.songList.source let listKey = `sdetail__${source}__${id}` const listCache = cache.get(listKey) const loadData = (id, page) => { let pageKey = `sdetail__${source}__${id}__${page}` return listCache.has(pageKey) ? Promise.resolve(listCache.get(pageKey).data) : getListDetailLimit({ source, id, page }).then(result => { // listCache.set(pageKey, result) return result }) } return loadData(id, 1).then(result => { if (result.total <= result.limit) return result.list let maxPage = Math.ceil(result.total / result.limit) const loadDetail = (loadPage = 2) => { return loadPage == maxPage ? loadData(id, loadPage).then(result => result.list) : loadData(id, loadPage).then(result1 => loadDetail(++loadPage).then(result2 => [...result1.list, ...result2])) } return loadDetail().then(result2 => [...result.list, ...result2]) }) } export const setVisibleListDetail = isShow => { return { type: TYPES.setVisibleListDetail, payload: isShow, } } export const setSelectListInfo = info => { return { type: TYPES.setSelectListInfo, payload: info, } } export const setTags = ({ tags, source }) => { return { type: TYPES.setTags, payload: { tags, source }, } } export const setList = ({ result, pageKey, listKey, page }) => { return { type: TYPES.setList, payload: { result, pageKey, listKey, page }, } } export const clearList = () => { return { type: TYPES.clearList } } export const setListLoading = isLoading => { return { type: TYPES.setListLoading, payload: isLoading, } } export const setListDetailLoading = isLoading => { return { type: TYPES.setListDetailLoading, payload: isLoading, } } export const setListEnd = isEnd => { return { type: TYPES.setListEnd, payload: isEnd, } } export const setListDetailEnd = isEnd => { return { type: TYPES.setListDetailEnd, payload: isEnd, } } export const setListDetail = ({ result, pageKey, listKey, source, id, page }) => { return { type: TYPES.setListDetail, payload: { result, pageKey, listKey, source, id, page }, } }