mirror of
https://github.com/ikun0014/lx-music-mobile.git
synced 2025-07-04 01:52:09 +08:00
lint fix
This commit is contained in:
parent
4bbf3f51f9
commit
feeef4f6d2
@ -16,7 +16,7 @@
|
|||||||
"pack:android:debug": "./gradlew assembleDebug",
|
"pack:android:debug": "./gradlew assembleDebug",
|
||||||
"pack": "npm run pack:android",
|
"pack": "npm run pack:android",
|
||||||
"pack:android": "cd android && gradlew.bat assembleRelease",
|
"pack:android": "cd android && gradlew.bat assembleRelease",
|
||||||
"clear": "react-native clean-project",
|
"clear": "cd android && gradlew.bat clean",
|
||||||
"build:theme": "node src/theme/themes/createThemes.js",
|
"build:theme": "node src/theme/themes/createThemes.js",
|
||||||
"publish": "node publish"
|
"publish": "node publish"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useRef, useEffect } from 'react'
|
import React, { useState, useRef, useEffect } from 'react'
|
||||||
import { View } from 'react-native'
|
import { View } from 'react-native'
|
||||||
import Input, { InputType } from '@/components/common/Input'
|
import Input, { type InputType } from '@/components/common/Input'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle } from '@/utils/tools'
|
||||||
import { useI18n } from '@/lang'
|
import { useI18n } from '@/lang'
|
||||||
import { createUserList } from '@/core/list'
|
import { createUserList } from '@/core/list'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react'
|
import React, { forwardRef, useImperativeHandle, useRef, useState } from 'react'
|
||||||
import Dialog, { DialogType } from '@/components/common/Dialog'
|
import Dialog, { type DialogType } from '@/components/common/Dialog'
|
||||||
import { toast } from '@/utils/tools'
|
import { toast } from '@/utils/tools'
|
||||||
import Title from './Title'
|
import Title from './Title'
|
||||||
import List from './List'
|
import List from './List'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useRef, useImperativeHandle, forwardRef, useState } from 'react'
|
import React, { useRef, useImperativeHandle, forwardRef, useState } from 'react'
|
||||||
import Modal, { MusicMultiAddModalType as ModalType, SelectInfo } from './MusicMultiAddModal'
|
import Modal, { type MusicMultiAddModalType as ModalType, type SelectInfo } from './MusicMultiAddModal'
|
||||||
|
|
||||||
export interface MusicMultiAddModalType {
|
export interface MusicMultiAddModalType {
|
||||||
show: (info: SelectInfo) => void
|
show: (info: SelectInfo) => void
|
||||||
|
@ -113,10 +113,10 @@ export default forwardRef<MultipleModeBarType, MultipleModeBarProps>(({ onSelect
|
|||||||
return (
|
return (
|
||||||
<Animated.View style={animaStyle}>
|
<Animated.View style={animaStyle}>
|
||||||
<View style={styles.switchBtn}>
|
<View style={styles.switchBtn}>
|
||||||
<Button onPress={() => onSwitchMode('single')} style={{ ...styles.btn, backgroundColor: selectMode == 'single' ? theme['c-button-background'] : 'rgba(0,0,0,0)' }}>
|
<Button onPress={() => { onSwitchMode('single') }} style={{ ...styles.btn, backgroundColor: selectMode == 'single' ? theme['c-button-background'] : 'rgba(0,0,0,0)' }}>
|
||||||
<Text color={theme['c-button-font']}>{global.i18n.t('list_select_single')}</Text>
|
<Text color={theme['c-button-font']}>{global.i18n.t('list_select_single')}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
<Button onPress={() => onSwitchMode('range')} style={{ ...styles.btn, backgroundColor: selectMode == 'range' ? theme['c-button-background'] : 'rgba(0,0,0,0)' }}>
|
<Button onPress={() => { onSwitchMode('range') }} style={{ ...styles.btn, backgroundColor: selectMode == 'range' ? theme['c-button-background'] : 'rgba(0,0,0,0)' }}>
|
||||||
<Text color={theme['c-button-font']}>{global.i18n.t('list_select_range')}</Text>
|
<Text color={theme['c-button-font']}>{global.i18n.t('list_select_range')}</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useState, forwardRef, useImperativeHandle, Ref } from 'react'
|
import React, { useState, forwardRef, useImperativeHandle, type Ref } from 'react'
|
||||||
import { FlatList, FlatListProps } from 'react-native'
|
import { FlatList, type FlatListProps } from 'react-native'
|
||||||
|
|
||||||
// import InsetShadow from 'react-native-inset-shadow'
|
// import InsetShadow from 'react-native-inset-shadow'
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { useRef, useImperativeHandle, forwardRef, useState, useEffect } from 'react'
|
import React, { useRef, useImperativeHandle, forwardRef, useState, useEffect } from 'react'
|
||||||
import ConfirmAlert, { ConfirmAlertType } from '@/components/common/ConfirmAlert'
|
import ConfirmAlert, { type ConfirmAlertType } from '@/components/common/ConfirmAlert'
|
||||||
import Text from '@/components/common/Text'
|
import Text from '@/components/common/Text'
|
||||||
import { View } from 'react-native'
|
import { View } from 'react-native'
|
||||||
import Input, { InputType } from '@/components/common/Input'
|
import Input, { type InputType } from '@/components/common/Input'
|
||||||
import { createStyle, toast } from '@/utils/tools'
|
import { createStyle, toast } from '@/utils/tools'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
import { cancelTimeoutExit, getTimeoutExitTime, onTimeUpdate, startTimeoutExit, stopTimeoutExit, useTimeoutExitTimeInfo } from '@/core/player/timeoutExit'
|
import { cancelTimeoutExit, getTimeoutExitTime, onTimeUpdate, startTimeoutExit, stopTimeoutExit, useTimeoutExitTimeInfo } from '@/core/player/timeoutExit'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
import React, { useMemo, useRef, useImperativeHandle, forwardRef } from 'react'
|
import React, { useMemo, useRef, useImperativeHandle, forwardRef } from 'react'
|
||||||
import { Pressable, PressableProps, StyleSheet, View, ViewProps } from 'react-native'
|
import { Pressable, type PressableProps, StyleSheet, type View, type ViewProps } from 'react-native'
|
||||||
// import { AppColors } from '@/theme'
|
// import { AppColors } from '@/theme'
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React, { forwardRef, memo, useImperativeHandle, useRef, useState } from 'react'
|
import React, { forwardRef, memo, useImperativeHandle, useRef, useState } from 'react'
|
||||||
import { View, TouchableOpacity } from 'react-native'
|
import { View, TouchableOpacity } from 'react-native'
|
||||||
import Input, { InputType } from '@/components/common/Input'
|
import Input, { type InputType } from '@/components/common/Input'
|
||||||
import Text from '@/components/common/Text'
|
import Text from '@/components/common/Text'
|
||||||
import { Icon } from '@/components/common/Icon'
|
import { Icon } from '@/components/common/Icon'
|
||||||
import StatusBar from '@/components/common/StatusBar'
|
import StatusBar from '@/components/common/StatusBar'
|
||||||
import ConfirmAlert, { ConfirmAlertType } from '@/components/common/ConfirmAlert'
|
import ConfirmAlert, { type ConfirmAlertType } from '@/components/common/ConfirmAlert'
|
||||||
import { createStyle, toast } from '@/utils/tools'
|
import { createStyle, toast } from '@/utils/tools'
|
||||||
import { mkdir } from '@/utils/fs'
|
import { mkdir } from '@/utils/fs'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
|
@ -4,7 +4,7 @@ import { createStyle } from '@/utils/tools'
|
|||||||
import React, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import { View, FlatList } from 'react-native'
|
import { View, FlatList } from 'react-native'
|
||||||
|
|
||||||
import ListItem, { PathItem } from './ListItem'
|
import ListItem, { type PathItem } from './ListItem'
|
||||||
|
|
||||||
|
|
||||||
export default ({ list, onSetPath, toParentDir }: {
|
export default ({ list, onSetPath, toParentDir }: {
|
||||||
|
@ -2,9 +2,9 @@ import React, { useState, useRef, forwardRef, useImperativeHandle } from 'react'
|
|||||||
// import { StyleSheet, View, Text, StatusBar, ScrollView } from 'react-native'
|
// import { StyleSheet, View, Text, StatusBar, ScrollView } from 'react-native'
|
||||||
|
|
||||||
// import { useGetter, useDispatch } from '@/store'
|
// import { useGetter, useDispatch } from '@/store'
|
||||||
import List, { ListType } from './List'
|
import List, { type ListType } from './List'
|
||||||
|
|
||||||
import ConfirmAlert, { ConfirmAlertType } from '@/components/common/ConfirmAlert'
|
import ConfirmAlert, { type ConfirmAlertType } from '@/components/common/ConfirmAlert'
|
||||||
import { checkStoragePermissions, requestStoragePermission, toast } from '@/utils/tools'
|
import { checkStoragePermissions, requestStoragePermission, toast } from '@/utils/tools'
|
||||||
import { useI18n } from '@/lang'
|
import { useI18n } from '@/lang'
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import React, { useMemo, useRef, useImperativeHandle, forwardRef, useState } fro
|
|||||||
import { View, TouchableWithoutFeedback } from 'react-native'
|
import { View, TouchableWithoutFeedback } from 'react-native'
|
||||||
import { useDimensions } from '@/utils/hooks'
|
import { useDimensions } from '@/utils/hooks'
|
||||||
|
|
||||||
import Modal, { ModalType } from '@/components/common/Modal'
|
import Modal, { type ModalType } from '@/components/common/Modal'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle } from '@/utils/tools'
|
||||||
// import { useGetter } from '@/store'
|
// import { useGetter } from '@/store'
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { useRef, forwardRef } from 'react'
|
import React, { useRef, forwardRef } from 'react'
|
||||||
// import { View } from 'react-native'
|
// import { View } from 'react-native'
|
||||||
|
|
||||||
import Panel, { PanelType } from './Panel'
|
import Panel, { type PanelType } from './Panel'
|
||||||
import Button, { BtnType } from '@/components/common/Button'
|
import Button, { type BtnType } from '@/components/common/Button'
|
||||||
|
|
||||||
|
|
||||||
export interface DorpDownPanelProps {
|
export interface DorpDownPanelProps {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createIconSetFromIcoMoon } from 'react-native-vector-icons'
|
import { createIconSetFromIcoMoon } from 'react-native-vector-icons'
|
||||||
import icoMoonConfig from '@/resources/fonts/selection.json'
|
import icoMoonConfig from '@/resources/fonts/selection.json'
|
||||||
import { scaleSizeW } from '@/utils/pixelRatio'
|
import { scaleSizeW } from '@/utils/pixelRatio'
|
||||||
import { ComponentProps } from 'react'
|
import { type ComponentProps } from 'react'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
|
|
||||||
// import IconAntDesign from 'react-native-vector-icons/AntDesign'
|
// import IconAntDesign from 'react-native-vector-icons/AntDesign'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useRef, useImperativeHandle, forwardRef, useCallback } from 'react'
|
import React, { useRef, useImperativeHandle, forwardRef, useCallback } from 'react'
|
||||||
import { TextInput, View, TouchableOpacity, StyleSheet, TextInputProps } from 'react-native'
|
import { TextInput, View, TouchableOpacity, StyleSheet, type TextInputProps } from 'react-native'
|
||||||
import { Icon } from '@/components/common/Icon'
|
import { Icon } from '@/components/common/Icon'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle } from '@/utils/tools'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { memo } from 'react'
|
import React, { memo } from 'react'
|
||||||
|
|
||||||
import Slider, { SliderProps as _SliderProps } from '@react-native-community/slider'
|
import Slider, { type SliderProps as _SliderProps } from '@react-native-community/slider'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle } from '@/utils/tools'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { memo, useMemo } from 'react'
|
import React, { memo, useMemo } from 'react'
|
||||||
import { View, Pressable, GestureResponderEvent } from 'react-native'
|
import { View, Pressable, type GestureResponderEvent } from 'react-native'
|
||||||
import { useLayout } from '@/utils/hooks'
|
import { useLayout } from '@/utils/hooks'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle } from '@/utils/tools'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
|
@ -143,7 +143,7 @@ export const getListDetailAll = async(id: string, isRefresh = false): Promise<LX
|
|||||||
if (pageCache) return pageCache.data
|
if (pageCache) return pageCache.data
|
||||||
return getListLimit(source, bangId, page)
|
return getListLimit(source, bangId, page)
|
||||||
}
|
}
|
||||||
return loadData(1).then(result => {
|
return loadData(1).then(async result => {
|
||||||
if (result.total <= result.limit) return result.list
|
if (result.total <= result.limit) return result.list
|
||||||
|
|
||||||
let maxPage = Math.ceil(result.total / result.limit)
|
let maxPage = Math.ceil(result.total / result.limit)
|
||||||
|
@ -355,7 +355,7 @@ export const getOnlineOtherSourceLyricInfo = async({ musicInfos, onToggleSource,
|
|||||||
reqPromise = Promise.reject(err)
|
reqPromise = Promise.reject(err)
|
||||||
}
|
}
|
||||||
retryedSource.includes(musicInfo.source)
|
retryedSource.includes(musicInfo.source)
|
||||||
return reqPromise.then((lyricInfo: LX.Music.LyricInfo) => {
|
return reqPromise.then(async(lyricInfo: LX.Music.LyricInfo) => {
|
||||||
return existTimeExp.test(lyricInfo.lyric) ? {
|
return existTimeExp.test(lyricInfo.lyric) ? {
|
||||||
lyricInfo,
|
lyricInfo,
|
||||||
musicInfo,
|
musicInfo,
|
||||||
@ -389,7 +389,7 @@ export const handleGetOnlineLyricInfo = async({ musicInfo, onToggleSource, isRef
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
reqPromise = Promise.reject(err)
|
reqPromise = Promise.reject(err)
|
||||||
}
|
}
|
||||||
return reqPromise.then((lyricInfo: LX.Music.LyricInfo) => {
|
return reqPromise.then(async(lyricInfo: LX.Music.LyricInfo) => {
|
||||||
return existTimeExp.test(lyricInfo.lyric) ? {
|
return existTimeExp.test(lyricInfo.lyric) ? {
|
||||||
musicInfo,
|
musicInfo,
|
||||||
lyricInfo,
|
lyricInfo,
|
||||||
|
@ -80,7 +80,7 @@ const getMusicPlayUrl = async(musicInfo: LX.Music.MusicInfo | LX.Download.ListIt
|
|||||||
if (global.lx.isPlayedStop || diffCurrentMusicInfo(musicInfo)) return null
|
if (global.lx.isPlayedStop || diffCurrentMusicInfo(musicInfo)) return null
|
||||||
|
|
||||||
return url
|
return url
|
||||||
}).catch(err => {
|
}).catch(async err => {
|
||||||
// console.log('err', err.message)
|
// console.log('err', err.message)
|
||||||
if (global.lx.isPlayedStop ||
|
if (global.lx.isPlayedStop ||
|
||||||
diffCurrentMusicInfo(musicInfo) ||
|
diffCurrentMusicInfo(musicInfo) ||
|
||||||
|
@ -216,7 +216,7 @@ export const getListDetailAll = async(source: LX.OnlineSource, id: string, isRef
|
|||||||
if (pageCache) return pageCache.data
|
if (pageCache) return pageCache.data
|
||||||
return getListDetailLimit(source, id, page)
|
return getListDetailLimit(source, id, page)
|
||||||
}
|
}
|
||||||
return loadData(1).then(result => {
|
return loadData(1).then(async result => {
|
||||||
if (result.total <= result.limit) return result.list
|
if (result.total <= result.limit) return result.list
|
||||||
|
|
||||||
let maxPage = Math.ceil(result.total / result.limit)
|
let maxPage = Math.ceil(result.total / result.limit)
|
||||||
|
@ -124,7 +124,7 @@ export const useLrcSet = () => {
|
|||||||
setLines(lines)
|
setLines(lines)
|
||||||
}
|
}
|
||||||
lrcTools.addSetLyricHook(callback)
|
lrcTools.addSetLyricHook(callback)
|
||||||
return () => lrcTools.removeSetLyricHook(callback)
|
return () => { lrcTools.removeSetLyricHook(callback) }
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
|
@ -76,7 +76,7 @@ const registerPlaybackService = async() => {
|
|||||||
global.app_event.setProgress(position)
|
global.app_event.setProgress(position)
|
||||||
})
|
})
|
||||||
|
|
||||||
TrackPlayer.addEventListener(TPEvent.PlaybackState, info => {
|
TrackPlayer.addEventListener(TPEvent.PlaybackState, async info => {
|
||||||
if (global.lx.gettingUrlId || isTempId()) return
|
if (global.lx.gettingUrlId || isTempId()) return
|
||||||
// let currentIsPlaying = false
|
// let currentIsPlaying = false
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ const codeAuth = async(urlInfo: LX.Sync.UrlInfo, serverId: string, authCode: str
|
|||||||
|
|
||||||
const keyAuth = async(urlInfo: LX.Sync.UrlInfo, keyInfo: LX.Sync.KeyInfo) => {
|
const keyAuth = async(urlInfo: LX.Sync.UrlInfo, keyInfo: LX.Sync.KeyInfo) => {
|
||||||
const msg = aesEncrypt(SYNC_CODE.authMsg + await getDeviceName(), keyInfo.key)
|
const msg = aesEncrypt(SYNC_CODE.authMsg + await getDeviceName(), keyInfo.key)
|
||||||
return request(`${urlInfo.httpProtocol}//${urlInfo.hostPath}/ah`, { headers: { i: keyInfo.clientId, m: msg } }).then(({ text, code }) => {
|
return request(`${urlInfo.httpProtocol}//${urlInfo.hostPath}/ah`, { headers: { i: keyInfo.clientId, m: msg } }).then(async({ text, code }) => {
|
||||||
if (code != 200) throw new Error(SYNC_CODE.authFailed)
|
if (code != 200) throw new Error(SYNC_CODE.authFailed)
|
||||||
|
|
||||||
let msg
|
let msg
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useRef } from 'react'
|
import React, { useEffect, useRef } from 'react'
|
||||||
import { filterList, getHotComment } from './utils'
|
import { filterList, getHotComment } from './utils'
|
||||||
import music from '@/utils/musicSdk'
|
import music from '@/utils/musicSdk'
|
||||||
import List, { ListType } from './components/List'
|
import List, { type ListType } from './components/List'
|
||||||
const limit = 15
|
const limit = 15
|
||||||
|
|
||||||
export default ({ musicInfo, onUpdateTotal }: {
|
export default ({ musicInfo, onUpdateTotal }: {
|
||||||
|
@ -52,6 +52,7 @@ const CommentFloor = memo(({ comment, isLast }: {
|
|||||||
<Text style={styles.likedCount} size={12} color={ theme['c-450'] }>{comment.likedCount}</Text>
|
<Text style={styles.likedCount} size={12} color={ theme['c-450'] }>{comment.likedCount}</Text>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useMemo, useRef, useImperativeHandle, forwardRef, useState } from 'react'
|
import React, { useMemo, useRef, useImperativeHandle, forwardRef, useState } from 'react'
|
||||||
import { useI18n } from '@/lang'
|
import { useI18n } from '@/lang'
|
||||||
import Menu, { MenuType, Position } from '@/components/common/Menu'
|
import Menu, { type MenuType, type Position } from '@/components/common/Menu'
|
||||||
|
|
||||||
export interface SelectInfo {
|
export interface SelectInfo {
|
||||||
listId: string
|
listId: string
|
||||||
|
@ -18,7 +18,7 @@ export default forwardRef<MusicListType, {}>((props, ref) => {
|
|||||||
const listRef = useRef<OnlineListType>(null)
|
const listRef = useRef<OnlineListType>(null)
|
||||||
const isUnmountedRef = useRef(false)
|
const isUnmountedRef = useRef(false)
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
loadList(source, id) {
|
async loadList(source, id) {
|
||||||
const listDetailInfo = boardState.listDetailInfo
|
const listDetailInfo = boardState.listDetailInfo
|
||||||
listRef.current?.setList([])
|
listRef.current?.setList([])
|
||||||
if (listDetailInfo.id == id && listDetailInfo.source == source && listDetailInfo.list.length) {
|
if (listDetailInfo.id == id && listDetailInfo.source == source && listDetailInfo.list.length) {
|
||||||
|
@ -37,7 +37,7 @@ export default forwardRef<ActiveListType, ActiveListProps>(({ onShowSearchBar },
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void getListPrevSelectId().then((id) => {
|
void getListPrevSelectId().then((id) => {
|
||||||
void setActiveList(id)
|
setActiveList(id)
|
||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useMemo, useRef, useImperativeHandle, forwardRef, useState } from 'react'
|
import React, { useMemo, useRef, useImperativeHandle, forwardRef, useState } from 'react'
|
||||||
import { useI18n } from '@/lang'
|
import { useI18n } from '@/lang'
|
||||||
import Menu, { MenuType, Position } from '@/components/common/Menu'
|
import Menu, { type MenuType, type Position } from '@/components/common/Menu'
|
||||||
|
|
||||||
export interface SelectInfo {
|
export interface SelectInfo {
|
||||||
musicInfo: LX.Music.MusicInfo
|
musicInfo: LX.Music.MusicInfo
|
||||||
|
@ -18,7 +18,7 @@ export default forwardRef<MusicListType, {}>((props, ref) => {
|
|||||||
const searchInfoRef = useRef<{ text: string, source: Source }>({ text: '', source: 'kw' })
|
const searchInfoRef = useRef<{ text: string, source: Source }>({ text: '', source: 'kw' })
|
||||||
const isUnmountedRef = useRef(false)
|
const isUnmountedRef = useRef(false)
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
loadList(text, source) {
|
async loadList(text, source) {
|
||||||
// const listDetailInfo = searchMusicState.listDetailInfo
|
// const listDetailInfo = searchMusicState.listDetailInfo
|
||||||
listRef.current?.setList([], source == 'all')
|
listRef.current?.setList([], source == 'all')
|
||||||
if (searchMusicState.searchText == text && searchMusicState.source == source && searchMusicState.listInfos[searchMusicState.source]!.list.length) {
|
if (searchMusicState.searchText == text && searchMusicState.source == source && searchMusicState.listInfos[searchMusicState.source]!.list.length) {
|
||||||
|
@ -19,7 +19,7 @@ export default forwardRef<MusicListType, {}>((props, ref) => {
|
|||||||
const searchInfoRef = useRef<{ text: string, source: Source }>({ text: '', source: 'kw' })
|
const searchInfoRef = useRef<{ text: string, source: Source }>({ text: '', source: 'kw' })
|
||||||
const isUnmountedRef = useRef(false)
|
const isUnmountedRef = useRef(false)
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
loadList(text, source) {
|
async loadList(text, source) {
|
||||||
// const listDetailInfo = searchSonglistState.listDetailInfo
|
// const listDetailInfo = searchSonglistState.listDetailInfo
|
||||||
listRef.current?.setList([], source == 'all')
|
listRef.current?.setList([], source == 'all')
|
||||||
if (searchSonglistState.searchText == text && searchSonglistState.source == source && searchSonglistState.listInfos[searchSonglistState.source]!.list.length) {
|
if (searchSonglistState.searchText == text && searchSonglistState.source == source && searchSonglistState.listInfos[searchSonglistState.source]!.list.length) {
|
||||||
|
@ -31,7 +31,7 @@ const Item = ({ position, label }: {
|
|||||||
}) => {
|
}) => {
|
||||||
const isActive = useActive(position)
|
const isActive = useActive(position)
|
||||||
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
||||||
return <CheckBox marginRight={8} check={isActive} label={label} onChange={() => updateSetting({ 'common.drawerLayoutPosition': position })} need />
|
return <CheckBox marginRight={8} check={isActive} label={label} onChange={() => { updateSetting({ 'common.drawerLayoutPosition': position }) }} need />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(() => {
|
export default memo(() => {
|
||||||
|
@ -21,7 +21,7 @@ const Item = ({ id, name }: {
|
|||||||
}) => {
|
}) => {
|
||||||
const isActive = useActive(id)
|
const isActive = useActive(id)
|
||||||
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
||||||
return <CheckBox marginRight={8} check={isActive} label={name} onChange={() => setLanguage(id)} need />
|
return <CheckBox marginRight={8} check={isActive} label={name} onChange={() => { setLanguage(id) }} need />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(() => {
|
export default memo(() => {
|
||||||
|
@ -27,7 +27,7 @@ const Item = ({ id, name }: {
|
|||||||
}) => {
|
}) => {
|
||||||
const isActive = useActive(id)
|
const isActive = useActive(id)
|
||||||
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
||||||
return <CheckBox marginBottom={3} check={isActive} label={name} onChange={() => setShareType(id)} need />
|
return <CheckBox marginBottom={3} check={isActive} label={name} onChange={() => { setShareType(id) }} need />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(() => {
|
export default memo(() => {
|
||||||
|
@ -29,7 +29,7 @@ const Item = ({ id, name, change }: {
|
|||||||
}) => {
|
}) => {
|
||||||
const isActive = useActive(id)
|
const isActive = useActive(id)
|
||||||
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
||||||
return <CheckBox marginBottom={5} check={isActive} label={name} onChange={() => change(id)} need />
|
return <CheckBox marginBottom={5} check={isActive} label={name} onChange={() => { change(id) }} need />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(() => {
|
export default memo(() => {
|
||||||
|
@ -27,7 +27,7 @@ const Item = ({ id, name }: {
|
|||||||
}) => {
|
}) => {
|
||||||
const isActive = useActive(id)
|
const isActive = useActive(id)
|
||||||
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
||||||
return <CheckBox marginBottom={3} check={isActive} label={name} onChange={() => setSourceNameType(id)} need />
|
return <CheckBox marginBottom={3} check={isActive} label={name} onChange={() => { setSourceNameType(id) }} need />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(() => {
|
export default memo(() => {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { View, ImageBackground, TouchableOpacity, InteractionManager, ImageSourcePropType } from 'react-native'
|
import { View, ImageBackground, TouchableOpacity, InteractionManager, type ImageSourcePropType } from 'react-native'
|
||||||
import { setTheme } from '@/core/theme'
|
import { setTheme } from '@/core/theme'
|
||||||
import { useI18n } from '@/lang'
|
import { useI18n } from '@/lang'
|
||||||
import { useSettingValue } from '@/store/setting/hook'
|
import { useSettingValue } from '@/store/setting/hook'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
|
|
||||||
import SubTitle from '../components/SubTitle'
|
import SubTitle from '../components/SubTitle'
|
||||||
import { BG_IMAGES, getAllThemes, LocalTheme } from '@/theme/themes'
|
import { BG_IMAGES, getAllThemes, type LocalTheme } from '@/theme/themes'
|
||||||
import Text from '@/components/common/Text'
|
import Text from '@/components/common/Text'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle } from '@/utils/tools'
|
||||||
import { scaleSizeH } from '@/utils/pixelRatio'
|
import { scaleSizeH } from '@/utils/pixelRatio'
|
||||||
@ -28,7 +28,7 @@ const ThemeItem = ({ id, name, color, image, setTheme }: {
|
|||||||
const isActive = useActive(id)
|
const isActive = useActive(id)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TouchableOpacity style={{ ...styles.item, width: scaleSizeH(ITEM_HEIGHT) }} activeOpacity={0.5} onPress={() => setTheme(id)}>
|
<TouchableOpacity style={{ ...styles.item, width: scaleSizeH(ITEM_HEIGHT) }} activeOpacity={0.5} onPress={() => { setTheme(id) }}>
|
||||||
<View style={{ ...styles.colorContent, width: scaleSizeH(COLOR_ITEM_HEIGHT), borderColor: isActive ? color : 'transparent' }}>
|
<View style={{ ...styles.colorContent, width: scaleSizeH(COLOR_ITEM_HEIGHT), borderColor: isActive ? color : 'transparent' }}>
|
||||||
{
|
{
|
||||||
image
|
image
|
||||||
|
@ -24,7 +24,7 @@ const Item = ({ id, name }: {
|
|||||||
}) => {
|
}) => {
|
||||||
const isActive = useActive(id)
|
const isActive = useActive(id)
|
||||||
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
// const [toggleCheckBox, setToggleCheckBox] = useState(false)
|
||||||
return <CheckBox marginRight={8} check={isActive} label={name} onChange={() => setAddMusicLocationType(id)} need />
|
return <CheckBox marginRight={8} check={isActive} label={name} onChange={() => { setAddMusicLocationType(id) }} need />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { memo, useMemo } from 'react'
|
import React, { memo, useMemo } from 'react'
|
||||||
import { View } from 'react-native'
|
import { View } from 'react-native'
|
||||||
|
|
||||||
import InputItem, { InputItemProps } from '../components/InputItem'
|
import InputItem, { type InputItemProps } from '../components/InputItem'
|
||||||
import { createStyle, toast } from '@/utils/tools'
|
import { createStyle, toast } from '@/utils/tools'
|
||||||
import { useSettingValue } from '@/store/setting/hook'
|
import { useSettingValue } from '@/store/setting/hook'
|
||||||
import { useI18n } from '@/lang'
|
import { useI18n } from '@/lang'
|
||||||
|
@ -80,6 +80,7 @@ export default memo(({ host, setHost }: {
|
|||||||
return () => {
|
return () => {
|
||||||
isUnmountedRef.current = true
|
isUnmountedRef.current = true
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { memo } from 'react'
|
import React, { memo } from 'react'
|
||||||
|
|
||||||
import Button, { BtnProps } from '@/components/common/Button'
|
import Button, { type BtnProps } from '@/components/common/Button'
|
||||||
import Text from '@/components/common/Text'
|
import Text from '@/components/common/Text'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle } from '@/utils/tools'
|
||||||
|
@ -55,6 +55,7 @@ export default memo(({ value, label, onChanged, ...props }: InputItemProps) => {
|
|||||||
setText(newValue)
|
setText(newValue)
|
||||||
textRef.current = newValue
|
textRef.current = newValue
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [value])
|
}, [value])
|
||||||
const handleSetSelectMode = (text: string) => {
|
const handleSetSelectMode = (text: string) => {
|
||||||
setText(text)
|
setText(text)
|
||||||
|
@ -13,7 +13,7 @@ export default forwardRef<ListType, {}>((props, ref) => {
|
|||||||
const listRef = useRef<SonglistType>(null)
|
const listRef = useRef<SonglistType>(null)
|
||||||
const isUnmountedRef = useRef(false)
|
const isUnmountedRef = useRef(false)
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
loadList(source, sortId, tagId) {
|
async loadList(source, sortId, tagId) {
|
||||||
const listInfo = songlistState.listInfo
|
const listInfo = songlistState.listInfo
|
||||||
listRef.current?.setList([])
|
listRef.current?.setList([])
|
||||||
if (listInfo.tagId == tagId && listInfo.sortId == sortId && listInfo.source == source && listInfo.list.length) {
|
if (listInfo.tagId == tagId && listInfo.sortId == sortId && listInfo.source == source && listInfo.list.length) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useRef } from 'react'
|
import React, { useRef } from 'react'
|
||||||
import MusicAddModal, { MusicAddModalType } from '@/components/MusicAddModal'
|
import MusicAddModal, { type MusicAddModalType } from '@/components/MusicAddModal'
|
||||||
import playerState from '@/store/player/state'
|
import playerState from '@/store/player/state'
|
||||||
import Btn from './Btn'
|
import Btn from './Btn'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { memo, useMemo } from 'react'
|
import React, { memo, useMemo } from 'react'
|
||||||
import { View, Pressable, GestureResponderEvent } from 'react-native'
|
import { View, Pressable, type GestureResponderEvent } from 'react-native'
|
||||||
import { useLayout } from '@/utils/hooks'
|
import { useLayout } from '@/utils/hooks'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle } from '@/utils/tools'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useRef } from 'react'
|
import React, { useRef } from 'react'
|
||||||
import MusicAddModal, { MusicAddModalType } from '@/components/MusicAddModal'
|
import MusicAddModal, { type MusicAddModalType } from '@/components/MusicAddModal'
|
||||||
import playerState from '@/store/player/state'
|
import playerState from '@/store/player/state'
|
||||||
import Btn from './Btn'
|
import Btn from './Btn'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { memo, useRef } from 'react'
|
import React, { memo, useRef } from 'react'
|
||||||
import TimeoutExitEditModal, { TimeoutExitEditModalType, useTimeInfo } from '@/components/TimeoutExitEditModal'
|
import TimeoutExitEditModal, { type TimeoutExitEditModalType, useTimeInfo } from '@/components/TimeoutExitEditModal'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
import Btn from './Btn'
|
import Btn from './Btn'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { memo, useMemo } from 'react'
|
import React, { memo, useMemo } from 'react'
|
||||||
import { View, Pressable, GestureResponderEvent } from 'react-native'
|
import { View, Pressable, type GestureResponderEvent } from 'react-native'
|
||||||
import { useLayout } from '@/utils/hooks'
|
import { useLayout } from '@/utils/hooks'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle } from '@/utils/tools'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
|
@ -18,7 +18,7 @@ export default forwardRef<MusicListType, MusicListProps>(({ componentId }, ref)
|
|||||||
const headerRef = useRef<HeaderType>(null)
|
const headerRef = useRef<HeaderType>(null)
|
||||||
const isUnmountedRef = useRef(false)
|
const isUnmountedRef = useRef(false)
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
loadList(source, id) {
|
async loadList(source, id) {
|
||||||
const listDetailInfo = songlistState.listDetailInfo
|
const listDetailInfo = songlistState.listDetailInfo
|
||||||
listRef.current?.setList([])
|
listRef.current?.setList([])
|
||||||
if (listDetailInfo.id == id && listDetailInfo.source == source && listDetailInfo.list.length) {
|
if (listDetailInfo.id == id && listDetailInfo.source == source && listDetailInfo.list.length) {
|
||||||
@ -99,6 +99,7 @@ export default forwardRef<MusicListType, MusicListProps>(({ componentId }, ref)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const header = useMemo(() => <Header ref={headerRef} componentId={componentId} />, [])
|
const header = useMemo(() => <Header ref={headerRef} componentId={componentId} />, [])
|
||||||
|
|
||||||
return <OnlineList
|
return <OnlineList
|
||||||
|
@ -24,6 +24,7 @@ export default ({ componentId }: { componentId: string }) => {
|
|||||||
return () => {
|
return () => {
|
||||||
isUnmountedRef.current = true
|
isUnmountedRef.current = true
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ export const usePageVisible = (visibleNames: COMPONENT_IDS[], onChange: (visible
|
|||||||
return () => {
|
return () => {
|
||||||
global.state_event.off('componentIdsUpdated', handlecheck)
|
global.state_event.off('componentIdsUpdated', handlecheck)
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,6 +63,7 @@ export const useAssertApiSupport = (source: LX.Source) => {
|
|||||||
return () => {
|
return () => {
|
||||||
global.state_event.off('apiSourceUpdated', handleUpdate)
|
global.state_event.off('apiSourceUpdated', handleUpdate)
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
@ -84,6 +84,7 @@ export const useListFetching = (listId: string) => {
|
|||||||
return () => {
|
return () => {
|
||||||
global.state_event.off('fetchingListStatusUpdated', handleUpdate)
|
global.state_event.off('fetchingListStatusUpdated', handleUpdate)
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return fetching
|
return fetching
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
// import { createSlice } from '@reduxjs/toolkit'
|
|
||||||
import { NAV_MENUS } from '@/config/constant'
|
|
||||||
// import type { PayloadAction } from '@reduxjs/toolkit'
|
|
||||||
// import type { RootState } from '@/store'
|
|
||||||
|
|
||||||
// type MenuIds = (typeof NAV_MENUS)[number]['id']
|
|
||||||
|
|
||||||
// // Define a type for the slice state
|
|
||||||
// interface InitState {
|
|
||||||
// activeId: MenuIds
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Define the initial state using that type
|
|
||||||
// const initialState: InitState = {
|
|
||||||
// activeId: 'search',
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // export const slice = createSlice({
|
|
||||||
// // name: 'common',
|
|
||||||
// // // `createSlice` will infer the state type from the `initialState` argument
|
|
||||||
// // initialState,
|
|
||||||
// // reducers: {
|
|
||||||
// // setNavActive(state, action: PayloadAction<MenuIds>) {
|
|
||||||
// // if (action.payload === state.activeId) return
|
|
||||||
// // state.activeId = action.payload
|
|
||||||
// // },
|
|
||||||
// // },
|
|
||||||
// // })
|
|
||||||
|
|
||||||
// export const { setNavActive } = slice.actions
|
|
||||||
|
|
||||||
// // Other code such as selectors can use the imported `RootState` type
|
|
||||||
// // export const selectCount = (state: RootState) => state.counter.value
|
|
||||||
|
|
||||||
// export default slice.reducer
|
|
@ -1,5 +0,0 @@
|
|||||||
import common from './common'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
common,
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
import common from './common'
|
|
||||||
// import * as search from './search'
|
|
||||||
// import * as player from './player'
|
|
||||||
// import * as list from './list'
|
|
||||||
// import * as songList from './songList'
|
|
||||||
// import * as top from './top'
|
|
||||||
|
|
||||||
// export {
|
|
||||||
// common,
|
|
||||||
// search,
|
|
||||||
// player,
|
|
||||||
// list,
|
|
||||||
// songList,
|
|
||||||
// top,
|
|
||||||
// }
|
|
||||||
|
|
||||||
export default {
|
|
||||||
...common,
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
import music from '@/utils/musicSdk'
|
|
||||||
import { deduplicationList } from '@/utils/tools'
|
|
||||||
|
|
||||||
export const TYPES = {
|
|
||||||
loading: null,
|
|
||||||
setText: null,
|
|
||||||
addHistory: null,
|
|
||||||
setList: null,
|
|
||||||
setLists: null,
|
|
||||||
clearList: null,
|
|
||||||
removeHistory: null,
|
|
||||||
clearHistory: null,
|
|
||||||
setTipList: null,
|
|
||||||
setVisibleTipList: null,
|
|
||||||
}
|
|
||||||
for (const key of Object.keys(TYPES)) {
|
|
||||||
TYPES[key] = `search__${key}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const sources = []
|
|
||||||
for (const source of music.sources) {
|
|
||||||
const musicSearch = music[source.id].musicSearch
|
|
||||||
if (!musicSearch) continue
|
|
||||||
sources.push(source)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const search = ({ page, limit }) => (dispatch, getState) => {
|
|
||||||
// dispatch({ type: TYPES.setText, payload: text })
|
|
||||||
const state = getState()
|
|
||||||
const text = state.search.text
|
|
||||||
if (!text.length) {
|
|
||||||
dispatch({ type: TYPES.clearList })
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
|
||||||
dispatch({ type: TYPES.addHistory, payload: text })
|
|
||||||
|
|
||||||
|
|
||||||
if (state.common.setting.search.searchSource == 'all') {
|
|
||||||
const task = []
|
|
||||||
for (const source of sources) {
|
|
||||||
if (source.id == 'all') continue
|
|
||||||
dispatch({ type: TYPES.loading, payload: true })
|
|
||||||
task.push(music[source.id].musicSearch.search(text, page).catch(error => {
|
|
||||||
console.log(error)
|
|
||||||
return {
|
|
||||||
allPage: 1,
|
|
||||||
limit: 30,
|
|
||||||
list: [],
|
|
||||||
source: source.id,
|
|
||||||
total: 0,
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
return Promise.all(task).then(results => dispatch({ type: TYPES.setLists, payload: { results, page } }))
|
|
||||||
.finally(() => dispatch({ type: TYPES.loading, payload: false }))
|
|
||||||
} else {
|
|
||||||
dispatch({ type: TYPES.loading, payload: true })
|
|
||||||
return music[state.common.setting.search.searchSource].musicSearch.search(text, page, limit).catch(error => {
|
|
||||||
console.log(error)
|
|
||||||
return {
|
|
||||||
allPage: 1,
|
|
||||||
limit: 30,
|
|
||||||
list: [],
|
|
||||||
source: state.common.setting.search.searchSource,
|
|
||||||
total: 0,
|
|
||||||
}
|
|
||||||
}).then(data => dispatch({ type: TYPES.setList, payload: { page, ...data, list: deduplicationList(data.list) } }))
|
|
||||||
.finally(() => dispatch({ type: TYPES.loading, payload: false }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const setText = text => ({ type: TYPES.setText, payload: text })
|
|
||||||
export const setTipList = list => ({ type: TYPES.setTipList, payload: list })
|
|
||||||
export const setVisibleTipList = visible => ({ type: TYPES.setVisibleTipList, payload: visible })
|
|
||||||
|
|
||||||
export const clearList = () => ({
|
|
||||||
type: TYPES.clearList,
|
|
||||||
})
|
|
||||||
export const addHistory = text => ({
|
|
||||||
type: TYPES.addHistory,
|
|
||||||
payload: text,
|
|
||||||
})
|
|
||||||
export const removeHistory = index => ({
|
|
||||||
type: TYPES.addHistory,
|
|
||||||
payload: index,
|
|
||||||
})
|
|
||||||
export const clearHistory = () => ({
|
|
||||||
type: TYPES.addHistory,
|
|
||||||
})
|
|
@ -1,33 +0,0 @@
|
|||||||
import { createSelector } from 'reselect'
|
|
||||||
|
|
||||||
|
|
||||||
export const text = state => state.search.text
|
|
||||||
export const sourceList = state => state.search.sourceList
|
|
||||||
export const aggregationListInfo = state => state.search.aggregationListInfo
|
|
||||||
export const isEnd = state => state.search.isEnd
|
|
||||||
export const isLoading = state => state.search.isLoading
|
|
||||||
|
|
||||||
export const tipList = state => state.search.tipInfo.list
|
|
||||||
export const tipListVisible = state => state.search.tipInfo.visible
|
|
||||||
|
|
||||||
|
|
||||||
export const rawSources = state => state.search.sources
|
|
||||||
export const tempSearchSource = state => state.common.setting.search.tempSearchSource
|
|
||||||
export const searchSource = state => state.common.setting.search.searchSource
|
|
||||||
|
|
||||||
|
|
||||||
export const sources = createSelector([rawSources], sources => {
|
|
||||||
return sources.map(source => ({ label: source.name, id: source.id }))
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
export const currentSourceName = createSelector([rawSources, searchSource], (sources, searchSource) => {
|
|
||||||
const source = sources.find(s => s.id == searchSource)
|
|
||||||
return source ? source.name : 'unknown'
|
|
||||||
})
|
|
||||||
|
|
||||||
export const listInfo = createSelector([searchSource, sourceList, aggregationListInfo], (searchSource, sourceList, aggregationListInfo) => {
|
|
||||||
return searchSource == 'all'
|
|
||||||
? aggregationListInfo
|
|
||||||
: sourceList[searchSource]
|
|
||||||
})
|
|
@ -1,5 +0,0 @@
|
|||||||
import * as action from './action'
|
|
||||||
import * as getter from './getter'
|
|
||||||
|
|
||||||
export { action, getter }
|
|
||||||
export { default as reducer } from './reducer'
|
|
@ -1,248 +0,0 @@
|
|||||||
import { TYPES } from './action'
|
|
||||||
|
|
||||||
import music from '@/utils/musicSdk'
|
|
||||||
|
|
||||||
let historyList
|
|
||||||
if (historyList == null) {
|
|
||||||
historyList = []
|
|
||||||
// electronStore_data.set('searchHistoryList', historyList)
|
|
||||||
}
|
|
||||||
|
|
||||||
const sources = []
|
|
||||||
const sourceList = {}
|
|
||||||
for (const source of music.sources) {
|
|
||||||
const musicSearch = music[source.id].musicSearch
|
|
||||||
if (!musicSearch) continue
|
|
||||||
sources.push(source)
|
|
||||||
sourceList[source.id] = {
|
|
||||||
page: 1,
|
|
||||||
maxPage: 0,
|
|
||||||
limit: 30,
|
|
||||||
total: 0,
|
|
||||||
list: [],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sources.push({
|
|
||||||
// id: 'all',
|
|
||||||
// name: '聚合搜索',
|
|
||||||
// })
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
text: '',
|
|
||||||
historyList,
|
|
||||||
sources,
|
|
||||||
isEnd: false,
|
|
||||||
isLoading: false,
|
|
||||||
sourceList,
|
|
||||||
aggregationListInfo: {
|
|
||||||
list: [],
|
|
||||||
page: 1,
|
|
||||||
limit: 30,
|
|
||||||
maxPage: 1,
|
|
||||||
total: 0,
|
|
||||||
},
|
|
||||||
tipInfo: {
|
|
||||||
list: [],
|
|
||||||
visible: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// https://blog.csdn.net/xcxy2015/article/details/77164126#comments
|
|
||||||
const similar = (a, b) => {
|
|
||||||
if (!a || !b) return 0
|
|
||||||
if (a.length > b.length) { // 保证 a <= b
|
|
||||||
const t = b
|
|
||||||
b = a
|
|
||||||
a = t
|
|
||||||
}
|
|
||||||
const al = a.length
|
|
||||||
const bl = b.length
|
|
||||||
const mp = [] // 一个表
|
|
||||||
let i, j, ai, lt, tmp // ai:字符串a的第i个字符。 lt:左上角的值。 tmp:暂存新的值。
|
|
||||||
for (i = 0; i <= bl; i++) mp[i] = i
|
|
||||||
for (i = 1; i <= al; i++) {
|
|
||||||
ai = a.charAt(i - 1)
|
|
||||||
lt = mp[0]
|
|
||||||
mp[0] = mp[0] + 1
|
|
||||||
for (j = 1; j <= bl; j++) {
|
|
||||||
tmp = Math.min(mp[j] + 1, mp[j - 1] + 1, lt + (ai == b.charAt(j - 1) ? 0 : 1))
|
|
||||||
lt = mp[j]
|
|
||||||
mp[j] = tmp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1 - (mp[bl] / bl)
|
|
||||||
}
|
|
||||||
|
|
||||||
const sortInsert = (arr, data) => {
|
|
||||||
const key = data.num
|
|
||||||
let left = 0
|
|
||||||
let right = arr.length - 1
|
|
||||||
|
|
||||||
while (left <= right) {
|
|
||||||
const middle = parseInt((left + right) / 2)
|
|
||||||
if (key == arr[middle]) {
|
|
||||||
left = middle
|
|
||||||
break
|
|
||||||
} else if (key < arr[middle].num) {
|
|
||||||
right = middle - 1
|
|
||||||
} else {
|
|
||||||
left = middle + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (left > 0) {
|
|
||||||
if (arr[left - 1].num != key) break
|
|
||||||
left--
|
|
||||||
}
|
|
||||||
|
|
||||||
arr.splice(left, 0, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSortList = (list, keyword) => {
|
|
||||||
const arr = []
|
|
||||||
for (const item of list) {
|
|
||||||
sortInsert(arr, {
|
|
||||||
num: similar(keyword, `${item.name} ${item.singer}`),
|
|
||||||
data: item,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return arr.map(item => item.data).reverse()
|
|
||||||
}
|
|
||||||
|
|
||||||
const filterList = list => {
|
|
||||||
const set = new Set()
|
|
||||||
for (let i = list.length - 1; i > -1; i--) {
|
|
||||||
const item = list[i]
|
|
||||||
if (set.has(item.songmid)) {
|
|
||||||
list.splice(i, 1)
|
|
||||||
} else {
|
|
||||||
set.add(item.songmid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
const mutations = {
|
|
||||||
[TYPES.loading](state, isLoading) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
isLoading,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setText](state, text) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
text,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.addHistory](state, text) {
|
|
||||||
let historyList = [...state.historyList]
|
|
||||||
const index = historyList.indexOf(text)
|
|
||||||
if (index > -1) historyList.splice(index, 1)
|
|
||||||
if (historyList.length >= 15) historyList = historyList.slice(0, 14)
|
|
||||||
historyList.unshift(text)
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
historyList,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setList](state, datas) {
|
|
||||||
const source = { ...state.sourceList[datas.source] }
|
|
||||||
source.list = datas.page > 1 ? filterList([...source.list, ...datas.list]) : datas.list
|
|
||||||
source.total = datas.total
|
|
||||||
source.maxPage = datas.allPage
|
|
||||||
source.page = datas.page
|
|
||||||
state.isEnd = datas.page >= source.maxPage
|
|
||||||
// source.limit = datas.limit
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
sourceList: {
|
|
||||||
...state.sourceList,
|
|
||||||
[datas.source]: source,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setLists](state, { results, page }) {
|
|
||||||
const pages = []
|
|
||||||
let total = 0
|
|
||||||
// let limit = 0
|
|
||||||
let maxPage = 1
|
|
||||||
const list = []
|
|
||||||
state = { ...state }
|
|
||||||
const aggregationListInfo = { ...state.aggregationListInfo }
|
|
||||||
for (const source of results) {
|
|
||||||
if (source.allPage < page) continue
|
|
||||||
list.push(...source.list)
|
|
||||||
pages.push(source.allPage)
|
|
||||||
total += source.total
|
|
||||||
// limit = Math.max(source.limit, limit)
|
|
||||||
maxPage = Math.max(source.allPage, maxPage)
|
|
||||||
}
|
|
||||||
aggregationListInfo.maxPage = Math.max(...pages)
|
|
||||||
aggregationListInfo.total = total
|
|
||||||
// aggregationListInfo.limit = limit
|
|
||||||
aggregationListInfo.page = page
|
|
||||||
aggregationListInfo.maxPage = maxPage
|
|
||||||
aggregationListInfo.list = page > 1 ? filterList([...aggregationListInfo.list, ...handleSortList(list, state.text)]) : handleSortList(list, state.text)
|
|
||||||
aggregationListInfo.isEnd = aggregationListInfo.maxPage >= page
|
|
||||||
return state
|
|
||||||
},
|
|
||||||
[TYPES.clearList](state) {
|
|
||||||
state = { ...state }
|
|
||||||
state.sourceList = { ...state.sourceList }
|
|
||||||
for (const source of Object.keys(state.sourceList)) {
|
|
||||||
state.sourceList[source] = { ...state.sourceList[source] }
|
|
||||||
state.sourceList[source].list = []
|
|
||||||
state.sourceList[source].page = 0
|
|
||||||
state.sourceList[source].maxPage = 1
|
|
||||||
state.sourceList[source].total = 0
|
|
||||||
}
|
|
||||||
const aggregationListInfo = { ...state.aggregationListInfo }
|
|
||||||
aggregationListInfo.list = []
|
|
||||||
aggregationListInfo.page = 0
|
|
||||||
aggregationListInfo.maxPage = 1
|
|
||||||
aggregationListInfo.total = 0
|
|
||||||
state.text = ''
|
|
||||||
state.isEnd = false
|
|
||||||
return state
|
|
||||||
},
|
|
||||||
[TYPES.removeHistory](state, index) {
|
|
||||||
const historyList = [...state.historyList]
|
|
||||||
historyList.splice(index, 1)
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
historyList,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.clearHistory](state) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
historyList: [],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setTipList](state, list) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
tipInfo: {
|
|
||||||
...state.tipInfo,
|
|
||||||
list,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setVisibleTipList](state, visible) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
tipInfo: {
|
|
||||||
...state.tipInfo,
|
|
||||||
visible,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default (state = initialState, action) =>
|
|
||||||
mutations[action.type]
|
|
||||||
? mutations[action.type](state, action.payload)
|
|
||||||
: state
|
|
@ -1,235 +0,0 @@
|
|||||||
import music from '@/utils/musicSdk'
|
|
||||||
import { deduplicationList } from '@/utils/tools'
|
|
||||||
|
|
||||||
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,
|
|
||||||
setGetListDetailFailed: null,
|
|
||||||
clearListDetail: 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())
|
|
||||||
|
|
||||||
dispatch(setGetListDetailFailed(false))
|
|
||||||
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)
|
|
||||||
}).catch(err => {
|
|
||||||
console.log(err)
|
|
||||||
if (page == 1) {
|
|
||||||
dispatch(setGetListDetailFailed(true))
|
|
||||||
}
|
|
||||||
return Promise.reject(err)
|
|
||||||
}).finally(() => {
|
|
||||||
const state = getState().songList
|
|
||||||
if (state.listDetail.pageKey != pageKey) return
|
|
||||||
dispatch(setListDetailLoading(false))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getListDetailAll = ({ source, id, isRefresh = false }) => (dispatch, getState) => {
|
|
||||||
let listKey = `sdetail__${source}__${id}`
|
|
||||||
if (isRefresh && cache.has(listKey)) cache.delete(listKey)
|
|
||||||
if (!cache.has(listKey)) cache.set(listKey, new Map())
|
|
||||||
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])
|
|
||||||
}).then(list => deduplicationList(list))
|
|
||||||
}
|
|
||||||
|
|
||||||
export const setVisibleListDetail = isShow => {
|
|
||||||
return {
|
|
||||||
type: TYPES.setVisibleListDetail,
|
|
||||||
payload: isShow,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export const setSelectListInfo = info => (dispatch, getState) => {
|
|
||||||
dispatch({
|
|
||||||
type: TYPES.setSelectListInfo,
|
|
||||||
payload: info,
|
|
||||||
})
|
|
||||||
dispatch({
|
|
||||||
type: TYPES.clearListDetail,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export const setGetListDetailFailed = isFailed => {
|
|
||||||
return {
|
|
||||||
type: TYPES.setGetListDetailFailed,
|
|
||||||
payload: isFailed,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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 },
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
import { createSelector } from 'reselect'
|
|
||||||
|
|
||||||
|
|
||||||
// sourceInfo(state, getters, rootState, { sourceNames }) {
|
|
||||||
// return { sources: sources.map(item => ({ id: item.id, name: sourceNames[item.id] })), sortList }
|
|
||||||
// },
|
|
||||||
// tags: state => state.tags,
|
|
||||||
// isVisibleListDetail: state => state.isVisibleListDetail,
|
|
||||||
|
|
||||||
export const rawSources = state => state.songList.sources
|
|
||||||
|
|
||||||
export const sortList = state => state.songList.sortList
|
|
||||||
|
|
||||||
export const tags = state => state.songList.tags
|
|
||||||
|
|
||||||
export const isVisibleListDetail = state => state.songList.isVisibleListDetail
|
|
||||||
export const isGetListDetailFailed = state => state.songList.isGetListDetailFailed
|
|
||||||
export const selectListInfo = state => state.songList.selectListInfo
|
|
||||||
export const listData = state => state.songList.list
|
|
||||||
export const listDetailData = state => state.songList.listDetail
|
|
||||||
|
|
||||||
export const listInfo = state => state.songList.list
|
|
||||||
export const listDetailInfo = state => state.songList.listDetail
|
|
||||||
|
|
||||||
export const songListSource = state => state.common.setting.songList.source
|
|
||||||
export const songListSortId = state => state.common.setting.songList.sortId
|
|
||||||
export const songListTagInfo = state => state.common.setting.songList.tagInfo
|
|
||||||
|
|
||||||
export const sources = createSelector([rawSources], sources => {
|
|
||||||
return sources.map(source => ({ label: source.name, id: source.id }))
|
|
||||||
})
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
import * as action from './action'
|
|
||||||
import * as getter from './getter'
|
|
||||||
|
|
||||||
export { action, getter }
|
|
||||||
export { default as reducer } from './reducer'
|
|
@ -1,191 +0,0 @@
|
|||||||
import { TYPES } from './action'
|
|
||||||
import music from '@/utils/musicSdk'
|
|
||||||
import { deduplicationList } from '@/utils/tools'
|
|
||||||
const sortList = {}
|
|
||||||
const sources = []
|
|
||||||
for (const source of music.sources) {
|
|
||||||
const songList = music[source.id].songList
|
|
||||||
if (!songList) continue
|
|
||||||
sortList[source.id] = songList.sortList
|
|
||||||
sources.push(source)
|
|
||||||
}
|
|
||||||
// state
|
|
||||||
const initialState = {
|
|
||||||
sources,
|
|
||||||
sortList,
|
|
||||||
tags: {},
|
|
||||||
list: {
|
|
||||||
list: [],
|
|
||||||
total: 0,
|
|
||||||
page: 1,
|
|
||||||
limit: 30,
|
|
||||||
listKey: null,
|
|
||||||
pageKey: null,
|
|
||||||
isLoading: false,
|
|
||||||
isEnd: false,
|
|
||||||
},
|
|
||||||
listDetail: {
|
|
||||||
list: [],
|
|
||||||
desc: null,
|
|
||||||
total: 0,
|
|
||||||
page: 1,
|
|
||||||
limit: 30,
|
|
||||||
info: {},
|
|
||||||
listKey: null,
|
|
||||||
pageKey: null,
|
|
||||||
isLoading: false,
|
|
||||||
isEnd: false,
|
|
||||||
},
|
|
||||||
selectListInfo: {},
|
|
||||||
isVisibleListDetail: false,
|
|
||||||
isGetListDetailFailed: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
sources.forEach(source => {
|
|
||||||
initialState.tags[source.id] = null
|
|
||||||
})
|
|
||||||
|
|
||||||
const mutations = {
|
|
||||||
[TYPES.setTags](state, { tags, source }) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
tags: { ...state.tags, [source]: tags },
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.clearList](state) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
list: {
|
|
||||||
...state.list,
|
|
||||||
list: [],
|
|
||||||
total: 0,
|
|
||||||
page: 1,
|
|
||||||
pageKey: null,
|
|
||||||
listKey: null,
|
|
||||||
isLoading: false,
|
|
||||||
isEnd: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setList](state, { result, pageKey, listKey, page }) {
|
|
||||||
if (pageKey == state.list.pageKey && state.list.list.length) return state
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
list: {
|
|
||||||
...state.list,
|
|
||||||
list: listKey == state.list.listKey && page != 1 ? [...state.list.list, ...result.list] : result.list,
|
|
||||||
total: result.total,
|
|
||||||
limit: result.limit,
|
|
||||||
page,
|
|
||||||
pageKey,
|
|
||||||
listKey,
|
|
||||||
isEnd: page >= Math.ceil(result.total / result.limit),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setListDetail](state, { result, pageKey, listKey, source, id, page }) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
listDetail: {
|
|
||||||
...state.listDetail,
|
|
||||||
list: deduplicationList(listKey == state.listDetail.listKey && page != 1 ? [...state.listDetail.list, ...result.list] : result.list),
|
|
||||||
id,
|
|
||||||
source,
|
|
||||||
total: result.total,
|
|
||||||
limit: result.limit,
|
|
||||||
page,
|
|
||||||
pageKey,
|
|
||||||
listKey,
|
|
||||||
isEnd: page >= Math.ceil(result.total / result.limit),
|
|
||||||
info: result.info || {
|
|
||||||
name: state.selectListInfo.name,
|
|
||||||
img: state.selectListInfo.img,
|
|
||||||
desc: state.selectListInfo.desc,
|
|
||||||
author: state.selectListInfo.author,
|
|
||||||
play_count: state.selectListInfo.play_count,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setVisibleListDetail](state, bool) {
|
|
||||||
const newState = {
|
|
||||||
...state,
|
|
||||||
isVisibleListDetail: bool,
|
|
||||||
}
|
|
||||||
if (!bool) newState.listDetail = { ...newState.listDetail, list: [] }
|
|
||||||
return newState
|
|
||||||
},
|
|
||||||
[TYPES.setSelectListInfo](state, info) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
selectListInfo: info,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.clearListDetail](state) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
listDetail: {
|
|
||||||
...state.listDetail,
|
|
||||||
id: null,
|
|
||||||
source: null,
|
|
||||||
list: [],
|
|
||||||
desc: null,
|
|
||||||
total: 0,
|
|
||||||
page: 1,
|
|
||||||
limit: 30,
|
|
||||||
pageKey: null,
|
|
||||||
listKey: null,
|
|
||||||
isLoading: false,
|
|
||||||
isEnd: false,
|
|
||||||
info: {},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setGetListDetailFailed](state, isFailed) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
isGetListDetailFailed: isFailed,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setListLoading](state, isLoading) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
list: {
|
|
||||||
...state.list,
|
|
||||||
isLoading,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setListDetailLoading](state, isLoading) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
listDetail: {
|
|
||||||
...state.listDetail,
|
|
||||||
isLoading,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setListEnd](state, isEnd) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
list: {
|
|
||||||
...state.list,
|
|
||||||
isEnd,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setListDetailEnd](state, isEnd) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
listDetail: {
|
|
||||||
...state.listDetail,
|
|
||||||
isEnd,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default (state = initialState, action) => mutations[action.type]
|
|
||||||
? mutations[action.type](state, action.payload)
|
|
||||||
: state
|
|
||||||
|
|
@ -1,161 +0,0 @@
|
|||||||
import music from '@/utils/musicSdk'
|
|
||||||
import { deduplicationList } from '@/utils/tools'
|
|
||||||
|
|
||||||
const cache = new Map()
|
|
||||||
const LIST_LOAD_LIMIT = 30
|
|
||||||
|
|
||||||
export const TYPES = {
|
|
||||||
setBoardsList: null,
|
|
||||||
setList: null,
|
|
||||||
clearList: null,
|
|
||||||
setListLoading: null,
|
|
||||||
setListEnd: null,
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const key of Object.keys(TYPES)) {
|
|
||||||
TYPES[key] = `top__${key}`
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getBoardsList = () => (dispatch, getState) => {
|
|
||||||
const state = getState()
|
|
||||||
let source = state.common.setting.leaderboard.source
|
|
||||||
// let tabId = rootState.setting.leaderboard.tabId
|
|
||||||
// let key = `${source}${tabId}${page}`
|
|
||||||
// if (state.list.length && state.key == key) return true
|
|
||||||
// commit('clearList')
|
|
||||||
if (state.top.boards[source].length) return Promise.resolve()
|
|
||||||
return music[source].leaderboard.getBoards().then(result => dispatch(setBoardsList({ boards: result, source })))
|
|
||||||
}
|
|
||||||
|
|
||||||
const getListLimit = ({ source, tabId, bangId, page }) => {
|
|
||||||
const listKey = `${source}__${tabId}`
|
|
||||||
const prevPageKey = `${source}__${tabId}__${page - 1}`
|
|
||||||
const tempListKey = `${source}__${tabId}__temp`
|
|
||||||
|
|
||||||
const listCache = cache.get(listKey)
|
|
||||||
let sourcePage = 0
|
|
||||||
if (listCache.has(prevPageKey)) {
|
|
||||||
sourcePage = listCache.get(prevPageKey).sourcePage
|
|
||||||
}
|
|
||||||
return music[source].leaderboard.getList(bangId, sourcePage + 1).then(result => {
|
|
||||||
let p = page
|
|
||||||
if (listCache.has(tempListKey)) {
|
|
||||||
const list = listCache.get(tempListKey)
|
|
||||||
listCache.delete(tempListKey)
|
|
||||||
listCache.set(`${source}__${tabId}__${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(`${source}__${tabId}__${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(`${source}__${tabId}__${page}`).data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getList = ({ page, isRefresh = false }) => (dispatch, getState) => {
|
|
||||||
const state = getState()
|
|
||||||
let tabId = state.common.setting.leaderboard.tabId
|
|
||||||
if (tabId == null) return Promise.resolve()
|
|
||||||
// console.log(tabId)
|
|
||||||
const [source, bangId] = tabId.split('__')
|
|
||||||
const listKey = `${source}__${tabId}`
|
|
||||||
const pageKey = `${source}__${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).data).then(result => dispatch(setList({ result, listKey, pageKey, page })))
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(setListEnd(false))
|
|
||||||
dispatch(setListLoading(true))
|
|
||||||
return getListLimit({ source, tabId, bangId, page }).then(result => {
|
|
||||||
dispatch(setList({ result, listKey, pageKey, page }))
|
|
||||||
// listCache.set(pageKey, result)
|
|
||||||
}).finally(() => {
|
|
||||||
const state = getState().top
|
|
||||||
if (state.listInfo.pageKey != pageKey) return
|
|
||||||
dispatch(setListLoading(false))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getListAll = ({ id: tabId, isRefresh = false }) => (dispatch, getState) => {
|
|
||||||
// console.log(tabId)
|
|
||||||
const [source, bangId] = tabId.split('__')
|
|
||||||
const listKey = `${source}__${tabId}`
|
|
||||||
if (isRefresh && cache.has(listKey)) cache.delete(listKey)
|
|
||||||
if (!cache.has(listKey)) cache.set(listKey, new Map())
|
|
||||||
const listCache = cache.get(listKey)
|
|
||||||
const loadData = (bangId, page) => {
|
|
||||||
const pageKey = `${source}__${tabId}__${page}`
|
|
||||||
return listCache.has(pageKey)
|
|
||||||
? Promise.resolve(listCache.get(pageKey).data)
|
|
||||||
: getListLimit({ source, tabId, bangId, page }).then(result => {
|
|
||||||
// listCache.set(pageKey, result)
|
|
||||||
return result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return loadData(bangId, 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(bangId, loadPage).then(result => result.list)
|
|
||||||
: loadData(bangId, loadPage).then(result1 => loadDetail(++loadPage).then(result2 => [...result1.list, ...result2]))
|
|
||||||
}
|
|
||||||
return loadDetail().then(result2 => [...result.list, ...result2])
|
|
||||||
}).then(list => deduplicationList(list))
|
|
||||||
}
|
|
||||||
|
|
||||||
export const setBoardsList = ({ boards, source }) => {
|
|
||||||
return {
|
|
||||||
type: TYPES.setBoardsList,
|
|
||||||
payload: { boards, 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 setListEnd = isEnd => {
|
|
||||||
return {
|
|
||||||
type: TYPES.setListEnd,
|
|
||||||
payload: isEnd,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
import { createSelector } from 'reselect'
|
|
||||||
|
|
||||||
|
|
||||||
// sourceInfo(state, getters, rootState, { sourceNames }) {
|
|
||||||
// return { sources: sources.map(item => ({ id: item.id, name: sourceNames[item.id] })), sortList }
|
|
||||||
// },
|
|
||||||
// tags: state => state.tags,
|
|
||||||
// isVisibleListDetail: state => state.isVisibleListDetail,
|
|
||||||
|
|
||||||
export const rawSources = state => state.top.sources
|
|
||||||
|
|
||||||
export const boards = state => state.top.boards
|
|
||||||
|
|
||||||
export const listInfo = state => state.top.listInfo
|
|
||||||
export const isEnd = state => state.top.isEnd
|
|
||||||
export const isLoading = state => state.top.isLoading
|
|
||||||
|
|
||||||
export const sourceId = state => state.common.setting.leaderboard.source
|
|
||||||
export const tabId = state => state.common.setting.leaderboard.tabId
|
|
||||||
|
|
||||||
export const sources = createSelector([rawSources], sources => {
|
|
||||||
return sources.map(source => ({ label: source.name, id: source.id }))
|
|
||||||
})
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
import * as action from './action'
|
|
||||||
import * as getter from './getter'
|
|
||||||
|
|
||||||
export { action, getter }
|
|
||||||
export { default as reducer } from './reducer'
|
|
@ -1,84 +0,0 @@
|
|||||||
import { TYPES } from './action'
|
|
||||||
import music from '@/utils/musicSdk'
|
|
||||||
import { deduplicationList } from '@/utils/tools'
|
|
||||||
|
|
||||||
const sourceList = {}
|
|
||||||
const sources = []
|
|
||||||
for (const source of music.sources) {
|
|
||||||
const leaderboard = music[source.id].leaderboard
|
|
||||||
if (!leaderboard || !leaderboard.getBoards) continue
|
|
||||||
sourceList[source.id] = []
|
|
||||||
sources.push(source)
|
|
||||||
}
|
|
||||||
|
|
||||||
// state
|
|
||||||
const initialState = {
|
|
||||||
sources,
|
|
||||||
boards: sourceList,
|
|
||||||
listInfo: {
|
|
||||||
list: [],
|
|
||||||
total: 0,
|
|
||||||
page: 1,
|
|
||||||
limit: 30,
|
|
||||||
listKey: null,
|
|
||||||
pageKey: null,
|
|
||||||
},
|
|
||||||
isLoading: false,
|
|
||||||
isEnd: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
const mutations = {
|
|
||||||
[TYPES.setBoardsList](state, { boards, source }) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
boards: { ...state.boards, [source]: boards.list },
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.clearList](state) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
listInfo: {
|
|
||||||
...state.listInfo,
|
|
||||||
list: [],
|
|
||||||
total: 0,
|
|
||||||
page: 1,
|
|
||||||
pageKey: null,
|
|
||||||
listKey: null,
|
|
||||||
},
|
|
||||||
isLoading: false,
|
|
||||||
isEnd: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setList](state, { result, pageKey, listKey, page }) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
listInfo: {
|
|
||||||
...state.listInfo,
|
|
||||||
list: deduplicationList(listKey == state.listInfo.listKey && page != 1 ? [...state.listInfo.list, ...result.list] : result.list),
|
|
||||||
total: result.total,
|
|
||||||
limit: result.limit,
|
|
||||||
page,
|
|
||||||
pageKey,
|
|
||||||
listKey,
|
|
||||||
},
|
|
||||||
isEnd: page >= Math.ceil(result.total / result.limit),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setListLoading](state, isLoading) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
isLoading,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[TYPES.setListEnd](state, isEnd) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
isEnd,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default (state = initialState, action) => mutations[action.type]
|
|
||||||
? mutations[action.type](state, action.payload)
|
|
||||||
: state
|
|
||||||
|
|
@ -5,7 +5,7 @@ import settingState from '@/store/setting/state'
|
|||||||
import themeState from '@/store/theme/state'
|
import themeState from '@/store/theme/state'
|
||||||
import { isUrl } from '@/utils'
|
import { isUrl } from '@/utils'
|
||||||
import { externalDirectoryPath } from '@/utils/fs'
|
import { externalDirectoryPath } from '@/utils/fs'
|
||||||
import { ImageSourcePropType } from 'react-native'
|
import { type ImageSourcePropType } from 'react-native'
|
||||||
|
|
||||||
export const BG_IMAGES = {
|
export const BG_IMAGES = {
|
||||||
'china_ink.jpg': require('./images/china_ink.jpg') as ImageSourcePropType,
|
'china_ink.jpg': require('./images/china_ink.jpg') as ImageSourcePropType,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user