') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); [PE-6448] Fix mobile track tile favorites and library loading by dylanjeffers · Pull Request #12409 · AudiusProject/apps · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/common/src/store/ui/buy-sell/useBuySellSwap.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -78,6 +78,7 @@ export const useBuySellSwap = (props: UseBuySellSwapProps) => {
clearTimeout(retryTimeoutRef.current)
}

// @ts-ignore - weird mobile type issue
retryTimeoutRef.current = setTimeout(() => {
invalidateBalances()
performSwap()
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
import { useCallback, useMemo } from 'react'

import { useCollection, useCurrentUserId, useUser } from '@audius/common/api'
import { useGatedCollectionAccess } from '@audius/common/hooks'
import {
ShareSource,
RepostSource,
Expand DownExpand Up@@ -90,6 +91,8 @@ export const CollectionTile = (props: CollectionTileProps) => {
})
})

const { hasStreamAccess } = useGatedCollectionAccess(id)

const currentTrack = useSelector((state: CommonState) => {
const uid = getUid(state)
return tracks.find((track) => track.uid === uid) ?? null
Expand DownExpand Up@@ -270,7 +273,7 @@ export const CollectionTile = (props: CollectionTileProps) => {
collection.is_album ? PurchaseableContentType.ALBUM : undefined
}
streamConditions={collection.stream_conditions}
hasStreamAccess={true} // This should be determined by the hook
hasStreamAccess={hasStreamAccess}
source={source}
onPressOverflow={handlePressOverflow}
onPressRepost={handlePressRepost}
Expand Down
8 changes: 6 additions & 2 deletions packages/mobile/src/components/lineup-tile/TrackTile.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -6,6 +6,7 @@ import {
useTrack,
useUser
} from '@audius/common/api'
import { useGatedTrackAccess } from '@audius/common/hooks'
import {
ShareSource,
RepostSource,
Expand DownExpand Up@@ -67,6 +68,7 @@ export const TrackTile = (props: TrackTileProps) => {
duration: track.duration,
field_visibility: track.field_visibility,
has_current_user_reposted: track.has_current_user_reposted,
has_current_user_saved: track.has_current_user_saved,
title: track.title,
track_id: track.track_id,
genre: track.genre,
Expand All@@ -88,6 +90,8 @@ export const TrackTile = (props: TrackTileProps) => {
})
})

const { hasStreamAccess } = useGatedTrackAccess(id)

const isPlayingUid = useSelector(
(state: CommonState) => getUid(state) === lineupTileProps.uid
)
Expand DownExpand Up@@ -261,15 +265,15 @@ export const TrackTile = (props: TrackTileProps) => {
{isReadonly ? null : (
<LineupTileActionButtons
hasReposted={track.has_current_user_reposted}
hasSaved={false} // This will be handled by the hook
hasSaved={track.has_current_user_saved}
isOwner={isOwner}
isShareHidden={hideShare}
isUnlisted={track.is_unlisted}
readonly={isReadonly}
contentId={track.track_id}
contentType={PurchaseableContentType.TRACK}
streamConditions={track.stream_conditions}
hasStreamAccess={true} // This should be determined by the hook
hasStreamAccess={hasStreamAccess}
source={lineupTileProps.source}
onPressOverflow={handlePressOverflow}
onPressRepost={handlePressRepost}
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
import { FavoritesScreen } from 'app/screens/library-screen'
import { LibraryScreen } from 'app/screens/library-screen'

import type { AppTabScreenParamList } from './AppTabScreen'
import { createAppTabScreenStack } from './createAppTabScreenStack'
Expand All@@ -11,6 +11,6 @@ export type FavoritesTabScreenParamList = AppTabScreenParamList & {
export const FavoritesTabScreen =
createAppTabScreenStack<FavoritesTabScreenParamList>((Stack) => (
<>
<Stack.Screen name='Library' component={FavoritesScreen} />
<Stack.Screen name='Library' component={LibraryScreen} />
</>
))
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
import { useCallback } from 'react'
import { useCallback, useEffect } from 'react'

import type { LibraryCategoryType } from '@audius/common/store'
import {
Expand DownExpand Up@@ -50,11 +50,12 @@ const ALL_CATEGORIES = [

const CATEGORIES_WITHOUT_PURCHASED = ALL_CATEGORIES.slice(0, -1)

type LibraryTabRouteName = 'albums' | 'tracks' | 'playlists'
type LibraryTabRouteName = 'Albums' | 'Tracks' | 'Playlists'

const ROUTE_NAME_TO_TAB = {
albums: LibraryPageTabs.ALBUMS,
tracks: LibraryPageTabs.TRACKS,
playlists: LibraryPageTabs.PLAYLISTS
Albums: LibraryPageTabs.ALBUMS,
Tracks: LibraryPageTabs.TRACKS,
Playlists: LibraryPageTabs.PLAYLISTS
} as Record<LibraryTabRouteName, LibraryPageTabs>

export const LibraryCategorySelectionMenu = () => {
Expand All@@ -80,7 +81,10 @@ export const LibraryCategorySelectionMenu = () => {
return LibraryPageTabs.TRACKS
}

return ROUTE_NAME_TO_TAB[routeName] || LibraryPageTabs.TRACKS
return (
ROUTE_NAME_TO_TAB[routeName as LibraryTabRouteName] ||
LibraryPageTabs.TRACKS
)
}) as LibraryPageTabs

const selectedCategory = useSelector((state) =>
Expand All@@ -89,6 +93,27 @@ export const LibraryCategorySelectionMenu = () => {
})
)

const isUSDCPurchasesEnabled = useIsUSDCEnabled()
const categories =
isUSDCPurchasesEnabled &&
(currentTab === LibraryPageTabs.TRACKS ||
currentTab === LibraryPageTabs.ALBUMS)
? ALL_CATEGORIES
: CATEGORIES_WITHOUT_PURCHASED

// Auto-switch to "All" if the selected category is not available for the current tab
useEffect(() => {
const availableCategoryValues = categories.map((category) => category.value)
if (!availableCategoryValues.includes(selectedCategory)) {
dispatch(
setSelectedCategory({
currentTab,
category: LibraryCategory.All
})
)
}
}, [currentTab, selectedCategory, categories, dispatch])

const handleChange = useCallback(
(category: string) => {
dispatch(
Expand All@@ -101,14 +126,6 @@ export const LibraryCategorySelectionMenu = () => {
[currentTab, dispatch]
)

const isUSDCPurchasesEnabled = useIsUSDCEnabled()
const categories =
isUSDCPurchasesEnabled &&
(currentTab === LibraryPageTabs.TRACKS ||
currentTab === LibraryPageTabs.ALBUMS)
? ALL_CATEGORIES
: CATEGORIES_WITHOUT_PURCHASED

return (
<View style={styles.container}>
<ScrollView
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ import { getCollectionDownloadStatus } from 'app/store/offline-downloads/selecto
import { makeStyles } from 'app/styles'

import { DownloadProgress } from './DownloadProgress'
import { FavoritesDownloadStatusIndicator } from './FavoritesDownloadStatusIndicator'
import { LibraryDownloadStatusIndicator } from './LibraryDownloadStatusIndicator'

const useStyles = makeStyles(() => ({
root: { flexDirection: 'row', alignItems: 'center' }
Expand DownExpand Up@@ -38,12 +38,12 @@ const OfflineListeningIndicatorButton = () => {

return (
<TouchableOpacity onPress={handlePressStatusIndicator}>
<FavoritesDownloadStatusIndicator switchValue={switchValue} />
<LibraryDownloadStatusIndicator switchValue={switchValue} />
</TouchableOpacity>
)
}

export const FavoritesDownloadSection = () => {
export const LibraryDownloadSection = () => {
const styles = useStyles()

return (
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ const useStyles = makeStyles(({ spacing }) => ({
}
}))

const getFavoritesDownloadStatus = (state: AppState) => {
const getLibraryDownloadStatus = (state: AppState) => {
const { collectionStatus } = state.offlineDownloads
const favoritedCollectionStatus = collectionStatus[DOWNLOAD_REASON_FAVORITES]

Expand All@@ -38,16 +38,16 @@ const getFavoritesDownloadStatus = (state: AppState) => {
return OfflineDownloadStatus.SUCCESS
}

type FavoritesDownloadStatusIndicatorProps = {
type LibraryDownloadStatusIndicatorProps = {
switchValue: boolean
}

export const FavoritesDownloadStatusIndicator = (
props: FavoritesDownloadStatusIndicatorProps
export const LibraryDownloadStatusIndicator = (
props: LibraryDownloadStatusIndicatorProps
) => {
const { switchValue } = props
const styles = useStyles()
const downloadStatus = useProxySelector(getFavoritesDownloadStatus, [])
const downloadStatus = useProxySelector(getLibraryDownloadStatus, [])

return (
<DownloadStatusIndicator
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,16 +14,16 @@ import { useAppTabScreen } from 'app/hooks/useAppTabScreen'
import { makeStyles } from 'app/styles'

import { AlbumsTab } from './AlbumsTab'
import { FavoritesDownloadSection } from './FavoritesDownloadSection'
import { LibraryCategorySelectionMenu } from './LibraryCategorySelectionMenu'
import { LibraryDownloadSection } from './LibraryDownloadSection'
import { PlaylistsTab } from './PlaylistsTab'
import { TracksTab } from './TracksTab'

const messages = {
header: 'Library'
}

const favoritesScreens = [
const libraryScreens = [
{
name: LibraryPageTabs.TRACKS,
Icon: IconNote,
Expand All@@ -49,7 +49,7 @@ const useHeaderStyles = makeStyles(({ spacing }) => ({
}
}))

export const FavoritesScreen = () => {
export const LibraryScreen = () => {
useAppTabScreen()
const headerStyles = useHeaderStyles()

Expand All@@ -61,14 +61,14 @@ export const FavoritesScreen = () => {
icon={IconLibrary}
styles={headerStyles}
>
<FavoritesDownloadSection />
<LibraryDownloadSection />
<LibraryCategorySelectionMenu />
</ScreenHeader>
</ScreenPrimaryContent>
<ScreenContent isOfflineCapable>
<ScreenSecondaryContent>
<TopTabNavigator
screens={favoritesScreens}
screens={libraryScreens}
screenOptions={{ lazy: true }}
/>
</ScreenSecondaryContent>
Expand Down
2 changes: 1 addition & 1 deletion packages/mobile/src/screens/library-screen/index.ts
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
export * from './FavoritesScreen'
export * from './LibraryScreen'
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,6 @@ import {
import { Status } from '@audius/common/models'
import {
libraryPageSelectors,
LibraryPageTabs,
reachabilitySelectors
} from '@audius/common/store'
import type { CommonState, CollectionType } from '@audius/common/store'
Expand All@@ -25,7 +24,7 @@ import { OfflineDownloadStatus } from 'app/store/offline-downloads/slice'

const { getIsReachable } = reachabilitySelectors
const {
getCategory,
getCollectionsCategory,
getSelectedCategoryLocalAlbumAdds,
getSelectedCategoryLocalAlbumRemovals,
getSelectedCategoryLocalPlaylistAdds,
Expand All@@ -43,14 +42,7 @@ export const useLibraryCollections = ({
}: UseLibraryCollectionsConfig) => {
const isDoneLoadingFromDisk = useSelector(getIsDoneLoadingFromDisk)
const isReachable = useSelector(getIsReachable)
const selectedCategory = useSelector((state) =>
getCategory(state, {
currentTab:
collectionType === 'albums'
? LibraryPageTabs.ALBUMS
: LibraryPageTabs.PLAYLISTS
})
)
const selectedCategory = useSelector(getCollectionsCategory)

const locallyAddedCollectionIds = useSelector((state: CommonState) => {
const ids =
Expand Down