[PAY-1202] Refactor saved collections fetching#3337
Conversation
|
Preview this change https://demo.audius.co/pay-1202-refactor-saved-collections |
|
Preview this change https://demo.audius.co/pay-1202-refactor-saved-collections |
sliptype
left a comment
There was a problem hiding this comment.
Awesome work! All looks good to me
| const dispatch = useDispatch() | ||
| const [hasFetched, setHasFetched] = useState(false) | ||
| const { unfetched: unfetchedAlbums, fetched: albumsWithDetails } = | ||
| useSelector(getAlbumsWithDetails) |
There was a problem hiding this comment.
The return value isn't really implied by the name getAlbumsWithDetails, is there a better name for this selector?
There was a problem hiding this comment.
I can update the selector name and add a comment
| } | ||
|
|
||
| /* TODO: Handle filtering | ||
| * Option 1: This hook takes the list of album ids to fetch and computes the unfetched |
There was a problem hiding this comment.
Option 1 seems good to me
piazzatron
left a comment
There was a problem hiding this comment.
Very clean and easy to review! Only nits :)
| tracks: TracksCacheState | ||
| users: UsersCacheState | ||
|
|
||
| savedCollections: SavedCollectionsState |
There was a problem hiding this comment.
nit: IMO a bit cleaner to use the ReturnType of the reducer here, and then we don't have to export the state
There was a problem hiding this comment.
I believe I did try to do this originally, but the value returned from ReturnType had some issues that made it a problem to consume in the calling code (I think a few fields were incorrectly marked as possibly null or any?)
There was a problem hiding this comment.
Huh, nevermind I guess It works just fine!
There was a problem hiding this comment.
We've tended to colocate action types in their corresponding slice in the past – this is nice too but would opt for consistency one way or the other (cc @sliptype)
There was a problem hiding this comment.
I was using notifications as the most recent example, which puts types in a separate file.
There was a problem hiding this comment.
notifications is a bit of a special case since there are so many notification types - from a few weeks ago, looks like are keeping action types in the same file for the AI attributed slice: https://github.com/AudiusProject/audius-client/blob/main/packages/common/src/store/pages/ai/slice.ts
There was a problem hiding this comment.
Got it. The other complicating factor here is that there are types shared between the slice and selectors module and I don't really want to import selectors just to get at the types.
Historically, in TS, as soon as a type is used in multiple places I pull it out into a types file to remove the future possibility of circular dependencies.
So I can move just the action types if that's the pattern we are going for. But we will still have the types file.
| // Request ids in chunks if we're asked for too many | ||
| const chunks = chunk(ids, COLLECTIONS_BATCH_LIMIT) | ||
| for (let i = 0; i < chunks.length; i += 1) { | ||
| yield call(retrieveCollections, null, chunks[i]) |
There was a problem hiding this comment.
I wonder if we should rename/deprecate retrieveCollections or add a comment indicating that it doesn't paginate and that future callers should hit fetchCollectionChunks instead?
There was a problem hiding this comment.
That's not a bad idea. At the very least, I can add a comment to retrieveCollections stating that it's not appropriate for fetching large numbers of collections. Or... I suppose I could have just updated retrieveCollections to do the chunking...
There was a problem hiding this comment.
Updated to do this in retrieveCollections. Turns out we were already doing chunking for track fetching! So I updated both patterns to match.
| currentUserReposted: PropTypes.boolean, | ||
| currentUserSaved: PropTypes.boolean, | ||
| currentUserReposted: PropTypes.bool, | ||
| currentUserSaved: PropTypes.bool, |
| import { push as pushRoute } from 'connected-react-router' | ||
| import { useDispatch } from 'react-redux' | ||
|
|
||
| export function useGoToRoute() { |
| primaryText='You haven’t favorited any albums yet.' | ||
| secondaryText='Once you have, this is where you’ll find them!' | ||
| buttonLabel='Go to Trending' |
There was a problem hiding this comment.
nit: could pull these out into a messages object as campground cleaning (this file might have been around prior to that convention!)
There was a problem hiding this comment.
Oh yep. Definitely just moved code around without looking at it here. Will put into a messages object.
| album: CollectionWithOwner | ||
| } | ||
|
|
||
| const AlbumCard = ({ album, index, isLoading, setDidLoad }: AlbumCardProps) => { |
There was a problem hiding this comment.
Good looks pulling these out into standalone components
| return | ||
| } | ||
| const ids = unfetchedAlbums | ||
| .slice(0, Math.min(pageSize, unfetchedAlbums.length)) |
There was a problem hiding this comment.
Doesn't the saga layer already chunk this via your fetchCollectionChunks fn?
There was a problem hiding this comment.
Yes, but there are two layers. This is intended for future use where we are calling fetchMore here and it's fetching the next X album records using the underlying saga. This has a configurable page size based on how many you want to fetch at once in a particular component.
The saga has no notion of page sizes. It's just a bulk fetch that guards against 400s by chunking up the list if you ask for too many at once.
For most purposes, the pageSize here will be much less than the chunk size in the saga. (i.e. we shoudn't ever trigger the saga's chunking.
There was a problem hiding this comment.
Could we lose getFilteredAlbums?
There was a problem hiding this comment.
Oh yep. Good catch. I had left it until I decided what to do about filtering. But it won't be used either way.
|
Preview this change https://demo.audius.co/pay-1202-refactor-saved-collections |
|
@piazzatron @sliptype Mind looking at these two changes as well? |
|
Preview this change https://demo.audius.co/pay-1202-refactor-saved-collections |
2863089 to
437e164
Compare
|
Preview this change https://demo.audius.co/pay-1202-refactor-saved-collections |
[9855fd2] Update locks (#3397) Dylan Jeffers [aecef5f] [PAY-1144] [PAY-1182] [PAY-1147] DMs: Delete chat, message permissions (#3390) Marcus Pasell [64ccd9d] Add stylelint to ci (#3373) Dylan Jeffers [b642a16] [C-2518, C-2523, C-2611] Improve playlist create sagas (#3378) Dylan Jeffers [5620d53] [PAY-1197] Mobile inbox unavailable modal from profile screen (#3376) Reed [2ebaef5] [PAY-1248] Initial changes to get ready for upcoming PRs that include track and playlist tiles in DMs (#3391) Saliou Diallo [c2fabf6] [PAY-1218] Mobile block dms drawer switches block/unblock (#3387) Reed [0acad29] [C-2575] Match length of related artists user list to preview (#3395) Andrew Mendelsohn [40525ae] [C-2615] Fix favorite tracks error due to empty track entries on web mobile (#3386) Kyle Shanks [93a8077] [PAY-1145] DMs: Add InboxUnavailableModal (#3369) Marcus Pasell [633484d] Update edit playlist flow and components (#3361) Kyle Shanks [334ea0d] Special case ios safari for stem download (#3385) Raymond Jacobson [d38238d] [C-2607] Pagination wrapper hooks for audius-query (#3375) Andrew Mendelsohn [0a332d8] Hotfix: Fix stems downloads on mobile web (#3382) Marcus Pasell [81da65e] Clean up artist_pick_track_id in APIUser (#3381) Michelle Brier [64d89ef] Fix lint (#3380) Raymond Jacobson [59129b4] [C-2614] Fix download stems mobile web (#3379) Raymond Jacobson [df68727] [PAY-1032][PAY-892] Mobile DMs unread indicator, prefetch chats (#3352) Reed [4a00fad] [PAY-1151] Handle chat reactions near top of screen on mobile (#3370) Reed [bff316f] [PAY-1139] Throttle calls to fetchMessages on web scroll (#3372) Michael Piazza [e723cec] C-2483 Fix queue overshot empty track player bug (#3353) nicoback2 [472a41d] [C-2596] Add disabled option to audius-query hooks (#3367) Andrew Mendelsohn [f518962] [C-2602] Improve playlist library layout (#3364) Dylan Jeffers [b3db8fa] Fix debounce on notif reaction (#3362) Raymond Jacobson [2104b2b] [PAY-1183] Make clicking ChatUser handle/displayname lead to profile (#3368) Michael Piazza [21cb6fc] DMs: Fix click handler in search user list for users you can't chat (#3358) Marcus Pasell [24e7d8a] DMs: Update copy, scroll inbox-settings modal (#3359) Marcus Pasell [e5e8d90] [PAY-941] Fix "1 new messages" unread tag (web) (#3366) Michael Piazza [cfa1b2a] [C-2603] Fix readonly object error in audius-query reducer (#3365) Andrew Mendelsohn [978c993] Fix invite reward claimable state on mobile (#3363) Reed [a174fcc] [C-2556, C-2557] Address AI Attribution QA (#3349) Dylan Jeffers [3c9b0f1] [PAY-1202] Refactor saved collections fetching (#3337) Randy Schott [a0bdad5] Get call to action for chat permissions (#3325) Marcus Pasell [03a2721] DMs: Use the optimistic unread count if applicable (#3354) Marcus Pasell [8b99c2b] [C-2550] Left-nav fixes and improvements (#3357) Dylan Jeffers [e7b0aab] [PAY-1215] Fix create new message crash (#3356) Reed [6e7ece9] [PAY-1196] Mobile dms search users empty state (#3355) Reed [315ae4f] [PAY-1219] Fix mobile chat reactions popup message getting cut off (#3342) Reed
Description
This is the first round of changes to improve the saved albums/playlists experience. This PR focuses on updates to the fetching logic.
Previously, the fetching was done in account sagas (
fetchSavedAlbumsAsyncandfetchSavedPlaylistsAsync), and all records were fetched in one API call. This breaks for more than about 80 ids passed. We were also using a large provider to fetch the data and then prop-drilling it down toSavedPageand its children.Changes
retrieveCollectionsdirectly to to use the new saga helper.fetchMorestyle pagination of full playlist metadata. It uses derived selectors to determine which playlists from the fully fetched album id list do not have local metadata.fetchMorewill collect the firstpage_sizeids and initiate a fetch for them. This will be used in future work to implement anInfiniteScrollcomponent. (Note: For now, we are using the new hook with a page size of 9999, which has the same effect as the previous "load everything at once" behavior)SavedPageProviderwebto follow the mobile patternsuseGoToRoutehook for components to consume if they need to push routes. We don't need to pass this down through props.There are some follow-up issues that I will address in future PRs, but nothing that wasn't already broken :-)
Dragons
This does change fetching logic on both mobile and web, though it should be in a way that doesn't break anything for users which were not already broken (i.e. users who had too many playlists to fetch safely)
How Has This Been Tested?
Tested on desktop, mobile web, and local emulator to ensure playlists and albums still load correctly.
How will this change be monitored?
Will test as part of client release process. Will monitor sentry and rollback if any major issues occur.
Feature Flags
N/A