diff --git a/packages/mobile/src/components/fields/PickArtworkField.tsx b/packages/mobile/src/components/fields/PickArtworkField.tsx index 402d5b0bc4..df0c9551c0 100644 --- a/packages/mobile/src/components/fields/PickArtworkField.tsx +++ b/packages/mobile/src/components/fields/PickArtworkField.tsx @@ -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' @@ -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({ @@ -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 ( - setStatus({ imageLoading: false, imageGenerating: false }) - } + onLoad={handleImageLoad} style={styles.image} noSkeleton > - {status.imageLoading || status.imageGenerating ? ( + {isLoading || isImageLoading ? ( ) : trackArtworkUrl ? null : ( @@ -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} /> diff --git a/packages/mobile/src/screens/edit-playlist-screen/PlaylistArtworkField.tsx b/packages/mobile/src/screens/edit-playlist-screen/PlaylistArtworkField.tsx new file mode 100644 index 0000000000..4027da1df6 --- /dev/null +++ b/packages/mobile/src/screens/edit-playlist-screen/PlaylistArtworkField.tsx @@ -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 ( + + ) +} diff --git a/packages/mobile/src/screens/edit-playlist-screen/PlaylistImageInput.tsx b/packages/mobile/src/screens/edit-playlist-screen/PlaylistImageInput.tsx index 079495949f..212a580e65 100644 --- a/packages/mobile/src/screens/edit-playlist-screen/PlaylistImageInput.tsx +++ b/packages/mobile/src/screens/edit-playlist-screen/PlaylistImageInput.tsx @@ -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' @@ -18,7 +18,7 @@ export const PlaylistImageInput = () => { return ( - + ) diff --git a/packages/web/src/common/store/cache/tracks/sagas.js b/packages/web/src/common/store/cache/tracks/sagas.js index dda87f6856..ec58eb6236 100644 --- a/packages/web/src/common/store/cache/tracks/sagas.js +++ b/packages/web/src/common/store/cache/tracks/sagas.js @@ -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 } }