Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
[C-2856] Fix track/collection artwork field (#3760)
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanjeffers authored Jul 18, 2023
1 parent 366e4df commit 40ea57e
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 47 deletions.
66 changes: 23 additions & 43 deletions packages/mobile/src/components/fields/PickArtworkField.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useCallback, useMemo } from 'react'
import { useCallback, useMemo, useState } from 'react'

import { useGeneratePlaylistArtwork } from '@audius/common'
import { useField, useFormikContext } from 'formik'
import { useField } from 'formik'
import { capitalize } from 'lodash'
import { View } from 'react-native'
import type { Asset } from 'react-native-image-picker'
Expand Down Expand Up @@ -57,32 +56,30 @@ const useStyles = makeStyles(({ palette, spacing }) => ({

const messages = {
addArtwork: 'Add Artwork',
changeArtwork: 'Change Artwork',
removeArtwork: 'Remove Artwork',
removingArtwork: 'Removing Artwork',
updatingArtwork: 'Updating Artwork'
changeArtwork: 'Change Artwork'
}

type PickArtworkFieldProps = {
name: string
onChange?: (image: Asset) => void
buttonTitle?: string
onPress?: () => void
onImageLoad?: () => void
isLoading?: boolean
}

export const PickArtworkField = (props: PickArtworkFieldProps) => {
const { name } = props
const { name, onChange, buttonTitle, onPress, onImageLoad, isLoading } = props
const styles = useStyles()
const { neutralLight8 } = useThemeColors()
const [{ value }, { error, touched }, { setValue: setArtwork }] =
useField(name)
const [{ value: existingTrackArtwork }] = useField('trackArtwork')
const trackArtworkUrl = value?.url ?? existingTrackArtwork
const [{ value: collectionId }] = useField('playlist_id')
const [{ value: isImageAutogenerated }, , { setValue: setIsAutogenerated }] =
useField('is_image_autogenerated')
const [isImageLoading, setIsImageLoading] = useState(false)

const { secondary } = useThemeColors()

const { status, setStatus } = useFormikContext()

const handleChangeArtwork = useCallback(() => {
const handleImageSelected = (_image: Image, rawResponse: Asset) => {
setArtwork({
Expand All @@ -94,35 +91,29 @@ export const PickArtworkField = (props: PickArtworkFieldProps) => {
},
source: 'original'
})
setIsAutogenerated(false)
setStatus({ imageLoading: true })
onChange?.(rawResponse)
setIsImageLoading(true)
}
launchSelectImageActionSheet(handleImageSelected, secondary)
}, [secondary, setArtwork, setIsAutogenerated, setStatus])

const source = useMemo(() => ({ uri: trackArtworkUrl }), [trackArtworkUrl])
}, [secondary, setArtwork, onChange])

const generatePlaylistArtwork = useGeneratePlaylistArtwork(collectionId)
const handleImageLoad = useCallback(() => {
onImageLoad?.()
setIsImageLoading(false)
}, [onImageLoad])

const handleRemoveArtwork = useCallback(async () => {
setStatus({ imageLoading: true, imageGenerating: true })
const { file, url } = await generatePlaylistArtwork()
setArtwork({ url, file })
setIsAutogenerated(true)
}, [setStatus, generatePlaylistArtwork, setArtwork, setIsAutogenerated])
const source = useMemo(() => ({ uri: trackArtworkUrl }), [trackArtworkUrl])

return (
<View style={styles.root}>
<DynamicImage
source={source}
onLoad={() =>
setStatus({ imageLoading: false, imageGenerating: false })
}
onLoad={handleImageLoad}
style={styles.image}
noSkeleton
>
<View style={styles.iconPicture}>
{status.imageLoading || status.imageGenerating ? (
{isLoading || isImageLoading ? (
<LoadingSpinner style={styles.loading} />
) : trackArtworkUrl ? null : (
<IconImage height={128} width={128} fill={neutralLight8} />
Expand All @@ -133,23 +124,12 @@ export const PickArtworkField = (props: PickArtworkFieldProps) => {
variant='secondaryAlt'
size='large'
title={
status.imageGenerating && isImageAutogenerated
? messages.updatingArtwork
: trackArtworkUrl && status.imageGenerating
? messages.removingArtwork
: trackArtworkUrl && !isImageAutogenerated
? messages.removeArtwork
: trackArtworkUrl
? messages.changeArtwork
: messages.addArtwork
buttonTitle ||
(trackArtworkUrl ? messages.changeArtwork : messages.addArtwork)
}
icon={IconPencil}
iconPosition='left'
onPress={
trackArtworkUrl && !isImageAutogenerated
? handleRemoveArtwork
: handleChangeArtwork
}
onPress={onPress ?? handleChangeArtwork}
/>
</View>
</DynamicImage>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useCallback } from 'react'

import { useGeneratePlaylistArtwork } from '@audius/common'
import { useField, useFormikContext } from 'formik'

import { PickArtworkField } from 'app/components/fields'

const messages = {
removeArtwork: 'Remove Artwork',
removingArtwork: 'Removing Artwork',
updatingArtwork: 'Updating Artwork'
}

type PickArtworkFieldProps = {
name: string
}

export const PlaylistArtworkField = (props: PickArtworkFieldProps) => {
const { name } = props
const [{ value: artworkUrl }, , { setValue: setArtwork }] = useField(name)
const [{ value: collectionId }] = useField('playlist_id')
const [{ value: isImageAutogenerated }, , { setValue: setIsAutogenerated }] =
useField('is_image_autogenerated')
const generatePlaylistArtwork = useGeneratePlaylistArtwork(collectionId)
const { status, setStatus } = useFormikContext()

const handleChange = useCallback(() => {
setIsAutogenerated(false)
}, [setIsAutogenerated])

const handleRemove = useCallback(async () => {
setStatus({ imageGenerating: true })
const { file, url } = await generatePlaylistArtwork()
setArtwork({ url, file })
setIsAutogenerated(true)
}, [setStatus, generatePlaylistArtwork, setArtwork, setIsAutogenerated])

const handleImageLoad = useCallback(() => {
setStatus({ imageGenerating: false })
}, [setStatus])

return (
<PickArtworkField
{...props}
onPress={artworkUrl && !isImageAutogenerated ? handleRemove : undefined}
onChange={handleChange}
buttonTitle={
status.imageGenerating && isImageAutogenerated
? messages.updatingArtwork
: artworkUrl && status.imageGenerating
? messages.removingArtwork
: artworkUrl && !isImageAutogenerated
? messages.removeArtwork
: undefined
}
onImageLoad={handleImageLoad}
isLoading={status.imageGenerating}
/>
)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { View } from 'react-native'

import { PickArtworkField } from 'app/components/fields'
import { makeStyles } from 'app/styles'

import { PlaylistArtworkField } from './PlaylistArtworkField'
import { RandomImageInput } from './RandomImageButton'

const name = 'artwork'
Expand All @@ -18,7 +18,7 @@ export const PlaylistImageInput = () => {

return (
<View style={styles.root}>
<PickArtworkField name={name} />
<PlaylistArtworkField name={name} />
<RandomImageInput name={name} />
</View>
)
Expand Down
4 changes: 2 additions & 2 deletions packages/web/src/common/store/cache/tracks/sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ function* editTrackAsync(action) {

const track = { ...action.formFields }
track.track_id = action.trackId
if (track.artwork) {
if (track.artwork?.file) {
track.cover_art_sizes = track.artwork.url
track._cover_art_sizes = {
...track._cover_art_sizes,
[DefaultSizes.OVERRIDE]: track.artwork.url
}
}
Expand Down

0 comments on commit 40ea57e

Please sign in to comment.