mirror of
https://github.com/ikun0014/lx-music-mobile.git
synced 2025-07-03 20:52:10 +08:00
修改列表布局
This commit is contained in:
parent
a8b169d4d9
commit
2b83d2126b
@ -6,12 +6,19 @@
|
|||||||
|
|
||||||
### 不兼容性变更
|
### 不兼容性变更
|
||||||
|
|
||||||
该版本修改了同步协议逻辑,至少需要PC端v2.4.0或移动端v1.0.7版本才能连接使用。
|
该版本修改了同步协议逻辑,同步功能至少需要PC端v2.4.0或移动端v1.1.0或同步服务v2.0.0版本才能连接使用
|
||||||
|
|
||||||
|
### 新增
|
||||||
|
|
||||||
|
- 新增列表设置-是否显示歌曲专辑名,默认关闭
|
||||||
|
- 新增列表设置-是否显示歌曲时长,默认开启
|
||||||
|
|
||||||
### 优化
|
### 优化
|
||||||
|
|
||||||
- 优化歌单列表歌单封面大小计算方式
|
- 优化歌单列表歌单封面大小计算方式
|
||||||
- 调整竖屏下的排行榜布局
|
- 调整竖屏下的排行榜布局
|
||||||
|
- 调整歌曲列表信息布局
|
||||||
|
- 调整横屏下的歌曲列表为两列
|
||||||
- 调整桌面歌词主题配色,增强歌词字体阴影(#276)
|
- 调整桌面歌词主题配色,增强歌词字体阴影(#276)
|
||||||
- 优化数据传输逻辑,列表同步指令使用队列机制,保证列表同步操作的顺序
|
- 优化数据传输逻辑,列表同步指令使用队列机制,保证列表同步操作的顺序
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import { FlatList, type FlatListProps, RefreshControl, View } from 'react-native
|
|||||||
|
|
||||||
// import { useMusicList } from '@/store/list/hook'
|
// import { useMusicList } from '@/store/list/hook'
|
||||||
import ListItem, { ITEM_HEIGHT } from './ListItem'
|
import ListItem, { ITEM_HEIGHT } from './ListItem'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle, getRowInfo, type RowInfoType } from '@/utils/tools'
|
||||||
import type { Position } from './ListMenu'
|
import type { Position } from './ListMenu'
|
||||||
import type { SelectMode } from './MultipleModeBar'
|
import type { SelectMode } from './MultipleModeBar'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
@ -12,9 +12,14 @@ import { MULTI_SELECT_BAR_HEIGHT } from './MultipleModeBar'
|
|||||||
import { useI18n } from '@/lang'
|
import { useI18n } from '@/lang'
|
||||||
import Text from '@/components/common/Text'
|
import Text from '@/components/common/Text'
|
||||||
import { handlePlay } from './listAction'
|
import { handlePlay } from './listAction'
|
||||||
|
import { useSettingValue } from '@/store/setting/hook'
|
||||||
|
|
||||||
type FlatListType = FlatListProps<LX.Music.MusicInfoOnline>
|
type FlatListType = FlatListProps<LX.Music.MusicInfoOnline>
|
||||||
|
|
||||||
|
export type {
|
||||||
|
RowInfoType,
|
||||||
|
}
|
||||||
|
|
||||||
export interface ListProps {
|
export interface ListProps {
|
||||||
onShowMenu: (musicInfo: LX.Music.MusicInfoOnline, index: number, position: Position) => void
|
onShowMenu: (musicInfo: LX.Music.MusicInfoOnline, index: number, position: Position) => void
|
||||||
onMuiltSelectMode: () => void
|
onMuiltSelectMode: () => void
|
||||||
@ -25,6 +30,7 @@ export interface ListProps {
|
|||||||
progressViewOffset?: number
|
progressViewOffset?: number
|
||||||
ListHeaderComponent?: FlatListType['ListEmptyComponent']
|
ListHeaderComponent?: FlatListType['ListEmptyComponent']
|
||||||
checkHomePagerIdle: boolean
|
checkHomePagerIdle: boolean
|
||||||
|
rowType?: RowInfoType
|
||||||
}
|
}
|
||||||
export interface ListType {
|
export interface ListType {
|
||||||
setList: (list: LX.Music.MusicInfoOnline[], isAppend: boolean, showSource: boolean) => void
|
setList: (list: LX.Music.MusicInfoOnline[], isAppend: boolean, showSource: boolean) => void
|
||||||
@ -48,6 +54,7 @@ const List = forwardRef<ListType, ListProps>(({
|
|||||||
progressViewOffset,
|
progressViewOffset,
|
||||||
ListHeaderComponent,
|
ListHeaderComponent,
|
||||||
checkHomePagerIdle,
|
checkHomePagerIdle,
|
||||||
|
rowType,
|
||||||
}, ref) => {
|
}, ref) => {
|
||||||
// const t = useI18n()
|
// const t = useI18n()
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
@ -61,6 +68,9 @@ const List = forwardRef<ListType, ListProps>(({
|
|||||||
const selectedListRef = useRef<LX.Music.MusicInfoOnline[]>([])
|
const selectedListRef = useRef<LX.Music.MusicInfoOnline[]>([])
|
||||||
const [visibleMultiSelect, setVisibleMultiSelect] = useState(false)
|
const [visibleMultiSelect, setVisibleMultiSelect] = useState(false)
|
||||||
const [status, setStatus] = useState<Status>('idle')
|
const [status, setStatus] = useState<Status>('idle')
|
||||||
|
const rowInfo = useRef(getRowInfo(rowType))
|
||||||
|
const isShowAlbumName = useSettingValue('list.isShowAlbumName')
|
||||||
|
const isShowInterval = useSettingValue('list.isShowInterval')
|
||||||
// const currentListIdRef = useRef('')
|
// const currentListIdRef = useRef('')
|
||||||
// console.log('render music list')
|
// console.log('render music list')
|
||||||
|
|
||||||
@ -179,6 +189,9 @@ const List = forwardRef<ListType, ListProps>(({
|
|||||||
onLongPress={handleLongPress}
|
onLongPress={handleLongPress}
|
||||||
onShowMenu={onShowMenu}
|
onShowMenu={onShowMenu}
|
||||||
selectedList={selectedList}
|
selectedList={selectedList}
|
||||||
|
rowInfo={rowInfo.current}
|
||||||
|
isShowAlbumName={isShowAlbumName}
|
||||||
|
isShowInterval={isShowInterval}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
const getkey: FlatListType['keyExtractor'] = item => item.id
|
const getkey: FlatListType['keyExtractor'] = item => item.id
|
||||||
@ -221,6 +234,8 @@ const List = forwardRef<ListType, ListProps>(({
|
|||||||
ref={flatListRef}
|
ref={flatListRef}
|
||||||
style={styles.list}
|
style={styles.list}
|
||||||
data={currentList}
|
data={currentList}
|
||||||
|
numColumns={rowInfo.current.rowNum}
|
||||||
|
horizontal={false}
|
||||||
maxToRenderPerBatch={4}
|
maxToRenderPerBatch={4}
|
||||||
// updateCellsBatchingPeriod={80}
|
// updateCellsBatchingPeriod={80}
|
||||||
windowSize={8}
|
windowSize={8}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { memo, useRef } from 'react'
|
import React, { memo, useRef } from 'react'
|
||||||
import { StyleSheet, View, TouchableOpacity } from 'react-native'
|
import { View, TouchableOpacity } from 'react-native'
|
||||||
// import Button from '@/components/common/Button'
|
// import Button from '@/components/common/Button'
|
||||||
import Text from '@/components/common/Text'
|
import Text from '@/components/common/Text'
|
||||||
import Badge, { type BadgeType } from '@/components/common/Badge'
|
import Badge, { type BadgeType } from '@/components/common/Badge'
|
||||||
@ -8,6 +8,7 @@ import { useI18n } from '@/lang'
|
|||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
import { scaleSizeH } from '@/utils/pixelRatio'
|
import { scaleSizeH } from '@/utils/pixelRatio'
|
||||||
import { LIST_ITEM_HEIGHT } from '@/config/constant'
|
import { LIST_ITEM_HEIGHT } from '@/config/constant'
|
||||||
|
import { createStyle, type RowInfo } from '@/utils/tools'
|
||||||
|
|
||||||
export const ITEM_HEIGHT = scaleSizeH(LIST_ITEM_HEIGHT)
|
export const ITEM_HEIGHT = scaleSizeH(LIST_ITEM_HEIGHT)
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ const useQualityTag = (musicInfo: LX.Music.MusicInfoOnline) => {
|
|||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(({ item, index, showSource, onPress, onLongPress, onShowMenu, selectedList }: {
|
export default memo(({ item, index, showSource, onPress, onLongPress, onShowMenu, selectedList, rowInfo, isShowAlbumName, isShowInterval }: {
|
||||||
item: LX.Music.MusicInfoOnline
|
item: LX.Music.MusicInfoOnline
|
||||||
index: number
|
index: number
|
||||||
showSource?: boolean
|
showSource?: boolean
|
||||||
@ -36,6 +37,9 @@ export default memo(({ item, index, showSource, onPress, onLongPress, onShowMenu
|
|||||||
onLongPress: (item: LX.Music.MusicInfoOnline, index: number) => void
|
onLongPress: (item: LX.Music.MusicInfoOnline, index: number) => void
|
||||||
onShowMenu: (item: LX.Music.MusicInfoOnline, index: number, position: { x: number, y: number, w: number, h: number }) => void
|
onShowMenu: (item: LX.Music.MusicInfoOnline, index: number, position: { x: number, y: number, w: number, h: number }) => void
|
||||||
selectedList: LX.Music.MusicInfoOnline[]
|
selectedList: LX.Music.MusicInfoOnline[]
|
||||||
|
rowInfo: RowInfo
|
||||||
|
isShowAlbumName: boolean
|
||||||
|
isShowInterval: boolean
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
@ -52,18 +56,25 @@ export default memo(({ item, index, showSource, onPress, onLongPress, onShowMenu
|
|||||||
}
|
}
|
||||||
const tagInfo = useQualityTag(item)
|
const tagInfo = useQualityTag(item)
|
||||||
|
|
||||||
|
const singer = `${item.singer}${isShowAlbumName && item.meta.albumName ? ` · ${item.meta.albumName}` : ''}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ ...styles.listItem, height: ITEM_HEIGHT, backgroundColor: isSelected ? theme['c-primary-background-hover'] : 'rgba(0,0,0,0)' }}>
|
<View style={{ ...styles.listItem, width: rowInfo.rowWidth, height: ITEM_HEIGHT, backgroundColor: isSelected ? theme['c-primary-background-hover'] : 'rgba(0,0,0,0)' }}>
|
||||||
<TouchableOpacity style={styles.listItemLeft} onPress={() => { onPress(item, index) }} onLongPress={() => { onLongPress(item, index) }}>
|
<TouchableOpacity style={styles.listItemLeft} onPress={() => { onPress(item, index) }} onLongPress={() => { onLongPress(item, index) }}>
|
||||||
<Text style={styles.sn} size={13} color={theme['c-300']}>{index + 1}</Text>
|
<Text style={styles.sn} size={13} color={theme['c-300']}>{index + 1}</Text>
|
||||||
<View style={styles.itemInfo}>
|
<View style={styles.itemInfo}>
|
||||||
<Text numberOfLines={1}>{item.name}</Text>
|
<Text numberOfLines={1}>{item.name}</Text>
|
||||||
<View style={styles.listItemSingle}>
|
<View style={styles.listItemSingle}>
|
||||||
<Text style={styles.listItemSingleText} size={13} color={theme['c-500']} numberOfLines={1}>{item.singer}</Text>
|
|
||||||
{ tagInfo.type ? <Badge type={tagInfo.type}>{tagInfo.text}</Badge> : null }
|
{ tagInfo.type ? <Badge type={tagInfo.type}>{tagInfo.text}</Badge> : null }
|
||||||
{ showSource ? <Badge type="tertiary">{item.source}</Badge> : null }
|
{ showSource ? <Badge type="tertiary">{item.source}</Badge> : null }
|
||||||
|
<Text style={styles.listItemSingleText} size={11} color={theme['c-500']} numberOfLines={1}>{singer}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
{
|
||||||
|
isShowInterval ? (
|
||||||
|
<Text size={12} color={theme['c-300']} numberOfLines={1}>{item.interval}</Text>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={handleShowMenu} ref={moreButtonRef} style={styles.moreButton}>
|
<TouchableOpacity onPress={handleShowMenu} ref={moreButtonRef} style={styles.moreButton}>
|
||||||
<Icon name="dots-vertical" style={{ color: theme['c-350'] }} size={12} />
|
<Icon name="dots-vertical" style={{ color: theme['c-350'] }} size={12} />
|
||||||
@ -77,9 +88,9 @@ export default memo(({ item, index, showSource, onPress, onLongPress, onShowMenu
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = createStyle({
|
||||||
listItem: {
|
listItem: {
|
||||||
width: '100%',
|
// width: '100%',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'nowrap',
|
flexWrap: 'nowrap',
|
||||||
// paddingLeft: 10,
|
// paddingLeft: 10,
|
||||||
@ -103,8 +114,9 @@ const styles = StyleSheet.create({
|
|||||||
paddingRight: 3,
|
paddingRight: 3,
|
||||||
},
|
},
|
||||||
itemInfo: {
|
itemInfo: {
|
||||||
flexGrow: 0,
|
flexGrow: 1,
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
|
paddingRight: 2,
|
||||||
// paddingTop: 10,
|
// paddingTop: 10,
|
||||||
// paddingBottom: 10,
|
// paddingBottom: 10,
|
||||||
},
|
},
|
||||||
@ -117,14 +129,20 @@ const styles = StyleSheet.create({
|
|||||||
listItemSingle: {
|
listItemSingle: {
|
||||||
paddingTop: 2,
|
paddingTop: 2,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
// alignItems: 'flex-end',
|
// alignItems: 'flex-end',
|
||||||
// backgroundColor: 'rgba(0,0,0,0.2)',
|
// backgroundColor: 'rgba(0,0,0,0.2)',
|
||||||
},
|
},
|
||||||
|
listItemTimeLabel: {
|
||||||
|
marginRight: 5,
|
||||||
|
fontWeight: '400',
|
||||||
|
},
|
||||||
listItemSingleText: {
|
listItemSingleText: {
|
||||||
// fontSize: 13,
|
// fontSize: 13,
|
||||||
// paddingTop: 2,
|
// paddingTop: 2,
|
||||||
flexGrow: 0,
|
flexGrow: 0,
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
|
fontWeight: '300',
|
||||||
},
|
},
|
||||||
listItemBadge: {
|
listItemBadge: {
|
||||||
// fontSize: 10,
|
// fontSize: 10,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useRef, forwardRef, useImperativeHandle } from 'react'
|
import React, { useRef, forwardRef, useImperativeHandle } from 'react'
|
||||||
import { View } from 'react-native'
|
import { View } from 'react-native'
|
||||||
// import LoadingMask, { LoadingMaskType } from '@/components/common/LoadingMask'
|
// import LoadingMask, { LoadingMaskType } from '@/components/common/LoadingMask'
|
||||||
import List, { type ListProps, type ListType, type Status } from './List'
|
import List, { type ListProps, type ListType, type Status, type RowInfoType } from './List'
|
||||||
import ListMenu, { type ListMenuType, type Position, type SelectInfo } from './ListMenu'
|
import ListMenu, { type ListMenuType, type Position, type SelectInfo } from './ListMenu'
|
||||||
import ListMusicMultiAdd, { type MusicMultiAddModalType as ListAddMultiType } from '@/components/MusicMultiAddModal'
|
import ListMusicMultiAdd, { type MusicMultiAddModalType as ListAddMultiType } from '@/components/MusicMultiAddModal'
|
||||||
import ListMusicAdd, { type MusicAddModalType as ListMusicAddType } from '@/components/MusicAddModal'
|
import ListMusicAdd, { type MusicAddModalType as ListMusicAddType } from '@/components/MusicAddModal'
|
||||||
@ -16,6 +16,7 @@ export interface OnlineListProps {
|
|||||||
progressViewOffset?: ListProps['progressViewOffset']
|
progressViewOffset?: ListProps['progressViewOffset']
|
||||||
ListHeaderComponent?: ListProps['ListHeaderComponent']
|
ListHeaderComponent?: ListProps['ListHeaderComponent']
|
||||||
checkHomePagerIdle?: boolean
|
checkHomePagerIdle?: boolean
|
||||||
|
rowType?: RowInfoType
|
||||||
}
|
}
|
||||||
export interface OnlineListType {
|
export interface OnlineListType {
|
||||||
setList: (list: LX.Music.MusicInfoOnline[], isAppend?: boolean, showSource?: boolean) => void
|
setList: (list: LX.Music.MusicInfoOnline[], isAppend?: boolean, showSource?: boolean) => void
|
||||||
@ -29,6 +30,7 @@ export default forwardRef<OnlineListType, OnlineListProps>(({
|
|||||||
progressViewOffset,
|
progressViewOffset,
|
||||||
ListHeaderComponent,
|
ListHeaderComponent,
|
||||||
checkHomePagerIdle = false,
|
checkHomePagerIdle = false,
|
||||||
|
rowType,
|
||||||
}, ref) => {
|
}, ref) => {
|
||||||
const listRef = useRef<ListType>(null)
|
const listRef = useRef<ListType>(null)
|
||||||
const multipleModeBarRef = useRef<MultipleModeBarType>(null)
|
const multipleModeBarRef = useRef<MultipleModeBarType>(null)
|
||||||
@ -90,6 +92,7 @@ export default forwardRef<OnlineListType, OnlineListProps>(({
|
|||||||
progressViewOffset={progressViewOffset}
|
progressViewOffset={progressViewOffset}
|
||||||
ListHeaderComponent={ListHeaderComponent}
|
ListHeaderComponent={ListHeaderComponent}
|
||||||
checkHomePagerIdle={checkHomePagerIdle}
|
checkHomePagerIdle={checkHomePagerIdle}
|
||||||
|
rowType={rowType}
|
||||||
/>
|
/>
|
||||||
<MultipleModeBar
|
<MultipleModeBar
|
||||||
ref={multipleModeBarRef}
|
ref={multipleModeBarRef}
|
||||||
|
@ -12,7 +12,8 @@ const styles = createStyle({
|
|||||||
// borderRadius: 2,
|
// borderRadius: 2,
|
||||||
// lineHeight: 12,
|
// lineHeight: 12,
|
||||||
// marginTop: 2,
|
// marginTop: 2,
|
||||||
marginLeft: 5,
|
marginRight: 5,
|
||||||
|
fontWeight: '400',
|
||||||
// marginRight: 5,
|
// marginRight: 5,
|
||||||
// marginBottom: 2,
|
// marginBottom: 2,
|
||||||
// alignSelf: 'flex-start',
|
// alignSelf: 'flex-start',
|
||||||
|
@ -53,6 +53,8 @@ const defaultSetting: LX.AppSetting = {
|
|||||||
|
|
||||||
'list.isClickPlayList': false,
|
'list.isClickPlayList': false,
|
||||||
'list.isShowSource': true,
|
'list.isShowSource': true,
|
||||||
|
'list.isShowAlbumName': false,
|
||||||
|
'list.isShowInterval': true,
|
||||||
'list.isSaveScrollLocation': true,
|
'list.isSaveScrollLocation': true,
|
||||||
'list.addMusicLocationType': 'top',
|
'list.addMusicLocationType': 'top',
|
||||||
|
|
||||||
|
@ -212,6 +212,8 @@
|
|||||||
"setting_list_add_music_location_type_bottom": "Bottom",
|
"setting_list_add_music_location_type_bottom": "Bottom",
|
||||||
"setting_list_add_music_location_type_top": "Top",
|
"setting_list_add_music_location_type_top": "Top",
|
||||||
"setting_list_click_action": "When you click a song in the list, it will automatically switch to the current list for playback (only valid for playlists and leaderboards)",
|
"setting_list_click_action": "When you click a song in the list, it will automatically switch to the current list for playback (only valid for playlists and leaderboards)",
|
||||||
|
"setting_list_show interval": "Show song duration",
|
||||||
|
"setting_list_show_album_name": "Show song album name",
|
||||||
"setting_lyric_dektop_permission_tip": "The desktop lyrics function needs to be granted the permission of LX Music to display the floating window in the system permission setting before it can be used. Do you go to the relevant interface to grant this permission?",
|
"setting_lyric_dektop_permission_tip": "The desktop lyrics function needs to be granted the permission of LX Music to display the floating window in the system permission setting before it can be used. Do you go to the relevant interface to grant this permission?",
|
||||||
"setting_lyric_desktop": "Desktop lyrics",
|
"setting_lyric_desktop": "Desktop lyrics",
|
||||||
"setting_lyric_desktop_enable": "Show desktop lyrics",
|
"setting_lyric_desktop_enable": "Show desktop lyrics",
|
||||||
|
@ -212,6 +212,8 @@
|
|||||||
"setting_list_add_music_location_type_bottom": "底部",
|
"setting_list_add_music_location_type_bottom": "底部",
|
||||||
"setting_list_add_music_location_type_top": "顶部",
|
"setting_list_add_music_location_type_top": "顶部",
|
||||||
"setting_list_click_action": "点击列表里的歌曲时自动切换到当前列表播放(仅对歌单、排行榜有效)",
|
"setting_list_click_action": "点击列表里的歌曲时自动切换到当前列表播放(仅对歌单、排行榜有效)",
|
||||||
|
"setting_list_show interval": "显示歌曲时长",
|
||||||
|
"setting_list_show_album_name": "显示歌曲专辑名",
|
||||||
"setting_lyric_dektop_permission_tip": "桌面歌词功能需要在系统权限设置中授予LX Music显示悬浮窗口的权限才能使用,是否去相关界面授予此权限?",
|
"setting_lyric_dektop_permission_tip": "桌面歌词功能需要在系统权限设置中授予LX Music显示悬浮窗口的权限才能使用,是否去相关界面授予此权限?",
|
||||||
"setting_lyric_desktop": "桌面歌词",
|
"setting_lyric_desktop": "桌面歌词",
|
||||||
"setting_lyric_desktop_enable": "显示桌面歌词",
|
"setting_lyric_desktop_enable": "显示桌面歌词",
|
||||||
|
@ -90,6 +90,7 @@ export default forwardRef<MusicListType, {}>((props, ref) => {
|
|||||||
onRefresh={handleRefresh}
|
onRefresh={handleRefresh}
|
||||||
onLoadMore={handleLoadMore}
|
onLoadMore={handleLoadMore}
|
||||||
checkHomePagerIdle
|
checkHomePagerIdle
|
||||||
|
rowType='medium'
|
||||||
/>
|
/>
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -8,11 +8,12 @@ import { getListPosition, getListPrevSelectId, saveListPosition } from '@/utils/
|
|||||||
// import { useMusicList } from '@/store/list/hook'
|
// import { useMusicList } from '@/store/list/hook'
|
||||||
import { getListMusics, setActiveList } from '@/core/list'
|
import { getListMusics, setActiveList } from '@/core/list'
|
||||||
import ListItem, { ITEM_HEIGHT } from './ListItem'
|
import ListItem, { ITEM_HEIGHT } from './ListItem'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle, getRowInfo } from '@/utils/tools'
|
||||||
import { usePlayInfo, usePlayMusicInfo } from '@/store/player/hook'
|
import { usePlayInfo, usePlayMusicInfo } from '@/store/player/hook'
|
||||||
import type { Position } from './ListMenu'
|
import type { Position } from './ListMenu'
|
||||||
import type { SelectMode } from './MultipleModeBar'
|
import type { SelectMode } from './MultipleModeBar'
|
||||||
import { useActiveListId } from '@/store/list/hook'
|
import { useActiveListId } from '@/store/list/hook'
|
||||||
|
import { useSettingValue } from '@/store/setting/hook'
|
||||||
|
|
||||||
type FlatListType = FlatListProps<LX.Music.MusicInfo>
|
type FlatListType = FlatListProps<LX.Music.MusicInfo>
|
||||||
|
|
||||||
@ -54,6 +55,9 @@ const List = forwardRef<ListType, ListProps>(({ onShowMenu, onMuiltSelectMode, o
|
|||||||
const selectedListRef = useRef<LX.List.ListMusics>([])
|
const selectedListRef = useRef<LX.List.ListMusics>([])
|
||||||
const currentListIdRef = useRef('')
|
const currentListIdRef = useRef('')
|
||||||
const waitJumpListPositionRef = useRef(false)
|
const waitJumpListPositionRef = useRef(false)
|
||||||
|
const rowInfo = useRef(getRowInfo())
|
||||||
|
const isShowAlbumName = useSettingValue('list.isShowAlbumName')
|
||||||
|
const isShowInterval = useSettingValue('list.isShowInterval')
|
||||||
// console.log('render music list')
|
// console.log('render music list')
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
@ -84,7 +88,7 @@ const List = forwardRef<ListType, ListProps>(({ onShowMenu, onMuiltSelectMode, o
|
|||||||
void getListMusics(listState.activeListId).then((list) => {
|
void getListMusics(listState.activeListId).then((list) => {
|
||||||
const index = list.findIndex(m => m.id == info.id)
|
const index = list.findIndex(m => m.id == info.id)
|
||||||
if (index < 0) return
|
if (index < 0) return
|
||||||
flatListRef.current?.scrollToIndex({ index, viewPosition: 0.3, animated: true })
|
flatListRef.current?.scrollToIndex({ index: Math.floor(index / (rowInfo.current.rowNum ?? 1)), viewPosition: 0.3, animated: true })
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
@ -110,7 +114,7 @@ const List = forwardRef<ListType, ListProps>(({ onShowMenu, onMuiltSelectMode, o
|
|||||||
waitJumpListPositionRef.current = false
|
waitJumpListPositionRef.current = false
|
||||||
if (playerState.playMusicInfo.listId == id && playerState.playInfo.playIndex > -1) {
|
if (playerState.playMusicInfo.listId == id && playerState.playInfo.playIndex > -1) {
|
||||||
try {
|
try {
|
||||||
flatListRef.current?.scrollToIndex({ index: playerState.playInfo.playIndex, viewPosition: 0.3, animated: false })
|
flatListRef.current?.scrollToIndex({ index: Math.floor(playerState.playInfo.playIndex / (rowInfo.current.rowNum ?? 1)), viewPosition: 0.3, animated: false })
|
||||||
return
|
return
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
@ -143,7 +147,7 @@ const List = forwardRef<ListType, ListProps>(({ onShowMenu, onMuiltSelectMode, o
|
|||||||
if (isUpdateingList) waitJumpListPositionRef.current = true
|
if (isUpdateingList) waitJumpListPositionRef.current = true
|
||||||
else {
|
else {
|
||||||
try {
|
try {
|
||||||
flatListRef.current?.scrollToIndex({ index: playerState.playInfo.playIndex, viewPosition: 0.3, animated: true })
|
flatListRef.current?.scrollToIndex({ index: Math.floor(playerState.playInfo.playIndex / (rowInfo.current.rowNum ?? 1)), viewPosition: 0.3, animated: true })
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,6 +253,9 @@ const List = forwardRef<ListType, ListProps>(({ onShowMenu, onMuiltSelectMode, o
|
|||||||
onLongPress={handleLongPress}
|
onLongPress={handleLongPress}
|
||||||
onShowMenu={onShowMenu}
|
onShowMenu={onShowMenu}
|
||||||
selectedList={selectedList}
|
selectedList={selectedList}
|
||||||
|
rowInfo={rowInfo.current}
|
||||||
|
isShowAlbumName={isShowAlbumName}
|
||||||
|
isShowInterval={isShowInterval}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
const getkey: FlatListType['keyExtractor'] = item => item.id
|
const getkey: FlatListType['keyExtractor'] = item => item.id
|
||||||
@ -263,6 +270,8 @@ const List = forwardRef<ListType, ListProps>(({ onShowMenu, onMuiltSelectMode, o
|
|||||||
style={styles.list}
|
style={styles.list}
|
||||||
data={currentList}
|
data={currentList}
|
||||||
maxToRenderPerBatch={4}
|
maxToRenderPerBatch={4}
|
||||||
|
numColumns={rowInfo.current.rowNum}
|
||||||
|
horizontal={false}
|
||||||
// updateCellsBatchingPeriod={80}
|
// updateCellsBatchingPeriod={80}
|
||||||
windowSize={8}
|
windowSize={8}
|
||||||
removeClippedSubviews={true}
|
removeClippedSubviews={true}
|
||||||
|
@ -3,7 +3,7 @@ import { View, TouchableOpacity } from 'react-native'
|
|||||||
import { LIST_ITEM_HEIGHT } from '@/config/constant'
|
import { LIST_ITEM_HEIGHT } from '@/config/constant'
|
||||||
// import { BorderWidths } from '@/theme'
|
// import { BorderWidths } from '@/theme'
|
||||||
import { Icon } from '@/components/common/Icon'
|
import { Icon } from '@/components/common/Icon'
|
||||||
import { createStyle } from '@/utils/tools'
|
import { createStyle, type RowInfo } from '@/utils/tools'
|
||||||
import { useTheme } from '@/store/theme/hook'
|
import { useTheme } from '@/store/theme/hook'
|
||||||
import { useAssertApiSupport } from '@/store/common/hook'
|
import { useAssertApiSupport } from '@/store/common/hook'
|
||||||
import { scaleSizeH } from '@/utils/pixelRatio'
|
import { scaleSizeH } from '@/utils/pixelRatio'
|
||||||
@ -12,7 +12,8 @@ import Badge from '@/components/common/Badge'
|
|||||||
|
|
||||||
export const ITEM_HEIGHT = scaleSizeH(LIST_ITEM_HEIGHT)
|
export const ITEM_HEIGHT = scaleSizeH(LIST_ITEM_HEIGHT)
|
||||||
|
|
||||||
export default memo(({ item, index, activeIndex, onPress, onShowMenu, onLongPress, selectedList }: {
|
|
||||||
|
export default memo(({ item, index, activeIndex, onPress, onShowMenu, onLongPress, selectedList, rowInfo, isShowAlbumName, isShowInterval }: {
|
||||||
item: LX.Music.MusicInfo
|
item: LX.Music.MusicInfo
|
||||||
index: number
|
index: number
|
||||||
activeIndex: number
|
activeIndex: number
|
||||||
@ -20,6 +21,9 @@ export default memo(({ item, index, activeIndex, onPress, onShowMenu, onLongPres
|
|||||||
onLongPress: (item: LX.Music.MusicInfo, index: number) => void
|
onLongPress: (item: LX.Music.MusicInfo, index: number) => void
|
||||||
onShowMenu: (item: LX.Music.MusicInfo, index: number, position: { x: number, y: number, w: number, h: number }) => void
|
onShowMenu: (item: LX.Music.MusicInfo, index: number, position: { x: number, y: number, w: number, h: number }) => void
|
||||||
selectedList: LX.Music.MusicInfo[]
|
selectedList: LX.Music.MusicInfo[]
|
||||||
|
rowInfo: RowInfo
|
||||||
|
isShowAlbumName: boolean
|
||||||
|
isShowInterval: boolean
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
|
|
||||||
@ -37,8 +41,10 @@ export default memo(({ item, index, activeIndex, onPress, onShowMenu, onLongPres
|
|||||||
}
|
}
|
||||||
const active = activeIndex == index
|
const active = activeIndex == index
|
||||||
|
|
||||||
|
const singer = `${item.singer}${isShowAlbumName && item.meta.albumName ? ` · ${item.meta.albumName}` : ''}`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ ...styles.listItem, height: ITEM_HEIGHT, backgroundColor: isSelected ? theme['c-primary-background-hover'] : 'rgba(0,0,0,0)', opacity: isSupported ? 1 : 0.5 }}>
|
<View style={{ ...styles.listItem, width: rowInfo.rowWidth, height: ITEM_HEIGHT, backgroundColor: isSelected ? theme['c-primary-background-hover'] : 'rgba(0,0,0,0)', opacity: isSupported ? 1 : 0.5 }}>
|
||||||
<TouchableOpacity style={styles.listItemLeft} onPress={() => { onPress(item, index) }} onLongPress={() => { onLongPress(item, index) }}>
|
<TouchableOpacity style={styles.listItemLeft} onPress={() => { onPress(item, index) }} onLongPress={() => { onLongPress(item, index) }}>
|
||||||
{
|
{
|
||||||
active
|
active
|
||||||
@ -50,10 +56,17 @@ export default memo(({ item, index, activeIndex, onPress, onShowMenu, onLongPres
|
|||||||
<Text color={active ? theme['c-primary-font'] : theme['c-font']} numberOfLines={1}>{item.name}</Text>
|
<Text color={active ? theme['c-primary-font'] : theme['c-font']} numberOfLines={1}>{item.name}</Text>
|
||||||
{/* </View> */}
|
{/* </View> */}
|
||||||
<View style={styles.listItemSingle}>
|
<View style={styles.listItemSingle}>
|
||||||
<Text style={styles.listItemSingleText} size={13} color={active ? theme['c-primary-alpha-200'] : theme['c-500']} numberOfLines={1}>{item.singer}</Text>
|
<Badge>{item.source.toUpperCase()}</Badge>
|
||||||
<Badge>{item.source}</Badge>
|
<Text style={styles.listItemSingleText} size={11} color={active ? theme['c-primary-alpha-200'] : theme['c-500']} numberOfLines={1}>
|
||||||
|
{singer}
|
||||||
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
{
|
||||||
|
isShowInterval ? (
|
||||||
|
<Text size={12} color={active ? theme['c-primary-alpha-200'] : theme['c-300']} numberOfLines={1}>{item.interval}</Text>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
{/* <View style={styles.listItemRight}> */}
|
{/* <View style={styles.listItemRight}> */}
|
||||||
<TouchableOpacity onPress={handleShowMenu} ref={moreButtonRef} style={styles.moreButton}>
|
<TouchableOpacity onPress={handleShowMenu} ref={moreButtonRef} style={styles.moreButton}>
|
||||||
@ -66,6 +79,8 @@ export default memo(({ item, index, activeIndex, onPress, onShowMenu, onLongPres
|
|||||||
return !!(prevProps.item === nextProps.item &&
|
return !!(prevProps.item === nextProps.item &&
|
||||||
prevProps.index === nextProps.index &&
|
prevProps.index === nextProps.index &&
|
||||||
prevProps.activeIndex != nextProps.index &&
|
prevProps.activeIndex != nextProps.index &&
|
||||||
|
prevProps.isShowAlbumName != nextProps.isShowAlbumName &&
|
||||||
|
prevProps.isShowInterval != nextProps.isShowInterval &&
|
||||||
nextProps.activeIndex != nextProps.index &&
|
nextProps.activeIndex != nextProps.index &&
|
||||||
nextProps.selectedList.includes(nextProps.item) == prevProps.selectedList.includes(nextProps.item)
|
nextProps.selectedList.includes(nextProps.item) == prevProps.selectedList.includes(nextProps.item)
|
||||||
)
|
)
|
||||||
@ -74,7 +89,7 @@ export default memo(({ item, index, activeIndex, onPress, onShowMenu, onLongPres
|
|||||||
|
|
||||||
const styles = createStyle({
|
const styles = createStyle({
|
||||||
listItem: {
|
listItem: {
|
||||||
width: '100%',
|
// width: '50%',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'nowrap',
|
flexWrap: 'nowrap',
|
||||||
// paddingLeft: 10,
|
// paddingLeft: 10,
|
||||||
@ -98,17 +113,18 @@ const styles = createStyle({
|
|||||||
paddingRight: 3,
|
paddingRight: 3,
|
||||||
},
|
},
|
||||||
itemInfo: {
|
itemInfo: {
|
||||||
flexGrow: 0,
|
flexGrow: 1,
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
// paddingTop: 10,
|
// paddingTop: 10,
|
||||||
// paddingBottom: 10,
|
// paddingBottom: 10,
|
||||||
|
paddingRight: 2,
|
||||||
},
|
},
|
||||||
// listItemTitle: {
|
// listItemTitle: {
|
||||||
// flexGrow: 0,
|
// flexGrow: 0,
|
||||||
// flexShrink: 1,
|
// flexShrink: 1,
|
||||||
// },
|
// },
|
||||||
listItemSingle: {
|
listItemSingle: {
|
||||||
paddingTop: 2,
|
paddingTop: 3,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
// alignItems: 'flex-end',
|
// alignItems: 'flex-end',
|
||||||
},
|
},
|
||||||
@ -116,14 +132,15 @@ const styles = createStyle({
|
|||||||
// backgroundColor: 'rgba(0,0,0,0.2)',
|
// backgroundColor: 'rgba(0,0,0,0.2)',
|
||||||
flexGrow: 0,
|
flexGrow: 0,
|
||||||
flexShrink: 1,
|
flexShrink: 1,
|
||||||
|
fontWeight: '300',
|
||||||
// fontSize: 15,
|
// fontSize: 15,
|
||||||
},
|
},
|
||||||
listItemBadge: {
|
// listItemBadge: {
|
||||||
// fontSize: 10,
|
// // fontSize: 10,
|
||||||
paddingLeft: 5,
|
// paddingLeft: 5,
|
||||||
paddingTop: 2,
|
// paddingTop: 2,
|
||||||
alignSelf: 'flex-start',
|
// alignSelf: 'flex-start',
|
||||||
},
|
// },
|
||||||
listItemRight: {
|
listItemRight: {
|
||||||
flexGrow: 0,
|
flexGrow: 0,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
|
@ -26,7 +26,7 @@ export default memo(() => {
|
|||||||
const styles = createStyle({
|
const styles = createStyle({
|
||||||
content: {
|
content: {
|
||||||
marginTop: 5,
|
marginTop: 5,
|
||||||
marginBottom: 15,
|
// marginBottom: 15,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
import { updateSetting } from '@/core/common'
|
||||||
|
import { useI18n } from '@/lang'
|
||||||
|
import { createStyle } from '@/utils/tools'
|
||||||
|
import React, { memo } from 'react'
|
||||||
|
import { View } from 'react-native'
|
||||||
|
import { useSettingValue } from '@/store/setting/hook'
|
||||||
|
|
||||||
|
|
||||||
|
import CheckBoxItem from '../../components/CheckBoxItem'
|
||||||
|
|
||||||
|
export default memo(() => {
|
||||||
|
const t = useI18n()
|
||||||
|
const isShowAlbumName = useSettingValue('list.isShowAlbumName')
|
||||||
|
const setShowAlbumName = (isShowAlbumName: boolean) => {
|
||||||
|
updateSetting({ 'list.isShowAlbumName': isShowAlbumName })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.content}>
|
||||||
|
<CheckBoxItem check={isShowAlbumName} onChange={setShowAlbumName} label={t('setting_list_show_album_name')} />
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const styles = createStyle({
|
||||||
|
content: {
|
||||||
|
marginTop: 5,
|
||||||
|
// marginBottom: 15,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
import { updateSetting } from '@/core/common'
|
||||||
|
import { useI18n } from '@/lang'
|
||||||
|
import { createStyle } from '@/utils/tools'
|
||||||
|
import React, { memo } from 'react'
|
||||||
|
import { View } from 'react-native'
|
||||||
|
import { useSettingValue } from '@/store/setting/hook'
|
||||||
|
|
||||||
|
|
||||||
|
import CheckBoxItem from '../../components/CheckBoxItem'
|
||||||
|
|
||||||
|
export default memo(() => {
|
||||||
|
const t = useI18n()
|
||||||
|
const isShowInterval = useSettingValue('list.isShowInterval')
|
||||||
|
const setShowInterval = (isShowInterval: boolean) => {
|
||||||
|
updateSetting({ 'list.isShowInterval': isShowInterval })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.content}>
|
||||||
|
<CheckBoxItem check={isShowInterval} onChange={setShowInterval} label={t('setting_list_show interval')} />
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const styles = createStyle({
|
||||||
|
content: {
|
||||||
|
marginTop: 5,
|
||||||
|
marginBottom: 15,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
@ -3,6 +3,8 @@ import React, { memo } from 'react'
|
|||||||
import Section from '../../components/Section'
|
import Section from '../../components/Section'
|
||||||
import AddMusicLocationType from './AddMusicLocationType'
|
import AddMusicLocationType from './AddMusicLocationType'
|
||||||
import IsClickPlayList from './IsClickPlayList'
|
import IsClickPlayList from './IsClickPlayList'
|
||||||
|
import IsShowAlbumName from './IsShowAlbumName'
|
||||||
|
import IsShowInterval from './IsShowInterval'
|
||||||
|
|
||||||
import { useI18n } from '@/lang'
|
import { useI18n } from '@/lang'
|
||||||
|
|
||||||
@ -12,6 +14,8 @@ export default memo(() => {
|
|||||||
return (
|
return (
|
||||||
<Section title={t('setting_list')}>
|
<Section title={t('setting_list')}>
|
||||||
<IsClickPlayList />
|
<IsClickPlayList />
|
||||||
|
<IsShowAlbumName />
|
||||||
|
<IsShowInterval />
|
||||||
<AddMusicLocationType />
|
<AddMusicLocationType />
|
||||||
</Section>
|
</Section>
|
||||||
)
|
)
|
||||||
|
10
src/types/app_setting.d.ts
vendored
10
src/types/app_setting.d.ts
vendored
@ -266,6 +266,16 @@ declare global {
|
|||||||
*/
|
*/
|
||||||
'list.isShowSource': boolean
|
'list.isShowSource': boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否显示歌曲专辑名
|
||||||
|
*/
|
||||||
|
'list.isShowAlbumName': boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否显示歌曲时长
|
||||||
|
*/
|
||||||
|
'list.isShowInterval': boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否自动恢复列表滚动位置(仅对我的列表有效)
|
* 是否自动恢复列表滚动位置(仅对我的列表有效)
|
||||||
*/
|
*/
|
||||||
|
@ -423,4 +423,22 @@ export const createStyle = <T extends StyleSheet.NamedStyles<T>>(styles: T | Sty
|
|||||||
return StyleSheet.create(newStyle as StyleSheet.NamedStyles<T>)
|
return StyleSheet.create(newStyle as StyleSheet.NamedStyles<T>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RowInfo {
|
||||||
|
rowNum: number | undefined
|
||||||
|
rowWidth: `${number}%`
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RowInfoType = 'full' | 'medium'
|
||||||
|
|
||||||
|
export const getRowInfo = (type: RowInfoType = 'full'): RowInfo => {
|
||||||
|
const win = Dimensions.get('window')
|
||||||
|
let isMultiRow = win.width > win.height
|
||||||
|
if (type == 'medium' && win.width / win.height < 1.8) isMultiRow = false
|
||||||
|
// console.log('getRowInfo')
|
||||||
|
return {
|
||||||
|
rowNum: isMultiRow ? 2 : undefined,
|
||||||
|
rowWidth: isMultiRow ? '50%' : '100%',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const toMD5 = stringMd5
|
export const toMD5 = stringMd5
|
||||||
|
Loading…
x
Reference in New Issue
Block a user