新增APP全局字体阴影

This commit is contained in:
lyswhut 2023-12-23 14:34:41 +08:00
parent 634ebe71e9
commit eef6a189d8
18 changed files with 148 additions and 51 deletions

View File

@ -5,6 +5,7 @@
- 新增实验性的添加本地歌曲到我的收藏支持与PC端类似在我的收藏的列表菜单中选择歌曲目录将添加所选目录下的所有歌曲目前支持mp3/flac/ogg/wav等格式
- 新增歌曲标签编辑功能,允许编辑本地源且文件歌曲存在的歌曲标签信息
- 新增动态背景默认关闭启用后将使用当前歌曲封面做APP背景
- 新增APP全局字体阴影默认开启可到设置-主题设置关闭
### 优化

View File

@ -1,8 +1,9 @@
import { createIconSetFromIcoMoon } from 'react-native-vector-icons'
import icoMoonConfig from '@/resources/fonts/selection.json'
import { scaleSizeW } from '@/utils/pixelRatio'
import { type ComponentProps } from 'react'
import { useTheme } from '@/store/theme/hook'
import { memo, type ComponentProps } from 'react'
import { useTextShadow, useTheme } from '@/store/theme/hook'
import { StyleSheet, type StyleProp, type TextStyle } from 'react-native'
// import IconAntDesign from 'react-native-vector-icons/AntDesign'
// import IconEntypo from 'react-native-vector-icons/Entypo'
@ -27,11 +28,31 @@ const IcoMoon = createIconSetFromIcoMoon(icoMoonConfig)
type IconType = ReturnType<typeof createIconSetFromIcoMoon>
export const Icon = ({ size = 15, rawSize, color, ...props }: ComponentProps<IconType> & { rawSize?: number }) => {
const theme = useTheme()
return <IcoMoon size={rawSize ?? scaleSizeW(size)} color={color ?? theme['c-font']} {...props} />
interface IconProps extends Omit<ComponentProps<IconType>, 'style'> {
style?: StyleProp<TextStyle>
rawSize?: number
}
export const Icon = memo(({ size = 15, rawSize, color, style, ...props }: IconProps) => {
const theme = useTheme()
const textShadow = useTextShadow()
const newStyle = textShadow ? StyleSheet.compose({
textShadowColor: theme['c-primary-alpha-700'],
textShadowOffset: { width: 0, height: 0.2 },
textShadowRadius: 2,
}, style) : style
return (
<IcoMoon
size={rawSize ?? scaleSizeW(size)}
color={color ?? theme['c-font']}
// @ts-expect-error
style={newStyle}
{...props}
/>
)
})
export {
// IconAntDesign,
// IconEntypo,

View File

@ -1,6 +1,6 @@
import { type ComponentProps } from 'react'
import { Text, type TextProps as _TextProps, StyleSheet, Animated, type ColorValue, type TextStyle } from 'react-native'
import { useTheme } from '@/store/theme/hook'
import { useTextShadow, useTheme } from '@/store/theme/hook'
import { setSpText } from '@/utils/pixelRatio'
import { useAnimateColor } from '@/utils/hooks/useAnimateColor'
import { DEFAULT_DURATION, useAnimateNumber } from '@/utils/hooks/useAnimateNumber'
@ -31,10 +31,23 @@ export interface TextProps extends _TextProps {
export default ({ style, size = 15, color, children, ...props }: TextProps) => {
const theme = useTheme()
const textShadow = useTextShadow()
style = StyleSheet.compose(textShadow ? {
fontFamily: 'System',
textShadowColor: theme['c-primary-alpha-700'],
textShadowOffset: { width: 0, height: 0.2 },
textShadowRadius: 2,
fontSize: setSpText(size),
color: color ?? theme['c-font'],
} : {
fontFamily: 'System',
fontSize: setSpText(size),
color: color ?? theme['c-font'],
}, style)
return (
<Text
style={StyleSheet.compose({ fontFamily: 'System', fontSize: setSpText(size), color: color ?? theme['c-font'] }, style)}
style={style}
{...props}
>{children}</Text>
)
@ -52,13 +65,21 @@ export interface AnimatedTextProps extends _AnimatedTextProps {
}
export const AnimatedText = ({ style, size = 15, color, children, ...props }: AnimatedTextProps) => {
const theme = useTheme()
const textShadow = useTextShadow()
style = StyleSheet.compose(textShadow ? {
fontFamily: 'System',
textShadowColor: theme['c-primary-alpha-700'],
textShadowOffset: { width: 0, height: 0.2 },
textShadowRadius: 2,
fontSize: setSpText(size),
color: color ?? theme['c-font'],
} : {
fontFamily: 'System',
fontSize: setSpText(size),
color: color ?? theme['c-font'],
}, style as TextStyle)
return (
<Animated.Text
style={StyleSheet.compose({ fontFamily: 'System', fontSize: setSpText(size), color: color ?? theme['c-font'] }, style as TextStyle)}
{...props}
>{children}</Animated.Text>
)
return <Animated.Text style={style} {...props}>{children}</Animated.Text>
}
@ -79,14 +100,25 @@ export interface AnimatedColorTextProps extends _AnimatedTextProps {
}
export const AnimatedColorText = ({ style, size = 15, opacity: _opacity, color: _color, children, ...props }: AnimatedColorTextProps) => {
const theme = useTheme()
const textShadow = useTextShadow()
const [color] = useAnimateColor(_color ?? theme['c-font'])
const [opacity] = useAnimateNumber(_opacity ?? 1, DEFAULT_DURATION, false)
return (
<Animated.Text
style={StyleSheet.compose({ fontSize: setSpText(size), color: color as unknown as ColorValue, opacity }, style as TextStyle)}
{...props}
>{children}</Animated.Text>
)
style = StyleSheet.compose(textShadow ? {
fontFamily: 'System',
textShadowColor: theme['c-primary-alpha-700'],
textShadowOffset: { width: 0, height: 0.2 },
textShadowRadius: 2,
fontSize: setSpText(size),
color: color as unknown as ColorValue,
opacity,
} : {
fontFamily: 'System',
fontSize: setSpText(size),
color: color as unknown as ColorValue,
opacity,
}, style as TextStyle)
return <Animated.Text style={style} {...props}>{children}</Animated.Text>
}

View File

@ -30,7 +30,7 @@ export enum COMPONENT_IDS {
export enum NAV_SHEAR_NATIVE_IDS {
playDetail_pic = 'playDetail_pic',
playDetail_header = 'playDetail_header',
playDetail_pageIndicator = 'playDetail_pageIndicator',
// playDetail_pageIndicator = 'playDetail_pageIndicator',
playDetail_player = 'playDetail_player',
songlistDetail_pic = 'songlistDetail_pic',
songlistDetail_title = 'songlistDetail_title',

View File

@ -30,9 +30,9 @@ const defaultSetting: LX.AppSetting = {
// 'playDetail.isZoomActiveLrc': false,
// 'playDetail.isShowLyricProgressSetting': false,
'playDetail.style.align': 'center',
'playDetail.vertical.style.lrcFontSize': 176,
'playDetail.horizontal.style.lrcFontSize': 180,
'playDetail.style.align': 'left',
'playDetail.vertical.style.lrcFontSize': 210,
'playDetail.horizontal.style.lrcFontSize': 220,
'playDetail.isShowLyricProgressSetting': false,
'desktopLyric.enable': false,
@ -71,6 +71,7 @@ const defaultSetting: LX.AppSetting = {
'theme.darkId': 'black',
'theme.hideBgDark': false,
'theme.dynamicBg': false,
'theme.fontShadow': true,
}

View File

@ -264,6 +264,7 @@
"setting_basic_theme": "Theme",
"setting_basic_theme_auto_theme": "Follow the system light and dark mode to switch themes",
"setting_basic_theme_dynamic_bg": "Use dynamic backgrounds",
"setting_basic_theme_font_shadow": "Enable font shadow",
"setting_basic_theme_hide_bg_dark": "Hide black theme",
"setting_basic_theme_more_btn_show": "Expand themes",
"setting_dislike_list_input_tip": "song name@artist name\nSong name\n@ singer name",

View File

@ -264,6 +264,7 @@
"setting_basic_theme": "主题颜色",
"setting_basic_theme_auto_theme": "跟随系统亮、暗模式切换主题",
"setting_basic_theme_dynamic_bg": "使用动态背景",
"setting_basic_theme_font_shadow": "启用字体阴影",
"setting_basic_theme_hide_bg_dark": "隐藏黑色主题背景",
"setting_basic_theme_more_btn_show": "更多主题",
"setting_dislike_list_input_tip": "歌曲名@歌手名\n歌曲名\n@歌手名",

View File

@ -165,17 +165,6 @@ export function pushPlayDetailScreen(componentId: string) {
duration: 300,
},
},
{
id: NAV_SHEAR_NATIVE_IDS.playDetail_pageIndicator,
alpha: {
from: 0, // We don't declare 'to' value as that is the element's current alpha value, here we're essentially animating from 0 to 1
duration: 300,
},
translationX: {
from: -32, // Animate translationY from 16dp to 0dp
duration: 300,
},
},
{
id: NAV_SHEAR_NATIVE_IDS.playDetail_player,
alpha: {

View File

@ -13,6 +13,7 @@ import { setNavActiveId } from '@/core/common'
const hideKeys = [
'list.isShowAlbumName',
'list.isShowInterval',
'theme.fontShadow',
] as Readonly<Array<keyof LX.AppSetting>>
const SearchPage = () => {
@ -71,14 +72,19 @@ const SongListPage = () => {
if (currentId != 'nav_setting') return
setVisible(false)
}
const handleConfigUpdated = (keys: Array<keyof LX.AppSetting>) => {
if (keys.some(k => hideKeys.includes(k))) handleHide()
}
global.state_event.on('navActiveIdUpdated', handleNavIdUpdate)
global.state_event.on('themeUpdated', handleHide)
global.state_event.on('languageChanged', handleHide)
global.state_event.on('configUpdated', handleConfigUpdated)
return () => {
global.state_event.off('navActiveIdUpdated', handleNavIdUpdate)
global.state_event.off('themeUpdated', handleHide)
global.state_event.off('languageChanged', handleHide)
global.state_event.on('configUpdated', handleConfigUpdated)
}
}, [])

View File

@ -73,7 +73,7 @@ export default forwardRef<ListMenuType, ListMenuProps>((props, ref) => {
if (musicInfo.source == 'local') menu.splice(4, 0, { action: 'editMetadata', disabled: !edit_metadata, label: t('edit_metadata') })
setMenus(menu)
void Promise.all([hasEditMetadata(musicInfo)]).then(([_edit_metadata]) => {
console.log(_edit_metadata)
// console.log(_edit_metadata)
let isUpdated = true
if (edit_metadata != _edit_metadata) {
edit_metadata = _edit_metadata

View File

@ -25,6 +25,6 @@ export default memo(() => {
const styles = createStyle({
content: {
marginTop: 5,
marginBottom: 15,
// marginBottom: 15,
},
})

View File

@ -0,0 +1,29 @@
import { memo } from 'react'
import { View } from 'react-native'
import CheckBoxItem from '../../components/CheckBoxItem'
import { createStyle } from '@/utils/tools'
import { useI18n } from '@/lang'
import { updateSetting } from '@/core/common'
import { useSettingValue } from '@/store/setting/hook'
export default memo(() => {
const t = useI18n()
const isFontShadow = useSettingValue('theme.fontShadow')
const setIsFontShadow = (isFontShadow: boolean) => {
updateSetting({ 'theme.fontShadow': isFontShadow })
}
return (
<View style={styles.content}>
<CheckBoxItem check={isFontShadow} label={t('setting_basic_theme_font_shadow')} onChange={setIsFontShadow} />
</View>
)
})
const styles = createStyle({
content: {
marginTop: 5,
marginBottom: 15,
},
})

View File

@ -5,6 +5,7 @@ import Theme from './Theme'
import IsAutoTheme from './IsAutoTheme'
import IsHideBgDark from './IsHideBgDark'
import IsDynamicBg from './IsDynamicBg'
import IsFontShadow from './IsFontShadow'
// import { useI18n } from '@/lang/i18n'
export default memo(() => {
@ -14,6 +15,7 @@ export default memo(() => {
<IsAutoTheme />
<IsHideBgDark />
<IsDynamicBg />
<IsFontShadow />
</>
)
})

View File

@ -28,7 +28,7 @@ const LrcLine = memo(({ line, lineNum, activeLine, onLayout }: LineProps) => {
const lrcFontSize = useSettingValue('playDetail.horizontal.style.lrcFontSize')
const textAlign = useSettingValue('playDetail.style.align')
const size = lrcFontSize / 10
const lineHeight = setSpText(size) * 1.25
const lineHeight = setSpText(size) * 1.3
const colors = useMemo(() => {
const active = activeLine == lineNum

View File

@ -67,7 +67,7 @@ const LrcLine = memo(({ line, lineNum, activeLine, onLayout }: LineProps) => {
const lrcFontSize = useSettingValue('playDetail.vertical.style.lrcFontSize')
const textAlign = useSettingValue('playDetail.style.align')
const size = lrcFontSize / 10
const lineHeight = setSpText(size) * 1.25
const lineHeight = setSpText(size) * 1.3
const colors = useMemo(() => {
const active = activeLine == lineNum

View File

@ -12,13 +12,9 @@ import { NAV_SHEAR_NATIVE_IDS } from '@/config/constant'
export default memo(() => {
return (
<View style={styles.container} nativeID={NAV_SHEAR_NATIVE_IDS.playDetail_player}>
<View style={styles.status}>
<PlayInfo />
</View>
<PlayInfo />
<ControlBtn />
<View style={{ ...styles.info }} >
<MoreBtn />
</View>
<MoreBtn />
</View>
)
})
@ -38,12 +34,6 @@ const styles = createStyle({
// backgroundColor: 'red',
flexDirection: 'column',
},
info: {
flex: 0,
flexDirection: 'row',
// paddingBottom: 5,
// justifyContent: 'flex-end',
},
status: {
marginTop: 10,
flexDirection: 'column',

View File

@ -1,5 +1,6 @@
import { useContext } from 'react'
import { useContext, useEffect, useState } from 'react'
import { ThemeContext } from './state'
import settingState from '@/store/setting/state'
// export const useSetting = () => {
// const [setting, updateSetting] = useState(state.setting)
@ -36,3 +37,21 @@ import { ThemeContext } from './state'
export const useTheme = () => useContext(ThemeContext)
export const useTextShadow = () => {
const [value, update] = useState(settingState.setting['theme.fontShadow'])
useEffect(() => {
const handleUpdate = (keys: Array<keyof LX.AppSetting>, setting: Partial<LX.AppSetting>) => {
if (!keys.includes('theme.fontShadow')) return
requestAnimationFrame(() => {
update(setting['theme.fontShadow']!)
})
}
global.state_event.on('configUpdated', handleUpdate)
return () => {
global.state_event.off('configUpdated', handleUpdate)
}
}, [])
return value
}

View File

@ -81,6 +81,11 @@ declare global {
*/
'theme.dynamicBg': boolean
/**
*
*/
'theme.fontShadow': boolean
/**
*
*/