mirror of
https://github.com/austinried/subtracks.git
synced 2026-02-10 06:52:43 +01:00
fix view artist from context menu add loading indicators to song list and artist views (show info we have right away)
111 lines
2.6 KiB
TypeScript
111 lines
2.6 KiB
TypeScript
import { useArtistArtFile, useCoverArtFile } from '@app/hooks/cache'
|
|
import { CacheFile, CacheRequest } from '@app/models/cache'
|
|
import colors from '@app/styles/colors'
|
|
import React, { useState } from 'react'
|
|
import {
|
|
ActivityIndicator,
|
|
Image,
|
|
ImageResizeMode,
|
|
ImageSourcePropType,
|
|
ImageStyle,
|
|
StyleSheet,
|
|
View,
|
|
ViewStyle,
|
|
} from 'react-native'
|
|
|
|
type BaseProps = {
|
|
style?: ViewStyle
|
|
imageStyle?: ImageStyle
|
|
resizeMode?: ImageResizeMode
|
|
round?: boolean
|
|
}
|
|
|
|
type ArtistCoverArtProps = BaseProps & {
|
|
type: 'artist'
|
|
artistId: string
|
|
}
|
|
|
|
type CoverArtProps = BaseProps & {
|
|
type: 'cover'
|
|
coverArt?: string
|
|
}
|
|
|
|
const ImageSource = React.memo<{ cache?: { file?: CacheFile; request?: CacheRequest } } & BaseProps>(
|
|
({ cache, style, imageStyle, resizeMode }) => {
|
|
const [error, setError] = useState(false)
|
|
|
|
let source: ImageSourcePropType
|
|
if (!error && cache?.file && !cache?.request?.promise) {
|
|
source = { uri: `file://${cache.file.path}`, cache: 'reload' }
|
|
} else {
|
|
source = require('@res/fallback.png')
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Image
|
|
source={source}
|
|
fadeDuration={150}
|
|
resizeMode={resizeMode || 'contain'}
|
|
style={[{ height: style?.height, width: style?.width }, imageStyle]}
|
|
onError={() => setError(true)}
|
|
/>
|
|
<ActivityIndicator
|
|
animating={!!cache?.request?.promise}
|
|
size="large"
|
|
color={colors.accent}
|
|
style={styles.indicator}
|
|
/>
|
|
</>
|
|
)
|
|
},
|
|
)
|
|
|
|
const ArtistImage = React.memo<ArtistCoverArtProps>(props => {
|
|
const cache = useArtistArtFile(props.artistId)
|
|
|
|
return <ImageSource cache={cache} {...props} imageStyle={{ ...styles.artistImage, ...props.imageStyle }} />
|
|
})
|
|
|
|
const CoverArtImage = React.memo<CoverArtProps>(props => {
|
|
const cache = useCoverArtFile(props.coverArt)
|
|
|
|
return <ImageSource cache={cache} {...props} />
|
|
})
|
|
|
|
const CoverArt = React.memo<CoverArtProps | ArtistCoverArtProps>(props => {
|
|
const viewStyles = [props.style]
|
|
if (props.round) {
|
|
viewStyles.push(styles.round)
|
|
}
|
|
|
|
let imageComponent
|
|
switch (props.type) {
|
|
case 'artist':
|
|
imageComponent = <ArtistImage {...(props as ArtistCoverArtProps)} />
|
|
break
|
|
default:
|
|
imageComponent = <CoverArtImage {...(props as CoverArtProps)} />
|
|
break
|
|
}
|
|
|
|
return <View style={viewStyles}>{imageComponent}</View>
|
|
})
|
|
|
|
const styles = StyleSheet.create({
|
|
round: {
|
|
overflow: 'hidden',
|
|
borderRadius: 1000,
|
|
},
|
|
indicator: {
|
|
height: '100%',
|
|
width: '100%',
|
|
position: 'absolute',
|
|
},
|
|
artistImage: {
|
|
backgroundColor: 'rgba(81, 28, 99, 0.4)',
|
|
},
|
|
})
|
|
|
|
export default CoverArt
|