diff --git a/packages/common/src/api/suggestedTracks.ts b/packages/common/src/api/suggestedTracks.ts index 6d7beb09e7..36fc8690cb 100644 --- a/packages/common/src/api/suggestedTracks.ts +++ b/packages/common/src/api/suggestedTracks.ts @@ -7,12 +7,13 @@ import { usePaginatedQuery } from 'audius-query' import { ID } from 'models/Identifiers' import { Status } from 'models/Status' import { TimeRange } from 'models/TimeRange' -import { Track } from 'models/Track' +import { Track, UserTrackMetadata } from 'models/Track' import { getUserId } from 'store/account/selectors' import { addTrackToPlaylist } from 'store/cache/collections/actions' import { getCollection } from 'store/cache/collections/selectors' import { getTrack } from 'store/cache/tracks/selectors' import { CommonState } from 'store/index' +import { removeNullable } from 'utils/typeUtils' import { useGetFavoritedTrackList } from './favorites' import { useGetTracksByIds } from './track' @@ -20,6 +21,15 @@ import { useGetTrending } from './trending' const suggestedTrackCount = 5 +const isValidTrack = (track: Track | UserTrackMetadata) => { + return ( + !track.is_premium && + !track.is_delete && + !track.is_invalid && + !track.is_unlisted + ) +} + type SuggestedTrack = | { isLoading: true; key: ID } | { isLoading: true; id: ID; key: ID } @@ -34,11 +44,14 @@ const selectSuggestedTracks = ( state: CommonState, ids: ID[] ): SuggestedTrack[] => { - const suggestedTracks = ids.map((id) => { - const track = getTrack(state, { id }) - if (!track) return { id, isLoading: true as const, key: id } - return { id, track, isLoading: false as const, key: id } - }) + const suggestedTracks = ids + .map((id) => { + const track = getTrack(state, { id }) + if (!track) return { id, isLoading: true as const, key: id } + if (!isValidTrack) return null + return { id, track, isLoading: false as const, key: id } + }) + .filter(removeNullable) return [...suggestedTracks, ...skeletons].slice(0, 5) } @@ -93,9 +106,7 @@ export const useGetSuggestedTracks = (collectionId: ID) => { useEffect(() => { if (trendingStatus === Status.SUCCESS) { const trendingTrackIds = difference( - trendingTracks - .filter((track) => !track.is_premium) - .map((track) => track.track_id), + trendingTracks.filter(isValidTrack).map((track) => track.track_id), collectionTrackIds ) setSuggestedTrackIds([...suggestedTrackIds, ...trendingTrackIds]) diff --git a/packages/common/src/store/cache/reducer.ts b/packages/common/src/store/cache/reducer.ts index f6021ff257..09850e373f 100644 --- a/packages/common/src/store/cache/reducer.ts +++ b/packages/common/src/store/cache/reducer.ts @@ -95,6 +95,10 @@ export const mergeCustomizer = (objValue: any, srcValue: any, key: string) => { if (forceUpdateKeys.has(key)) { return srcValue } + + if (key === 'artwork') { + return null + } if (key === 'is_verified') { return srcValue || objValue } diff --git a/packages/common/src/utils/updatePlaylistArtwork.ts b/packages/common/src/utils/updatePlaylistArtwork.ts index 269edd54ce..0352677694 100644 --- a/packages/common/src/utils/updatePlaylistArtwork.ts +++ b/packages/common/src/utils/updatePlaylistArtwork.ts @@ -8,7 +8,7 @@ import { AudiusBackend } from 'services/audius-backend' import { Nullable } from './typeUtils' const filterTrack = (track1: Track) => (track2: Track) => - track1.track_id === track2.track_id + track1.track_id !== track2.track_id type ArtworkActions = { added?: Track @@ -29,8 +29,8 @@ export const updatePlaylistArtwork = async ( actions: ArtworkActions, context: Context ) => { - const { is_image_autogenerated } = collection - if (!is_image_autogenerated && !actions.regenerate) { + const { is_image_autogenerated, cover_art_sizes } = collection + if (!is_image_autogenerated && cover_art_sizes && !actions.regenerate) { return collection } @@ -49,12 +49,16 @@ export const updatePlaylistArtwork = async ( ) if (removedIndex === -1) { // continue - } else if (tracks.length >= 4 && removedIndex < 4) { + } else if (tracks.length > 4 && removedIndex < 4) { tracksForImage = tracks.filter(filterTrack(removed)).slice(0, 4) } else if (tracks.length === 4) { tracksForImage = tracks.filter(filterTrack(removed)).slice(0, 1) - } else if (tracks.length < 4 && removedIndex === 0) { - tracksForImage = tracks.slice(1, 2) + } else if (tracks.length < 4) { + if (tracks.length === 1) { + tracksForImage = [] + } else if (removedIndex === 0) { + tracksForImage = tracks.slice(1, 2) + } } } else if (actions.reordered) { if ( @@ -76,23 +80,34 @@ export const updatePlaylistArtwork = async ( tracksForImage = actions.updated.slice(0, 4) } } else if (actions.regenerate) { - tracksForImage = tracks.slice(0, 4) + if (tracks.length < 4) { + tracksForImage = tracks.slice(0, 1) + } else { + tracksForImage = tracks.slice(0, 4) + } } if (tracksForImage) { - const trackUrls = await Promise.all( - tracksForImage.map(async (track) => { - const { cover_art_sizes, cover_art } = track - return await context.audiusBackend.getImageUrl( - cover_art_sizes ?? cover_art, - SquareSizes.SIZE_1000_BY_1000 - ) - }) - ) + if (tracksForImage.length === 0) { + console.log('okay full removal!') + // @ts-expect-error + collection.cover_art_sizes = undefined + collection._cover_art_sizes = {} + } else { + const trackUrls = await Promise.all( + tracksForImage.map(async (track) => { + const { cover_art_sizes, cover_art } = track + return await context.audiusBackend.getImageUrl( + cover_art_sizes ?? cover_art, + SquareSizes.SIZE_1000_BY_1000 + ) + }) + ) - const artwork = await context.generateImage(trackUrls) - collection.artwork = artwork - collection.is_image_autogenerated = true + const artwork = await context.generateImage(trackUrls) + collection.artwork = artwork + collection.is_image_autogenerated = true + } } return collection diff --git a/packages/web/src/common/store/cache/collections/utils/optimisticUpdateCollection.ts b/packages/web/src/common/store/cache/collections/utils/optimisticUpdateCollection.ts index d2f79313a8..052ec64733 100644 --- a/packages/web/src/common/store/cache/collections/utils/optimisticUpdateCollection.ts +++ b/packages/web/src/common/store/cache/collections/utils/optimisticUpdateCollection.ts @@ -2,20 +2,20 @@ import { Collection, Kind, cacheActions } from '@audius/common' import { put } from 'typed-redux-saga' export function* optimisticUpdateCollection(collection: Collection) { - if (collection.artwork?.url) { - const { artwork } = collection + const optimisticCollection = { ...collection } + if (optimisticCollection.artwork?.url) { + const { artwork } = optimisticCollection const { url } = artwork - collection.artwork = artwork - collection.cover_art_sizes = url! - const coverArtSizes = collection._cover_art_sizes ?? {} + optimisticCollection.artwork = artwork + optimisticCollection.cover_art_sizes = url! + const coverArtSizes = optimisticCollection._cover_art_sizes ?? {} coverArtSizes.OVERRIDE = url - collection._cover_art_sizes = coverArtSizes - collection.is_image_autogenerated = true + optimisticCollection._cover_art_sizes = coverArtSizes } yield* put( cacheActions.update(Kind.COLLECTIONS, [ - { id: collection.playlist_id, metadata: collection } + { id: optimisticCollection.playlist_id, metadata: optimisticCollection } ]) ) } diff --git a/packages/web/src/components/collection/desktop/Artwork.tsx b/packages/web/src/components/collection/desktop/Artwork.tsx index f94c82e240..38a3f85138 100644 --- a/packages/web/src/components/collection/desktop/Artwork.tsx +++ b/packages/web/src/components/collection/desktop/Artwork.tsx @@ -62,7 +62,7 @@ export const Artwork = (props: ArtworkProps) => { useEffect(() => { // If there's a gradient, this is a smart collection. Just immediately call back - if (image || gradient || imageOverride) callback() + if (image || gradient || imageOverride || imageBlank) callback() }, [image, callback, gradient, imageOverride]) const handleEditArtwork = useCallback(() => { @@ -79,7 +79,7 @@ export const Artwork = (props: ArtworkProps) => { {Icon ? ( diff --git a/packages/web/src/components/create-playlist/PlaylistForm.tsx b/packages/web/src/components/create-playlist/PlaylistForm.tsx index 1abb042e22..a39dfc9319 100644 --- a/packages/web/src/components/create-playlist/PlaylistForm.tsx +++ b/packages/web/src/components/create-playlist/PlaylistForm.tsx @@ -106,7 +106,8 @@ const PlaylistForm = ({ ...newCollectionMetadata(metadata), artwork: oldFormFields.artwork, playlist_name: oldFormFields.playlist_name, - description: oldFormFields.description + description: oldFormFields.description, + is_image_autogenerated: oldFormFields.is_image_autogenerated })) } }, [metadata]) diff --git a/packages/web/src/components/suggested-tracks/SuggestedTracks.module.css b/packages/web/src/components/suggested-tracks/SuggestedTracks.module.css index d004b2b662..c0b0bce60d 100644 --- a/packages/web/src/components/suggested-tracks/SuggestedTracks.module.css +++ b/packages/web/src/components/suggested-tracks/SuggestedTracks.module.css @@ -35,6 +35,7 @@ .content { display: flex; flex-direction: column; + overflow: hidden; } .loading { diff --git a/packages/web/src/components/suggested-tracks/SuggestedTracks.tsx b/packages/web/src/components/suggested-tracks/SuggestedTracks.tsx index a7461a3622..d3d6a2b1e6 100644 --- a/packages/web/src/components/suggested-tracks/SuggestedTracks.tsx +++ b/packages/web/src/components/suggested-tracks/SuggestedTracks.tsx @@ -62,7 +62,7 @@ const SuggestedTrack = (props: SuggestedTrackProps) => { const handleAddTrack = useCallback(() => { onAddTrack(track_id, collectionId) - dispatch(toast({ content: messages.trackAdded })) + dispatch(toast({ content: messages.trackAdded, timeout: 1500 })) }, [onAddTrack, track_id, collectionId, dispatch]) return ( @@ -117,7 +117,7 @@ export const SuggestedTracks = (props: SuggestedTracksProps) => { const divider = const contentStyles = useSpring({ - maxHeight: isExpanded ? contentHeight : 0 + height: isExpanded ? contentHeight : 0 }) return (