mirror of
https://github.com/ikun0014/lx-music-mobile.git
synced 2025-07-03 19:32:09 +08:00
124 lines
3.6 KiB
TypeScript
124 lines
3.6 KiB
TypeScript
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'
|
|
import { View, ImageBackground, TouchableOpacity, InteractionManager, type ImageSourcePropType } from 'react-native'
|
|
import { setTheme } from '@/core/theme'
|
|
import { useI18n } from '@/lang'
|
|
import { useSettingValue } from '@/store/setting/hook'
|
|
import { useTheme } from '@/store/theme/hook'
|
|
|
|
import SubTitle from '../components/SubTitle'
|
|
import { BG_IMAGES, getAllThemes, type LocalTheme } from '@/theme/themes'
|
|
import Text from '@/components/common/Text'
|
|
import { createStyle } from '@/utils/tools'
|
|
import { scaleSizeH } from '@/utils/pixelRatio'
|
|
|
|
const useActive = (id: string) => {
|
|
const activeThemeId = useSettingValue('theme.id')
|
|
const isActive = useMemo(() => activeThemeId == id, [activeThemeId, id])
|
|
return isActive
|
|
}
|
|
|
|
const ThemeItem = ({ id, name, color, image, setTheme }: {
|
|
id: string
|
|
name: string
|
|
color: string
|
|
image?: ImageSourcePropType
|
|
setTheme: (id: string) => void
|
|
}) => {
|
|
const theme = useTheme()
|
|
const isActive = useActive(id)
|
|
|
|
return (
|
|
<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' }}>
|
|
{
|
|
image
|
|
? <ImageBackground style={{ ...styles.imageContent, width: scaleSizeH(IMAGE_HEIGHT), backgroundColor: color }}
|
|
source={image} borderRadius={4} />
|
|
: <View style={{ ...styles.imageContent, width: scaleSizeH(IMAGE_HEIGHT), backgroundColor: color }}></View>
|
|
}
|
|
</View>
|
|
<Text style={styles.name} size={12} color={isActive ? color : theme['c-font']} numberOfLines={1}>{name}</Text>
|
|
</TouchableOpacity>
|
|
)
|
|
}
|
|
|
|
interface ThemeInfo {
|
|
themes: Readonly<LocalTheme[]>
|
|
userThemes: LX.Theme[]
|
|
dataPath: string
|
|
}
|
|
const initInfo: ThemeInfo = { themes: [], userThemes: [], dataPath: '' }
|
|
export default memo(() => {
|
|
const t = useI18n()
|
|
const [themeInfo, setThemeInfo] = useState(initInfo)
|
|
const setThemeId = useCallback((id: string) => {
|
|
void InteractionManager.runAfterInteractions(() => {
|
|
setTheme(id)
|
|
})
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
void getAllThemes().then(setThemeInfo)
|
|
}, [])
|
|
|
|
return (
|
|
<SubTitle title={t('setting_basic_theme')}>
|
|
<View style={styles.list}>
|
|
{
|
|
themeInfo.themes.map(({ id, config }) => {
|
|
return <ThemeItem
|
|
key={id}
|
|
color={config.themeColors['c-theme']}
|
|
image={config.extInfo['bg-image'] ? BG_IMAGES[config.extInfo['bg-image']] : undefined}
|
|
id={id}
|
|
name={t(`theme_${id}`)}
|
|
setTheme={setThemeId} />
|
|
})
|
|
}
|
|
{
|
|
themeInfo.userThemes.map(({ id, name, config }) => {
|
|
return <ThemeItem
|
|
key={id}
|
|
color={config.themeColors['c-theme']}
|
|
// image={undefined}
|
|
id={id}
|
|
name={name}
|
|
setTheme={setThemeId} />
|
|
})
|
|
}
|
|
</View>
|
|
</SubTitle>
|
|
)
|
|
})
|
|
|
|
const ITEM_HEIGHT = 56
|
|
const COLOR_ITEM_HEIGHT = 34
|
|
const IMAGE_HEIGHT = 27
|
|
const styles = createStyle({
|
|
list: {
|
|
flexDirection: 'row',
|
|
flexWrap: 'wrap',
|
|
},
|
|
item: {
|
|
marginRight: 15,
|
|
alignItems: 'center',
|
|
marginTop: 5,
|
|
// backgroundColor: 'rgba(0,0,0,0.2)',
|
|
},
|
|
colorContent: {
|
|
height: COLOR_ITEM_HEIGHT,
|
|
borderRadius: 4,
|
|
borderWidth: 1.6,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
},
|
|
imageContent: {
|
|
height: IMAGE_HEIGHT,
|
|
borderRadius: 4,
|
|
// elevation: 1,
|
|
},
|
|
name: {
|
|
marginTop: 2,
|
|
},
|
|
})
|