优化背景切换逻辑

This commit is contained in:
lyswhut 2023-12-23 13:13:33 +08:00
parent 8367758113
commit 634ebe71e9
15 changed files with 124 additions and 94 deletions

12
package-lock.json generated
View File

@ -25,7 +25,7 @@
"react-native-fast-image": "^8.6.3",
"react-native-file-system": "github:lyswhut/react-native-file-system#291582cd202053246458bf9376efe27fbb75afb6",
"react-native-fs": "^2.20.0",
"react-native-local-media-metadata": "github:lyswhut/react-native-local-media-metadata#35d7df1f68f19492749a9ea0541f02be77c0a675",
"react-native-local-media-metadata": "github:lyswhut/react-native-local-media-metadata#fbf7c7d07475c6adb398b05653fa3cadc722d4ea",
"react-native-navigation": "^7.37.2",
"react-native-pager-view": "^6.2.3",
"react-native-quick-base64": "^2.0.8",
@ -9014,8 +9014,8 @@
},
"node_modules/react-native-local-media-metadata": {
"version": "0.1.0",
"resolved": "git+ssh://git@github.com/lyswhut/react-native-local-media-metadata.git#35d7df1f68f19492749a9ea0541f02be77c0a675",
"integrity": "sha512-Gbf8yuVQIWOAuJ4JQ5cRL9QNMePqsiPiSVw+e11ZfwKnZtpCtiwbgTixCjWpIcIyRsURNBz+3UJwQl2fPx6FWQ==",
"resolved": "git+ssh://git@github.com/lyswhut/react-native-local-media-metadata.git#fbf7c7d07475c6adb398b05653fa3cadc722d4ea",
"integrity": "sha512-HIjzXi0t/70NoDn91wS/A0SiusPpKF1aJPXXZ1e8BMf5TyepOwzRWDezvz8tvymsb52caY7DesgUWS1Tv2m29A==",
"license": "MIT",
"workspaces": [
"example"
@ -17217,9 +17217,9 @@
}
},
"react-native-local-media-metadata": {
"version": "git+ssh://git@github.com/lyswhut/react-native-local-media-metadata.git#35d7df1f68f19492749a9ea0541f02be77c0a675",
"integrity": "sha512-Gbf8yuVQIWOAuJ4JQ5cRL9QNMePqsiPiSVw+e11ZfwKnZtpCtiwbgTixCjWpIcIyRsURNBz+3UJwQl2fPx6FWQ==",
"from": "react-native-local-media-metadata@github:lyswhut/react-native-local-media-metadata#35d7df1f68f19492749a9ea0541f02be77c0a675",
"version": "git+ssh://git@github.com/lyswhut/react-native-local-media-metadata.git#fbf7c7d07475c6adb398b05653fa3cadc722d4ea",
"integrity": "sha512-HIjzXi0t/70NoDn91wS/A0SiusPpKF1aJPXXZ1e8BMf5TyepOwzRWDezvz8tvymsb52caY7DesgUWS1Tv2m29A==",
"from": "react-native-local-media-metadata@github:lyswhut/react-native-local-media-metadata#fbf7c7d07475c6adb398b05653fa3cadc722d4ea",
"requires": {}
},
"react-native-navigation": {

View File

@ -59,7 +59,7 @@
"react-native-fast-image": "^8.6.3",
"react-native-file-system": "github:lyswhut/react-native-file-system#291582cd202053246458bf9376efe27fbb75afb6",
"react-native-fs": "^2.20.0",
"react-native-local-media-metadata": "github:lyswhut/react-native-local-media-metadata#35d7df1f68f19492749a9ea0541f02be77c0a675",
"react-native-local-media-metadata": "github:lyswhut/react-native-local-media-metadata#fbf7c7d07475c6adb398b05653fa3cadc722d4ea",
"react-native-navigation": "^7.37.2",
"react-native-pager-view": "^6.2.3",
"react-native-quick-base64": "^2.0.8",

View File

@ -1,29 +1,24 @@
// import { useEffect, useState } from 'react'
import { Image, View } from 'react-native'
import { View } from 'react-native'
import { useTheme } from '@/store/theme/hook'
import ImageBackground from '@/components/common/ImageBackground'
import { useWindowSize } from '@/utils/hooks'
import { useEffect, useMemo, useState } from 'react'
import playerState from '@/store/player/state'
import settingState from '@/store/setting/state'
import { useMemo } from 'react'
import { scaleSizeAbsHR } from '@/utils/pixelRatio'
import { defaultHeaders } from './common/Image'
import SizeView from './SizeView'
import { useBgPic } from '@/store/common/hook'
interface Props {
children: React.ReactNode
}
const formatUri = <T extends string | null>(url: T) => {
return (typeof url == 'string' && url.startsWith('/')) ? `file://${url}` : url
}
const BLUR_RADIUS = Math.max(scaleSizeAbsHR(24), 10)
const BLUR_RADIUS = Math.max(scaleSizeAbsHR(18), 10)
export default ({ children }: Props) => {
const theme = useTheme()
const windowSize = useWindowSize()
const [pic, setPic] = useState<string | null | undefined>(settingState.setting['theme.dynamicBg'] ? playerState.musicInfo.pic : null)
const pic = useBgPic()
// const [wh, setWH] = useState<{ width: number | string, height: number | string }>({ width: '100%', height: Dimensions.get('screen').height })
// 固定宽高度 防止弹窗键盘时大小改变导致背景被缩放
@ -44,49 +39,6 @@ export default ({ children }: Props) => {
// }
// console.log('render page content')
useEffect(() => {
let pic = playerState.musicInfo.pic
let isUnmounted = false
let isDynamicBg = settingState.setting['theme.dynamicBg']
const handlePicUpdate = () => {
if (playerState.musicInfo.pic && playerState.musicInfo.pic != playerState.loadErrorPicUrl) {
// if (playerState.musicInfo.pic != playerState.loadErrorPicUrl) {
// console.log('picUpdated', playerState.musicInfo.pic)
pic = playerState.musicInfo.pic
if (!isDynamicBg) return
void Image.prefetch(formatUri(playerState.musicInfo.pic)).then(() => {
if (pic != playerState.musicInfo.pic || isUnmounted) return
setPic(playerState.musicInfo.pic)
}).catch(() => {
if (isUnmounted) return
setPic(null)
})
}
// } else {
// if (!isDynamicBg) return
// setPic(null)
// }
}
const handleConfigUpdate = (keys: Array<keyof LX.AppSetting>, setting: Partial<LX.AppSetting>) => {
if (!keys.includes('theme.dynamicBg')) return
isDynamicBg = setting['theme.dynamicBg']!
if (isDynamicBg) {
if (playerState.musicInfo.pic) {
pic = playerState.musicInfo.pic
// console.log(pic)
setPic(pic)
}
} else setPic(null)
}
global.state_event.on('playerMusicInfoChanged', handlePicUpdate)
global.state_event.on('configUpdated', handleConfigUpdate)
return () => {
isUnmounted = true
global.state_event.off('playerMusicInfoChanged', handlePicUpdate)
global.state_event.off('configUpdated', handleConfigUpdate)
}
}, [])
const themeComponent = useMemo(() => (
<View style={{ flex: 1, overflow: 'hidden' }}>
<ImageBackground
@ -105,11 +57,11 @@ export default ({ children }: Props) => {
<View style={{ flex: 1, overflow: 'hidden' }}>
<ImageBackground
style={{ position: 'absolute', left: 0, top: 0, height: windowSize.height, width: windowSize.width, backgroundColor: theme['c-content-background'] }}
source={{ uri: formatUri(pic!), headers: defaultHeaders }}
source={{ uri: pic!, headers: defaultHeaders }}
resizeMode="cover"
blurRadius={BLUR_RADIUS}
>
<View style={{ flex: 1, flexDirection: 'column', backgroundColor: theme['c-content-background'], opacity: 0.8 }}></View>
<View style={{ flex: 1, flexDirection: 'column', backgroundColor: theme['c-content-background'], opacity: 0.76 }}></View>
</ImageBackground>
<View style={{ flex: 1, flexDirection: 'column' }}>
{children}

View File

@ -94,3 +94,7 @@ export default forwardRef<View, ImageBackgroundProps>(({
</View>
)
})
export const prefetch = async(url: string) => {
return Image.prefetch(url)
}

View File

@ -46,7 +46,7 @@ export default ({ isHome }: { isHome: boolean }) => {
return (
<TouchableOpacity onLongPress={handleLongPress} onPress={handlePress} activeOpacity={0.7} >
<Image url={musicInfo.pic} cache={false} nativeID={NAV_SHEAR_NATIVE_IDS.playDetail_pic} style={styles.image} onError={handleError} />
<Image url={musicInfo.pic} nativeID={NAV_SHEAR_NATIVE_IDS.playDetail_pic} style={styles.image} onError={handleError} />
</TouchableOpacity>
)
}

View File

@ -108,3 +108,7 @@ export const requestStoragePermission = async() => {
await setSelectedManagedFolder(uri.path)
return true
}
export const setBgPic = (pic: string | null) => {
commonActions.setBgPic(pic)
}

71
src/core/init/common.ts Normal file
View File

@ -0,0 +1,71 @@
// import musicSdk from '@/utils/musicSdk'
// import commonActions from '@/store/common/action'
import playerState from '@/store/player/state'
import { prefetch } from '@/components/common/ImageBackground'
import { setBgPic } from '@/core/common'
// const handleUpdateSourceNmaes = () => {
// const prefix = settingState.setting['common.sourceNameType'] == 'real' ? 'source_' : 'source_alias_'
// const sourceNames: Record<LX.OnlineSource | 'all', string> = {
// kw: 'kw',
// tx: 'tx',
// kg: 'kg',
// mg: 'mg',
// wy: 'wy',
// // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
// all: global.i18n.t(prefix + 'all' as any),
// }
// for (const { id } of musicSdk.sources) {
// // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
// sourceNames[id as LX.OnlineSource] = global.i18n.t(prefix + id as any)
// }
// commonActions.setSourceNames(sourceNames)
// }
const formatUri = <T extends string | null>(url: T) => {
return (typeof url == 'string' && url.startsWith('/')) ? `file://${url}` : url
}
export default async(setting: LX.AppSetting) => {
// const handleConfigUpdated = (keys: Array<keyof LX.AppSetting>, setting: Partial<LX.AppSetting>) => {
// // if (keys.includes('common.sourceNameType')) handleUpdateSourceNmaes()
// handleConfigUpdate(keys, setting)
// }
let pic = playerState.musicInfo.pic
let isDynamicBg = setting['theme.dynamicBg']
const handleUpdatePic = (pic: string) => {
if (!pic) return
const picUrl = formatUri(pic)
void prefetch(picUrl).then(() => {
if (pic != playerState.musicInfo.pic) return
setBgPic(picUrl)
})
}
const handlePicUpdate = () => {
if (playerState.musicInfo.pic && playerState.musicInfo.pic != playerState.loadErrorPicUrl) {
// if (playerState.musicInfo.pic != playerState.loadErrorPicUrl) {
console.log('picUpdated', playerState.musicInfo.pic)
pic = playerState.musicInfo.pic
if (!isDynamicBg) return
handleUpdatePic(pic)
// .catch(() => {
// if (pic != playerState.musicInfo.pic) return
// setBgPic(null)
// })
}
// } else {
// if (!isDynamicBg) return
// setPic(null)
// }
}
const handleConfigUpdate = (keys: Array<keyof LX.AppSetting>, setting: Partial<LX.AppSetting>) => {
if (!keys.includes('theme.dynamicBg')) return
isDynamicBg = setting['theme.dynamicBg']!
if (isDynamicBg) {
if (pic) handleUpdatePic(pic)
} else setBgPic(null)
}
handlePicUpdate()
global.state_event.on('playerMusicInfoChanged', handlePicUpdate)
global.state_event.on('configUpdated', handleConfigUpdate)
}

View File

@ -6,7 +6,7 @@ import initUserApi from './userApi'
import initPlayer from './player'
import dataInit from './dataInit'
import initSync from './sync'
// import syncSetting from './syncSetting'
import initCommonState from './common'
import { setApiSource } from '@/core/apiSource'
import commonActions from '@/store/common/action'
import settingState from '@/store/setting/state'
@ -55,6 +55,10 @@ export default async() => {
bootLog('Player inited.')
await dataInit(setting)
bootLog('Data inited.')
await dataInit(setting)
bootLog('Data inited.')
await initCommonState(setting)
bootLog('Common State inited.')
void initSync(setting)
bootLog('Sync inited.')

View File

@ -1,28 +0,0 @@
import musicSdk from '@/utils/musicSdk'
import commonActions from '@/store/common/action'
import settingState from '@/store/setting/state'
const handleUpdateSourceNmaes = () => {
const prefix = settingState.setting['common.sourceNameType'] == 'real' ? 'source_' : 'source_alias_'
const sourceNames: Record<LX.OnlineSource | 'all', string> = {
kw: 'kw',
tx: 'tx',
kg: 'kg',
mg: 'mg',
wy: 'wy',
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
all: global.i18n.t(prefix + 'all' as any),
}
for (const { id } of musicSdk.sources) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
sourceNames[id as LX.OnlineSource] = global.i18n.t(prefix + id as any)
}
commonActions.setSourceNames(sourceNames)
}
export default () => {
const handleConfigUpdated = (keys: Array<keyof LX.AppSetting>) => {
if (keys.includes('common.sourceNameType')) handleUpdateSourceNmaes()
}
global.state_event.on('configUpdated', handleConfigUpdated)
}

View File

@ -40,6 +40,10 @@ export class StateEvent extends Event {
this.emit('themeUpdated', theme)
}
bgPicUpdated(bgPic: string | null) {
this.emit('bgPicUpdated', bgPic)
}
playerMusicInfoChanged(musicInfo: PlayerState['musicInfo']) {
this.emit('playerMusicInfoChanged', musicInfo)
}

View File

@ -32,7 +32,7 @@ export default memo(({ componentId }: { componentId: string }) => {
return (
<View style={{ ...styles.container, height: contentHeight }}>
<View style={{ ...styles.content, elevation: animated ? 3 : 0 }}>
<Image url={musicInfo.pic} cache={false} nativeID={NAV_SHEAR_NATIVE_IDS.playDetail_pic} style={{
<Image url={musicInfo.pic} nativeID={NAV_SHEAR_NATIVE_IDS.playDetail_pic} style={{
width: imgWidth,
height: imgWidth,
borderRadius: 2,

View File

@ -35,7 +35,7 @@ export default ({ componentId }: { componentId: string }) => {
return (
<View style={styles.container}>
<View style={{ ...styles.content, elevation: animated ? 3 : 0 }}>
<Image url={musicInfo.pic} cache={false} nativeID={NAV_SHEAR_NATIVE_IDS.playDetail_pic} style={style} />
<Image url={musicInfo.pic} nativeID={NAV_SHEAR_NATIVE_IDS.playDetail_pic} style={style} />
</View>
</View>
)

View File

@ -29,6 +29,10 @@ export default {
setLastNavActiveId(id: InitState['navActiveId']) {
state.lastNavActiveId = id
},
setBgPic(pic: string | null) {
state.bgPic = pic
global.state_event.bgPicUpdated(pic)
},
setSourceNames(names: InitState['sourceNames']) {
state.sourceNames = names
global.state_event.sourceNamesUpdated(names)

View File

@ -96,6 +96,19 @@ export const useNavActiveId = () => {
return value
}
export const useBgPic = () => {
const [value, update] = useState(state.bgPic)
useEffect(() => {
global.state_event.on('bgPicUpdated', update)
return () => {
global.state_event.off('bgPicUpdated', update)
}
}, [])
return value
}
export const useSourceNames = () => {
const [value, update] = useState(state.sourceNames)

View File

@ -8,6 +8,7 @@ export interface InitState {
navActiveId: NAV_ID_Type
lastNavActiveId: NAV_ID_Type
sourceNames: Record<LX.OnlineSource | 'all', string>
bgPic: string | null
}
const initData = {}
@ -19,6 +20,7 @@ const state: InitState = {
navActiveId: 'nav_search',
lastNavActiveId: 'nav_search',
sourceNames: initData as InitState['sourceNames'],
bgPic: null,
}