Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
Move client to API Trending (#23)
Browse files Browse the repository at this point in the history
* Successfully hitting API

* First pass at consuming API successful

* Remove scoring and ordering from store

* Clean up APIClient

* Move APIClient

* Handle environments better, add in URL construction

* Use libs selected discprov in AudiusAPIClient

* Use eager discprov selection in APIClient

* Polish

* More polish

* Fix apiClient.init() saga bug

* Handle trending response errors

* Fix trending tabs issue

* Clean up

Co-authored-by: Raymond Jacobson <ray@audius.co>
  • Loading branch information
piazzatron and raymondjacobson authored Sep 26, 2020
1 parent c9d1d7c commit 36b9ab4
Show file tree
Hide file tree
Showing 48 changed files with 619 additions and 367 deletions.
3 changes: 0 additions & 3 deletions src/components/artist/ArtistChip.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import DynamicImage from 'components/dynamic-image/DynamicImage'
import { SquareSizes } from 'models/common/ImageSizes'
import { useUserProfilePicture } from 'hooks/useImageSize'

import placeholderProfilePicture from 'assets/img/imageProfilePicEmpty2X.png'
import { ReactComponent as IconVerified } from 'assets/img/iconVerified.svg'
import styles from './ArtistChip.module.css'

Expand Down Expand Up @@ -55,7 +54,6 @@ ArtistChip.propTypes = {
className: PropTypes.string,
userId: PropTypes.number,
profilePictureSizes: PropTypes.object,
profileImgUrl: PropTypes.string,
name: PropTypes.string,
handle: PropTypes.string,
followers: PropTypes.number,
Expand All @@ -65,7 +63,6 @@ ArtistChip.propTypes = {
}

ArtistChip.defaultProps = {
profileImgUrl: placeholderProfilePicture,
name: '',
followers: 0,
verified: false,
Expand Down
1 change: 0 additions & 1 deletion src/components/artist/UserListModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ export const UserListModal = props => {
userId={user.user_id}
followers={user.follower_count}
verified={user.is_verified}
profileImgUrl={user.profile_picture_url}
onClickArtistName={() => {
props.onClose()
props.onClickArtistName(user.handle)
Expand Down
1 change: 0 additions & 1 deletion src/components/artist/mobile/UserListModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ export const UserListModal = (props: UserListModalProps) => {
className={styles.artistChipContainer}
followers={user.follower_count}
verified={user.is_verified}
profileImgUrl={user.profile_picture_url}
onClickArtistName={() => {
props.onClose()
props.onClickArtistName(user.handle)
Expand Down
3 changes: 0 additions & 3 deletions src/components/card/UserCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import cn from 'classnames'
import { formatCount } from 'utils/formatUtil'

import styles from './UserCard.module.css'
import placeholderArt from 'assets/img/imageProfilePicEmpty2X.png'
import { ReactComponent as IconVerified } from 'assets/img/iconVerified.svg'
import DynamicImage from 'components/dynamic-image/DynamicImage'
import { SquareSizes } from 'models/common/ImageSizes'
Expand Down Expand Up @@ -57,7 +56,6 @@ const UserCard = ({
UserCard.propTypes = {
className: PropTypes.string,
name: PropTypes.string,
profileImageUrl: PropTypes.string,
isVerified: PropTypes.bool,
isMobile: PropTypes.bool,
followers: PropTypes.number,
Expand All @@ -67,7 +65,6 @@ UserCard.propTypes = {

UserCard.defaultProps = {
isVerified: true,
profileImageUrl: placeholderArt,
onFollow: () => {},
name: '',
followers: 0,
Expand Down
1 change: 0 additions & 1 deletion src/components/card/desktop/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ type CardProps = {
imageSize: ProfilePictureSizes | CoverArtSizes | null
primaryText: string | React.ReactNode
secondaryText: string | React.ReactNode
cardCoverImageUrl?: string
cardCoverImageSizes?: CoverArtSizes
playlistName?: string
isUser: boolean
Expand Down
1 change: 0 additions & 1 deletion src/containers/discover-page/components/EmptyFeed.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ EmptyFeed.propTypes = {
PropTypes.shape({
user_id: PropTypes.number,
name: PropTypes.string,
profile_picture_url: PropTypes.string,
handle: PropTypes.string,
is_verified: PropTypes.bool,
follower_count: PropTypes.number
Expand Down
1 change: 0 additions & 1 deletion src/containers/discover-page/components/FollowUsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ const FollowUsers = props => {
name={user.name}
selected={followUsers.includes(user.user_id)}
onClick={onUserClick(user.user_id)}
profileImageUrl={user.profile_picture_url}
isVerified={user.is_verified}
followers={user.follower_count}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ const TrendingPageContent = (props: DiscoverPageContentProps) => {
currentLineup.lineup.status !== Status.LOADING) ||
(!unfetchedLineup &&
currentLineup.lineup.status === Status.SUCCESS &&
!(currentLineup.lineup as any).trendingOrder.length &&
!currentLineup.lineup.entries.length &&
trendingGenre !== null)

if (shouldMoveToNextTab) {
Expand Down
7 changes: 0 additions & 7 deletions src/containers/discover-page/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ export const SET_TRENDING_GENRE = 'DISCOVER/SET_TRENDING_GENRE'
export const SET_TRENDING_TIME_RANGE = 'DISCOVER/SET_TRENDING_TIME_RANGE'
export const SET_LAST_FETCHED_TRENDING_GENRE =
'DISCOVER/SET_LAST_FETCHED_TRENDING_GENRE'
export const SET_LAST_FETCHED_TIME_RANGE =
'DISCOVER/SET_LAST_FETCHED_TIME_RANGE'

export const fetchSuggestedFollowUsers = () => ({
type: FETCH_SUGGESTED_FOLLOW_USERS
Expand Down Expand Up @@ -43,8 +41,3 @@ export const setLastFetchedTrendingGenre = genre => ({
type: SET_LAST_FETCHED_TRENDING_GENRE,
genre
})

export const setLastFetchedTimeRange = timeRange => ({
type: SET_LAST_FETCHED_TIME_RANGE,
timeRange
})
20 changes: 5 additions & 15 deletions src/containers/discover-page/store/lineups/trending/actions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LineupActions, addPrefix } from 'store/lineup/actions'
import { LineupActions } from 'store/lineup/actions'

export const PREFIX = 'DISCOVER_TRENDING'
export const TRENDING_WEEK_PREFIX = 'DISCOVER_TRENDING_WEEK'
Expand All @@ -7,34 +7,24 @@ export const TRENDING_YEAR_PREFIX = 'DISCOVER_TRENDING_YEAR'

export const SET_TRENDING_SCORES = 'SET_TRENDING_SCORES'

export class BaseTrendingActions extends LineupActions {
setTrendingScores(trendingOrder, trendingStats) {
return {
type: addPrefix(this.prefix, SET_TRENDING_SCORES),
trendingOrder,
trendingStats
}
}
}

class TrendingActions extends BaseTrendingActions {
class TrendingActions extends LineupActions {
constructor() {
super(PREFIX)
}
}

class TrendingWeekActions extends BaseTrendingActions {
class TrendingWeekActions extends LineupActions {
constructor() {
super(TRENDING_WEEK_PREFIX)
}
}

class TrendingMonthActions extends BaseTrendingActions {
class TrendingMonthActions extends LineupActions {
constructor() {
super(TRENDING_MONTH_PREFIX)
}
}
class TrendingYearActions extends BaseTrendingActions {
class TrendingYearActions extends LineupActions {
constructor() {
super(TRENDING_YEAR_PREFIX)
}
Expand Down
24 changes: 1 addition & 23 deletions src/containers/discover-page/store/lineups/trending/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { initialLineupState } from 'store/lineup/reducer'
import { RESET_SUCCEEDED, stripPrefix } from 'store/lineup/actions'
import {
PREFIX,
SET_TRENDING_SCORES,
TRENDING_WEEK_PREFIX,
TRENDING_MONTH_PREFIX,
TRENDING_YEAR_PREFIX
Expand All @@ -12,35 +11,14 @@ const initialState = {
...initialLineupState,
antiBot: true,
dedupe: true,
prefix: PREFIX,

// Array<{
// track_id,
// }>
trendingOrder: [],
// { track_id:
// {
// listens,
// repost_count,
// save_count,
// track_owner_follower_count,
// }
// }
trendingStats: []
prefix: PREFIX
}

const makeActionsMap = initialState => {
return {
[RESET_SUCCEEDED](state, action) {
const newState = initialState
return newState
},
[SET_TRENDING_SCORES](state, action) {
return {
...state,
trendingOrder: action.trendingOrder,
trendingStats: action.trendingStats
}
}
}
}
Expand Down
142 changes: 22 additions & 120 deletions src/containers/discover-page/store/lineups/trending/sagas.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
import { call, put, select } from 'redux-saga/effects'
import { select } from 'redux-saga/effects'

import AudiusBackend from 'services/AudiusBackend'
import { makeGetTrendingOrder, makeGetTrendingStats } from './selectors'
import {
setLastFetchedTrendingGenre,
setLastFetchedTimeRange
} from 'containers/discover-page/store/actions'
import { LineupSagas } from 'store/lineup/sagas'
import TimeRange from 'models/TimeRange'

import { getTrendingScore, sortByTrendingScore } from 'utils/trendingScorer'

import {
getTrendingGenre,
getLastFetchedTrendingGenre
} from 'containers/discover-page/store/selectors'
import { getTrendingGenre } from 'containers/discover-page/store/selectors'

import {
TRENDING_WEEK_PREFIX,
Expand All @@ -24,108 +13,27 @@ import {
trendingMonthActions,
trendingYearActions
} from './actions'
import { retrieveTracks } from 'store/cache/tracks/utils'

const getActionSet = timeRange => {
return {
[TimeRange.WEEK]: trendingWeekActions,
[TimeRange.MONTH]: trendingMonthActions,
[TimeRange.YEAR]: trendingYearActions
}[timeRange]
}

function* getTrendingOrderAndStats(timeRange, genre) {
const trendingResponse = yield call(AudiusBackend.getTrendingTracks, {
offset: 0,
limit: 200,
timeRange,
genre: genre
})
const trendingOrder = trendingResponse.listen_counts
.sort(sortByTrendingScore(timeRange))
.map(t => t.track_id)
const trendingStats = trendingResponse.listen_counts.reduce((stats, t) => {
stats[t.track_id] = {
...t,
score: getTrendingScore(t, timeRange)
}
return stats
}, {})
return { trendingOrder, trendingStats }
}
import { getUserId } from 'store/account/selectors'
import { retrieveTrending } from 'containers/track-page/store/retrieveTrending'

// This will return true if it stored the response, false if the genre changed and it didn't store.
function* fetchTrendingScores(timeRange, genreAtStart) {
const { trendingOrder, trendingStats } = yield call(
getTrendingOrderAndStats,
timeRange,
genreAtStart
)

const actionSet = getActionSet(timeRange)
const genreAtEnd = yield select(getTrendingGenre)
if (genreAtStart !== genreAtEnd) return false

yield put(actionSet.setTrendingScores(trendingOrder, trendingStats))
return true
}

// Injects a timeRange provider function getTracks. Allows us to
// specialize a getTracks function for different lineup sagas.
function makeGetTracks(timeRangeProvider) {
function getTracks(timeRange) {
return function* ({ offset, limit }) {
return yield getTracks({ timeRangeProvider, offset, limit })
}
}

function* getTracks({ timeRangeProvider, offset, limit }) {
const timeRange = yield timeRangeProvider()
const [getTrendingOrder, getTrendingStats] = [
makeGetTrendingOrder(timeRange),
makeGetTrendingStats(timeRange)
]

// Refetch when the last fetched genre isn't the one being requested
const genreAtStart = yield select(getTrendingGenre)
const lastGenre = yield select(getLastFetchedTrendingGenre)

let trendingStats = yield select(getTrendingStats)
let trendingOrder = yield select(getTrendingOrder)

const needsNewScores =
!Object.keys(trendingStats).length ||
!trendingOrder.length ||
genreAtStart !== lastGenre

if (needsNewScores) {
const didFetch = yield call(fetchTrendingScores, timeRange, genreAtStart)
if (!didFetch) return null

trendingStats = yield select(getTrendingStats)
trendingOrder = yield select(getTrendingOrder)
}

let ret
if (trendingOrder.length > 0) {
const trackIds = yield call(retrieveTracks, {
trackIds: trendingOrder.slice(offset, offset + limit)
})

// If we've changed genres since we kicked off this call, we shouldn't
// save the trackIds.
const genreAtEnd = yield select(getTrendingGenre)
if (genreAtStart !== genreAtEnd) {
return null
const genreAtStart = yield select(getTrendingGenre)
const userId = yield select(getUserId)
try {
const tracks = yield retrieveTrending({
timeRange,
limit,
offset,
genre: genreAtStart,
currentUserId: userId
})
return tracks
} catch (e) {
console.error(`Trending error: ${e.message}`)
return []
}

ret = trackIds
} else {
ret = []
}

yield put(setLastFetchedTrendingGenre(genreAtStart))
yield put(setLastFetchedTimeRange(timeRange))
return ret
}

class TrendingWeekSagas extends LineupSagas {
Expand All @@ -134,9 +42,7 @@ class TrendingWeekSagas extends LineupSagas {
TRENDING_WEEK_PREFIX,
trendingWeekActions,
store => store.discover.trendingWeek,
makeGetTracks(function* () {
return yield TimeRange.WEEK
})
getTracks(TimeRange.WEEK)
)
}
}
Expand All @@ -147,9 +53,7 @@ class TrendingMonthSagas extends LineupSagas {
TRENDING_MONTH_PREFIX,
trendingMonthActions,
store => store.discover.trendingMonth,
makeGetTracks(function* () {
return yield TimeRange.MONTH
})
getTracks(TimeRange.MONTH)
)
}
}
Expand All @@ -160,9 +64,7 @@ class TrendingYearSagas extends LineupSagas {
TRENDING_YEAR_PREFIX,
trendingYearActions,
store => store.discover.trendingYear,
makeGetTracks(function* () {
return yield TimeRange.YEAR
})
getTracks(TimeRange.YEAR)
)
}
}
Expand Down
11 changes: 0 additions & 11 deletions src/containers/discover-page/store/lineups/trending/selectors.js

This file was deleted.

Loading

0 comments on commit 36b9ab4

Please sign in to comment.