diff --git a/packages/mobile/src/screens/favorites-screen/AlbumsTab.tsx b/packages/mobile/src/screens/favorites-screen/AlbumsTab.tsx index 5c38f75f4b..30e2556eaf 100644 --- a/packages/mobile/src/screens/favorites-screen/AlbumsTab.tsx +++ b/packages/mobile/src/screens/favorites-screen/AlbumsTab.tsx @@ -1,29 +1,17 @@ -import { useMemo, useState } from 'react' +import { useState } from 'react' -import { - useProxySelector, - reachabilitySelectors, - shallowCompare -} from '@audius/common' +import { reachabilitySelectors } from '@audius/common' import { useSelector } from 'react-redux' import { CollectionList } from 'app/components/collection-list' import { VirtualizedScrollView } from 'app/components/core' import { EmptyTileCTA } from 'app/components/empty-tile-cta' import { useIsOfflineModeEnabled } from 'app/hooks/useIsOfflineModeEnabled' -import type { AppState } from 'app/store' -import { - getOfflineTrackStatus, - getIsDoneLoadingFromDisk, - getOfflineCollectionsStatus -} from 'app/store/offline-downloads/selectors' -import { OfflineDownloadStatus } from 'app/store/offline-downloads/slice' import { FilterInput } from './FilterInput' import { NoTracksPlaceholder } from './NoTracksPlaceholder' import { OfflineContentBanner } from './OfflineContentBanner' -import { getAccountCollections } from './selectors' -import { buildCollectionIdsToNumPlayableTracksMap } from './utils' +import { useCollectionScreenData } from './useCollectionScreenData' const { getIsReachable } = reachabilitySelectors @@ -34,75 +22,10 @@ const messages = { export const AlbumsTab = () => { const [filterValue, setFilterValue] = useState('') + const { filteredCollections: userAlbums, collectionIdsToNumTracks } = + useCollectionScreenData(filterValue, 'albums') const isReachable = useSelector(getIsReachable) const isOfflineModeEnabled = useIsOfflineModeEnabled() - const isDoneLoadingFromDisk = useSelector(getIsDoneLoadingFromDisk) - - const offlineTracksStatus = useProxySelector( - (state: AppState) => { - if (isDoneLoadingFromDisk && isOfflineModeEnabled && !isReachable) { - return getOfflineTrackStatus(state) - } - // We don't need offline download status when we're not offline. This saves us rerenders while we're downloading things and updating the offline download slice. - return undefined - }, - [isReachable, isOfflineModeEnabled, isDoneLoadingFromDisk] - ) - - const userAlbums = useProxySelector( - (state: AppState) => { - if (isOfflineModeEnabled && !isReachable) { - if (!isDoneLoadingFromDisk) { - return [] - } - } - const offlineCollectionsStatus = getOfflineCollectionsStatus(state) - return getAccountCollections(state, filterValue).filter((collection) => { - if (!collection.is_album) { - return false - } - if (isOfflineModeEnabled && !isReachable) { - const trackIds = - collection.playlist_contents.track_ids.map( - (trackData) => trackData.track - ) ?? [] - const collectionDownloadStatus = - offlineCollectionsStatus[collection.playlist_id] - // Don't show a playlist in Offline Mode if it has at least one track but none of the tracks have been downloaded yet OR if it is not marked for download - return ( - collection.is_album && - Boolean(collectionDownloadStatus) && - collectionDownloadStatus !== OfflineDownloadStatus.INACTIVE && - (trackIds.length === 0 || - trackIds.some((t) => { - return ( - offlineTracksStatus && - offlineTracksStatus[t.toString()] === - OfflineDownloadStatus.SUCCESS - ) - })) - ) - } - return true - }) - }, - [ - filterValue, - isReachable, - isOfflineModeEnabled, - isDoneLoadingFromDisk, - offlineTracksStatus - ], - shallowCompare - ) - - const numPlayableTracksMap = useMemo(() => { - return buildCollectionIdsToNumPlayableTracksMap( - userAlbums, - isOfflineModeEnabled && !isReachable, - offlineTracksStatus || {} - ) - }, [isOfflineModeEnabled, isReachable, offlineTracksStatus, userAlbums]) return ( @@ -124,7 +47,7 @@ export const AlbumsTab = () => { listKey='favorites-albums' scrollEnabled={false} collection={userAlbums} - collectionIdsToNumTracks={numPlayableTracksMap} + collectionIdsToNumTracks={collectionIdsToNumTracks} style={{ marginVertical: 12 }} /> diff --git a/packages/mobile/src/screens/favorites-screen/PlaylistsTab.tsx b/packages/mobile/src/screens/favorites-screen/PlaylistsTab.tsx index be3ff48a25..d1f68c7c2a 100644 --- a/packages/mobile/src/screens/favorites-screen/PlaylistsTab.tsx +++ b/packages/mobile/src/screens/favorites-screen/PlaylistsTab.tsx @@ -1,33 +1,21 @@ -import { useCallback, useMemo, useState } from 'react' +import { useCallback, useState } from 'react' -import { - useProxySelector, - reachabilitySelectors, - shallowCompare -} from '@audius/common' +import { reachabilitySelectors } from '@audius/common' import Animated, { FadeIn, FadeOut, Layout } from 'react-native-reanimated' import { useSelector } from 'react-redux' import { CollectionList } from 'app/components/collection-list' -import { VirtualizedScrollView, Button } from 'app/components/core' +import { Button, VirtualizedScrollView } from 'app/components/core' import { EmptyTileCTA } from 'app/components/empty-tile-cta' import { useIsOfflineModeEnabled } from 'app/hooks/useIsOfflineModeEnabled' import { useNavigation } from 'app/hooks/useNavigation' -import type { AppState } from 'app/store' -import { - getIsDoneLoadingFromDisk, - getOfflineCollectionsStatus, - getOfflineTrackStatus -} from 'app/store/offline-downloads/selectors' -import { OfflineDownloadStatus } from 'app/store/offline-downloads/slice' import type { FavoritesTabScreenParamList } from '../app-screen/FavoritesTabScreen' import { FilterInput } from './FilterInput' import { NoTracksPlaceholder } from './NoTracksPlaceholder' import { OfflineContentBanner } from './OfflineContentBanner' -import { getAccountCollections } from './selectors' -import { buildCollectionIdsToNumPlayableTracksMap } from './utils' +import { useCollectionScreenData } from './useCollectionScreenData' const { getIsReachable } = reachabilitySelectors @@ -38,80 +26,16 @@ const messages = { export const PlaylistsTab = () => { const navigation = useNavigation() - const [filterValue, setFilterValue] = useState('') - const isOfflineModeEnabled = useIsOfflineModeEnabled() - const isReachable = useSelector(getIsReachable) - const isDoneLoadingFromDisk = useSelector(getIsDoneLoadingFromDisk) - const offlineTracksStatus = useProxySelector( - (state: AppState) => { - if (isDoneLoadingFromDisk && isOfflineModeEnabled && !isReachable) { - return getOfflineTrackStatus(state) - } - // We don't need offline download status when we're not offline. This saves us rerenders while we're downloading things and updating the offline download slice. - return undefined - }, - [isReachable, isOfflineModeEnabled, isDoneLoadingFromDisk] - ) - - const userPlaylists = useProxySelector( - (state: AppState) => { - if (isOfflineModeEnabled && !isReachable) { - if (!isDoneLoadingFromDisk) { - return [] - } - } - const offlineCollectionsStatus = getOfflineCollectionsStatus(state) - return getAccountCollections(state, filterValue).filter((collection) => { - if (collection.is_album) { - return false - } - if (isOfflineModeEnabled && !isReachable) { - const trackIds = - collection.playlist_contents.track_ids.map( - (trackData) => trackData.track - ) ?? [] - const collectionDownloadStatus = - offlineCollectionsStatus[collection.playlist_id] - // Don't show a playlist in Offline Mode if it has at least one track but none of the tracks have been downloaded yet OR if it is not marked for download - return ( - !collection.is_album && - Boolean(collectionDownloadStatus) && - collectionDownloadStatus !== OfflineDownloadStatus.INACTIVE && - (trackIds.length === 0 || - trackIds.some((t) => { - return ( - offlineTracksStatus && - offlineTracksStatus[t.toString()] === - OfflineDownloadStatus.SUCCESS - ) - })) - ) - } - return true - }) - }, - [ - filterValue, - isReachable, - isOfflineModeEnabled, - isDoneLoadingFromDisk, - offlineTracksStatus - ], - shallowCompare - ) - - const numPlayableTracksMap = useMemo(() => { - return buildCollectionIdsToNumPlayableTracksMap( - userPlaylists, - isOfflineModeEnabled && !isReachable, - offlineTracksStatus || {} - ) - }, [isOfflineModeEnabled, isReachable, offlineTracksStatus, userPlaylists]) - const handleNavigateToNewPlaylist = useCallback(() => { navigation.push('CreatePlaylist') }, [navigation]) + const [filterValue, setFilterValue] = useState('') + const { filteredCollections: userPlaylists, collectionIdsToNumTracks } = + useCollectionScreenData(filterValue, 'playlists') + const isOfflineModeEnabled = useIsOfflineModeEnabled() + const isReachable = useSelector(getIsReachable) + return ( {!userPlaylists?.length && !filterValue ? ( @@ -143,7 +67,7 @@ export const PlaylistsTab = () => { listKey='favorites-playlists' scrollEnabled={false} collection={userPlaylists} - collectionIdsToNumTracks={numPlayableTracksMap} + collectionIdsToNumTracks={collectionIdsToNumTracks} /> diff --git a/packages/mobile/src/screens/favorites-screen/useCollectionScreenData.ts b/packages/mobile/src/screens/favorites-screen/useCollectionScreenData.ts new file mode 100644 index 0000000000..456f5bd4b6 --- /dev/null +++ b/packages/mobile/src/screens/favorites-screen/useCollectionScreenData.ts @@ -0,0 +1,109 @@ +import { useMemo } from 'react' + +import { + reachabilitySelectors, + shallowCompare, + useProxySelector +} from '@audius/common' +import { useSelector } from 'react-redux' + +import { useIsOfflineModeEnabled } from 'app/hooks/useIsOfflineModeEnabled' +import type { AppState } from 'app/store' +import { + getIsDoneLoadingFromDisk, + getOfflineCollectionsStatus, + getOfflineTrackStatus +} from 'app/store/offline-downloads/selectors' +import { OfflineDownloadStatus } from 'app/store/offline-downloads/slice' + +import { getAccountCollections } from './selectors' +import { buildCollectionIdsToNumPlayableTracksMap } from './utils' + +const { getIsReachable } = reachabilitySelectors + +export const useCollectionScreenData = ( + filterValue = '', + collectionType: 'albums' | 'playlists' +) => { + const isDoneLoadingFromDisk = useSelector(getIsDoneLoadingFromDisk) + const isReachable = useSelector(getIsReachable) + const isOfflineModeEnabled = useIsOfflineModeEnabled() + const offlineTracksStatus = useProxySelector( + (state: AppState) => { + if (isDoneLoadingFromDisk && isOfflineModeEnabled && !isReachable) { + return getOfflineTrackStatus(state) + } + // We don't need offline download status when we're not offline. This saves us rerenders while we're downloading things and updating the offline download slice. + return undefined + }, + [isReachable, isOfflineModeEnabled, isDoneLoadingFromDisk] + ) + + const filteredCollections = useProxySelector( + (state: AppState) => { + if (isOfflineModeEnabled && !isReachable) { + if (!isDoneLoadingFromDisk) { + return [] + } + } + const offlineCollectionsStatus = getOfflineCollectionsStatus(state) + return getAccountCollections(state, filterValue).filter((collection) => { + const isCollectionCorrectType = + collectionType === 'albums' + ? collection.is_album + : !collection.is_album + if (!isCollectionCorrectType) { + return false + } + if (isOfflineModeEnabled && !isReachable) { + const trackIds = + collection.playlist_contents.track_ids.map( + (trackData) => trackData.track + ) ?? [] + const collectionDownloadStatus = + offlineCollectionsStatus[collection.playlist_id] + // Don't show a playlist in Offline Mode if it has at least one track but none of the tracks have been downloaded yet OR if it is not marked for download + return ( + isCollectionCorrectType && + Boolean(collectionDownloadStatus) && + collectionDownloadStatus !== OfflineDownloadStatus.INACTIVE && + (trackIds.length === 0 || + trackIds.some((t) => { + return ( + offlineTracksStatus && + offlineTracksStatus[t.toString()] === + OfflineDownloadStatus.SUCCESS + ) + })) + ) + } + return true + }) + }, + [ + filterValue, + isReachable, + isOfflineModeEnabled, + isDoneLoadingFromDisk, + offlineTracksStatus + ], + shallowCompare + ) + const numPlayableTracksMap = useMemo(() => { + return buildCollectionIdsToNumPlayableTracksMap( + filteredCollections, + isOfflineModeEnabled && !isReachable, + offlineTracksStatus || {} + ) + }, [ + isOfflineModeEnabled, + isReachable, + offlineTracksStatus, + filteredCollections + ]) + + return { + filteredCollections, + collectionIdsToNumTracks: numPlayableTracksMap + } +}