diff --git a/.changeset/remove-legacy-lineup-scaffolding.md b/.changeset/remove-legacy-lineup-scaffolding.md new file mode 100644 index 00000000000..816d8ce4c18 --- /dev/null +++ b/.changeset/remove-legacy-lineup-scaffolding.md @@ -0,0 +1,5 @@ +--- +'@audius/common': patch +--- + +Remove the unused legacy lineup store module (`store/lineup`: `lineupActions`, `lineupReducer`, `lineupSelectors`, `LineupBaseActions`, `lineupRegistry`) from `@audius/common`. The lineup engine has been fully migrated to tan-query hooks plus the playback slice; these exports had no remaining consumers and were not wired into any store. diff --git a/packages/common/src/store/index.ts b/packages/common/src/store/index.ts index 62900329824..78bddd5fc8d 100644 --- a/packages/common/src/store/index.ts +++ b/packages/common/src/store/index.ts @@ -5,7 +5,6 @@ export * from './buy-usdc' export * from './cache' export * from './cast' export * from './challenges' -export * from './lineup' export * from './notifications' export * from './pages' export * from './playlist-library' diff --git a/packages/common/src/store/lineup/actions.ts b/packages/common/src/store/lineup/actions.ts deleted file mode 100644 index 8d5b829d763..00000000000 --- a/packages/common/src/store/lineup/actions.ts +++ /dev/null @@ -1,291 +0,0 @@ -import { Collection, LineupEntry, PlaybackSource } from '~/models' - -import { ID, UID } from '../../models/Identifiers' -import { Track, TrackMetadata } from '../../models/Track' - -export const FETCH_LINEUP_METADATAS = 'FETCH_LINEUP_METADATAS' -export const FETCH_LINEUP_METADATAS_REQUESTED = - 'FETCH_LINEUP_METADATAS_REQUESTED' -export const FETCH_LINEUP_METADATAS_SUCCEEDED = - 'FETCH_LINEUP_METADATAS_SUCCEEDED' -export const FETCH_LINEUP_METADATAS_FAILED = 'FETCH_LINEUP_METADATAS_FAILED' - -export const FETCH_TRACKS_METADATAS = 'FETCH_TRACKS_METADATAS' -export const FETCH_TRACKS_METADATAS_REQUESTED = - 'FETCH_TRACKS_METADATAS_REQUESTED' -export const FETCH_TRACKS_METADATAS_SUCCEEDED = - 'FETCH_TRACKS_METADATAS_SUCCEEDED' -export const FETCH_TRACKS_METADATAS_FAILED = 'FETCH_TRACKS_METADATAS_FAILED' - -export const FETCH_TRACK_AUDIO = 'FETCH_TRACK_AUDIO' -export const FETCH_TRACK_AUDIO_REQUESTED = 'FETCH_TRACK_AUDIO_REQUESTED' -export const FETCH_TRACK_AUDIO_SUCCEEDED = 'FETCH_TRACK_AUDIO_SUCCEEDED' -export const UPDATE_LINEUP_ORDER = 'UPDATE_LINEUP_ORDER' - -export const PLAY = 'PLAY' -export const PAUSE = 'PAUSE' -export const TOGGLE_PLAY = 'TOGGLE_PLAY' - -export const RESET = 'RESET' -export const RESET_SUCCEEDED = 'RESET_SUCCEEDED' - -export const SET_MAX_ENTRIES = 'SET_MAX_ENTRIES' - -export const SET_IN_VIEW = 'SET_IN_VIEW' -export const REFRESH_IN_VIEW = 'REFRESH_IN_VIEW' - -export const UPDATE_TRACK_METADATA = 'UPDATE_TRACK_METADATA' -export const REMOVE = 'REMOVE' -export const ADD = 'ADD' -export const SET_LOADING = 'SET_LOADING' - -export const SET_PAGE = 'SET_PAGE' - -export const addPrefix = (prefix: string, actionType: string) => { - return `${prefix}_${actionType}` -} - -export const stripPrefix = (prefix: string, actionType: string) => { - return actionType.replace(`${prefix}_`, '') -} - -/** - * A generic class of common Lineup actions for fetching, loading and - * simple playback. - * @example - * // playlist.js - * // Creates lineup actions for a playlist, e.g. - * // PLAYLIST_FETCH_TRACKS_METADATAS. - * class PlaylistActions extends LineupActions { - * constructor () { - * super("PLAYLIST") - * } - * } - * export const playlistActions = new PlaylistActions() - */ -export class LineupActions { - prefix: string - removeDeleted: boolean - - constructor(prefix: string, removeDeleted = false) { - this.prefix = prefix - this.removeDeleted = removeDeleted - } - - getPrefix() { - return this.prefix - } - - /** - * Fetches entity metadatas for the lineup. - * Side-effect: Fetches relevant creators and caches loaded tracks. - */ - fetchLineupMetadatas( - // the offset into the "get tracks" query - offset = 0, - // the limit for the "get tracks" query - limit = 10, - // a boolean indicating whether to overwrite cached entries the fetch may be refetching - overwrite = false, - // keyword args payload to send to the "get tracks" query - payload?: unknown, - other?: Record - ) { - return { - type: addPrefix(this.prefix, FETCH_LINEUP_METADATAS), - offset, - limit, - overwrite, - payload, - ...other - } - } - - fetchLineupMetadatasRequested( - offset = 0, - limit = 10, - overwrite = false, - payload: unknown, - handle?: string - ) { - return { - type: addPrefix(this.prefix, FETCH_LINEUP_METADATAS_REQUESTED), - offset, - limit, - overwrite, - payload, - handle - } - } - - fetchLineupMetadatasSucceeded( - entries: unknown, - offset: number, - limit: number, - deleted: number, - nullCount: number, - handle?: string, - hasMore?: boolean - ) { - return { - type: addPrefix(this.prefix, FETCH_LINEUP_METADATAS_SUCCEEDED), - entries, - offset, - limit, - deleted, - nullCount, - handle, - hasMore - } - } - - fetchLineupMetadatasFailed() { - return { - type: addPrefix(this.prefix, FETCH_LINEUP_METADATAS_FAILED) - } - } - - fetchTrackAudio(trackMetadata: TrackMetadata) { - return { - type: addPrefix(this.prefix, FETCH_TRACK_AUDIO), - trackMetadata - } - } - - fetchTrackAudioRequested(index: number, trackId: ID) { - return { - type: addPrefix(this.prefix, FETCH_TRACK_AUDIO_REQUESTED), - index, - trackId - } - } - - fetchTrackAudioSucceeded(index: number, trackId: ID) { - return { - type: addPrefix(this.prefix, FETCH_TRACK_AUDIO_SUCCEEDED), - index, - trackId - } - } - - play(uid?: UID, { isPreview = false }: { isPreview?: boolean } = {}) { - return { - type: addPrefix(this.prefix, PLAY), - uid, - isPreview - } - } - - pause() { - return { - type: addPrefix(this.prefix, PAUSE) - } - } - - togglePlay(uid: UID, id: ID, source: PlaybackSource) { - return { - type: addPrefix(this.prefix, TOGGLE_PLAY), - uid, - id, - source - } - } - - updateTrackMetadata(trackId: ID, metadata: TrackMetadata) { - return { - type: addPrefix(this.prefix, UPDATE_TRACK_METADATA), - trackId, - metadata - } - } - - updateLineupOrder(orderedIds: UID[], handle?: string) { - return { - type: addPrefix(this.prefix, UPDATE_LINEUP_ORDER), - orderedIds, - handle - } - } - - // Side-effect: Unsubscribes this lineup from cache entries it is subscribed to. - reset(source?: string) { - return { - type: addPrefix(this.prefix, RESET), - source - } - } - - resetSucceeded() { - return { - type: addPrefix(this.prefix, RESET_SUCCEEDED) - } - } - - add( - entry: LineupEntry, - id: ID, - handle?: string, - shouldPrepend?: boolean - ) { - return { - type: addPrefix(this.prefix, ADD), - entry, - id, - handle, - shouldPrepend - } - } - - remove(kind: string, uid: UID, handle?: string) { - return { - type: addPrefix(this.prefix, REMOVE), - kind, - uid, - handle - } - } - - setMaxEntries(maxEntries: number | null) { - return { - type: addPrefix(this.prefix, SET_MAX_ENTRIES), - maxEntries - } - } - - setInView(inView: boolean) { - return { - type: addPrefix(this.prefix, SET_IN_VIEW), - inView - } - } - - // If limit is not provided, we use whatever is in the state - refreshInView( - overwrite = false, - payload?: unknown, - limit: number | null = null, - other?: Record - ) { - return { - ...other, - type: addPrefix(this.prefix, REFRESH_IN_VIEW), - overwrite, - payload, - limit - } - } - - setLoading() { - return { - type: addPrefix(this.prefix, SET_LOADING) - } - } - - setPage = (page: number, handle?: string) => { - return { - type: addPrefix(this.prefix, SET_PAGE), - page, - handle - } - } -} diff --git a/packages/common/src/store/lineup/index.ts b/packages/common/src/store/lineup/index.ts deleted file mode 100644 index 9647096eafa..00000000000 --- a/packages/common/src/store/lineup/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * as lineupActions from './actions' -export * as lineupReducer from './reducer' -export * as lineupSelectors from './selectors' -export { LineupActions as LineupBaseActions } from './actions' -export { lineupRegistry } from './registry' diff --git a/packages/common/src/store/lineup/reducer.ts b/packages/common/src/store/lineup/reducer.ts deleted file mode 100644 index 308149659ae..00000000000 --- a/packages/common/src/store/lineup/reducer.ts +++ /dev/null @@ -1,305 +0,0 @@ -import { Reducer } from 'redux' - -import { Status } from '~/models/Status' -import { - FETCH_LINEUP_METADATAS_REQUESTED, - FETCH_LINEUP_METADATAS_SUCCEEDED, - FETCH_LINEUP_METADATAS_FAILED, - SET_LOADING, - ADD, - REMOVE, - SET_IN_VIEW, - UPDATE_LINEUP_ORDER, - SET_PAGE, - stripPrefix, - SET_MAX_ENTRIES -} from '~/store/lineup/actions' - -import { UID } from '../../models/Identifiers' -import { LineupState, LineupEntry, Order } from '../../models/Lineup' - -export const initialLineupState = { - prefix: '', - // Contains identifiers for cache entries as well as retained metadata. - // array - entries: [], - entryIds: null, - // Maps unique ids to their index in entries: - // entry.uid => current index in entries - order: {}, - page: 0, - isMetadataLoading: false, - total: 0, - deleted: 0, - nullCount: 0, - status: Status.IDLE, - hasMore: true, - inView: false, - // Boolean if the lineup should remove duplicate content in entries - dedupe: false, - // Boolean if the lineup fetch call pagination includes deleted tracks/collections - // e.g. This should be true if we request 10 tracks but only get 9 back because - // one is deleted - // Whether the lineup is limited to a certain length - maxEntries: null, - // We save the payload of the last fetch call to re-use if not provided - payload: undefined, - // We save the handle of the last fetch call to re-use if not provided - handle: undefined -} - -type SetMaxEntriesAction = { - type: typeof SET_MAX_ENTRIES - maxEntries: number | null -} - -type SetInViewAction = { - type: typeof SET_IN_VIEW - inView: boolean -} - -type FetchLineupMetadatasRequestedAction = { - type: typeof FETCH_LINEUP_METADATAS_REQUESTED - limit: number - offset: number - handle: string - payload: unknown -} - -type FetchLineupMetadatasSucceededAction = { - type: typeof FETCH_LINEUP_METADATAS_SUCCEEDED - entries: LineupEntry[] - deleted: number - nullCount: number - limit: number - offset: number - hasMore?: boolean -} - -type FetchLineupMetadatasFailedAction = { - type: typeof FETCH_LINEUP_METADATAS_FAILED -} - -type UpdateLineupOrderAction = { - type: typeof UPDATE_LINEUP_ORDER - orderedIds: UID[] -} - -type AddAction = { - type: typeof ADD - entry: LineupEntry - shouldPrepend?: boolean -} - -type RemoveAction = { - type: typeof REMOVE - uid: UID -} - -type SetLoadingAction = { - type: typeof SET_LOADING -} - -type SetPageAction = { - type: typeof SET_PAGE - page: number -} - -export type LineupActions = - | SetMaxEntriesAction - | SetInViewAction - | FetchLineupMetadatasRequestedAction - | FetchLineupMetadatasSucceededAction - | FetchLineupMetadatasFailedAction - | UpdateLineupOrderAction - | AddAction - | RemoveAction - | SetLoadingAction - | SetPageAction - -export const actionsMap = { - [SET_IN_VIEW](state: LineupState, action: SetInViewAction) { - return { - ...state, - inView: action.inView - } - }, - [SET_MAX_ENTRIES](state: LineupState, action: SetMaxEntriesAction) { - return { - ...state, - maxEntries: action.maxEntries - } - }, - [FETCH_LINEUP_METADATAS_REQUESTED]( - state: LineupState, - action: FetchLineupMetadatasRequestedAction - ) { - const newState = { ...state } - if (action.offset === 0) newState.entryIds = new Set([]) - newState.total = action.limit + action.offset - newState.status = Status.LOADING - newState.isMetadataLoading = true - if (action.payload) { - newState.payload = action.payload - } - if (action.handle) { - newState.handle = action.handle - } - return newState - }, - [FETCH_LINEUP_METADATAS_SUCCEEDED]( - state: LineupState, - action: FetchLineupMetadatasSucceededAction - ) { - const newState = { ...state } - newState.isMetadataLoading = false - newState.status = Status.SUCCESS - newState.hasMore = - action.hasMore ?? action.entries.length + action.deleted >= action.limit - - // Hack alert: - // For lineups with max entries (such as trending playlists) and deleted content, - // manually set hasMore. - // - // Total entries is existing entries + deleted from both lineup & action - const totalEntries = - newState.entries.length + - action.entries.length + - newState.deleted + - action.deleted - if (newState.maxEntries !== null && totalEntries >= newState.maxEntries) { - newState.hasMore = false - } - - if (action.offset === 0) { - newState.entries = action.entries - } else { - newState.entries = newState.entries.concat(action.entries) - } - newState.deleted += Math.max(action.deleted || 0, 0) - newState.nullCount += Math.max(action.nullCount || 0, 0) - newState.entries.forEach((entry, i) => { - if (!entry.uid) entry.uid = `${entry.id.toString()}-${i.toString()}` - }) - newState.order = newState.entries.reduce((m, entry, i) => { - m[entry.uid] = i - return m - }, {}) - return newState - }, - [FETCH_LINEUP_METADATAS_FAILED]( - state: LineupState, - _action: FetchLineupMetadatasFailedAction - ) { - const newState = { ...state } - newState.status = Status.ERROR - newState.isMetadataLoading = false - newState.entries = [] - return newState - }, - [UPDATE_LINEUP_ORDER]( - state: LineupState, - action: UpdateLineupOrderAction - ) { - const reorderedEntries = action.orderedIds.map((uid) => ({ - ...state.entries[state.order[uid]] - })) - const newOrder = action.orderedIds.reduce((m, uid, i) => { - m[uid] = i - return m - }, {}) - return { - ...state, - entries: reorderedEntries, - order: newOrder - } - }, - [ADD](state: LineupState, action: AddAction) { - const { entry, shouldPrepend } = action - const newState = { ...state } - newState.order = { ...state.order } - - if (shouldPrepend) { - newState.entries = [entry, ...newState.entries] - newState.entries.forEach((newEntry, index) => { - newState.order[newEntry.uid] = index - }) - } else { - newState.entries = newState.entries.concat({ - ...entry - }) - newState.order[entry.uid] = newState.entries.length - } - return newState - }, - [REMOVE](state: LineupState, action: RemoveAction) { - const newState = { ...state } - newState.entries = state.entries.filter((e) => e.uid !== action.uid) - - const { [action.uid]: entryOrder, ...newOrder } = state.order - Object.keys(newOrder).forEach((uid) => { - newOrder[uid] = - newOrder[uid] > entryOrder ? newOrder[uid] - 1 : newOrder[uid] - }) - newState.order = newOrder - - return newState - }, - [SET_LOADING](state: LineupState, _action: SetLoadingAction) { - return { - ...state, - status: Status.LOADING - } - }, - [SET_PAGE](state: LineupState, action: SetPageAction) { - return { - ...state, - page: action.page - } - } -} - -/** - * Decorates a reducer with a higher order reducer, making it able to reduce on - * lineup actions. - * Decorated reducers should implement lineup actions with the LineupActions class. - * @param {String} prefix the lineup reducer's prefix, e.g. "FEED" - * @param {Function} reducer the reducer function to decorate - */ -export const asLineup = - < - EntryT, - LineupStateType extends LineupState, - LineupActionType extends { type: string } - >( - prefix: string, - reducer: ( - state: LineupStateType | undefined, - action: LineupActionType - ) => LineupStateType - ): Reducer> => - ( - state: LineupStateType | undefined, - action: LineupActionType | LineupActions - ): LineupStateType => { - if (!action.type.startsWith(prefix)) { - return reducer(state, action as LineupActionType) - } - const baseActionType = stripPrefix( - prefix, - action.type - ) as LineupActions['type'] - const matchingReduceFunction = actionsMap[baseActionType] - - if (matchingReduceFunction) { - const newState = matchingReduceFunction( - // @ts-ignore action is never for some reason, ts 4.1 may help here - state, - action as LineupActions - ) - // @ts-ignore action is never for some reason, ts 4.1 may help here - return reducer(newState, action as LineupActionType) - } else { - return reducer(state, action as LineupActionType) - } - } diff --git a/packages/common/src/store/lineup/registry.ts b/packages/common/src/store/lineup/registry.ts deleted file mode 100644 index 3a32db43c01..00000000000 --- a/packages/common/src/store/lineup/registry.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { LineupState } from '~/models/Lineup' - -import { CommonState } from '..' - -type LineupEntry = { - actions: any - selector: (state: CommonState, handle?: string) => LineupState -} - -/** - * Legacy lineup registry. All lineups have been migrated to tanquery + - * playback slice, so this registry is intentionally empty. Kept as an - * export only so that any lingering imports compile; remove once no - * importers remain. - */ -export const lineupRegistry: Record = {} diff --git a/packages/common/src/store/lineup/selectors.ts b/packages/common/src/store/lineup/selectors.ts deleted file mode 100644 index 03cc5942e7e..00000000000 --- a/packages/common/src/store/lineup/selectors.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { createSelector } from 'reselect' - -import { Nullable } from '~/utils/typeUtils' - -import { LineupState } from '../../models/Lineup' - -// Some lineups can have additional properties (T) -// e.g. collections have dateAdded in entries -export type LineupSelector = (state: State) => LineupState - -export const getLineupHasTracks = ( - selector: LineupSelector, - state: State -) => { - const lineup = selector(state) - return lineup && lineup.entries.length > 0 -} - -export const getLineupEntries = ( - selector: (state: State) => Nullable>, - state: State -) => { - return selector(state)?.entries -} - -export const makeGetLineupMetadatas = ( - lineupSelector: LineupSelector -) => { - return createSelector([lineupSelector], (lineup) => { - return lineup - }) -} - -export const makeGetLineupOrder = ( - lineupSelector: LineupSelector -) => - createSelector([lineupSelector], (lineup) => { - return lineup.order - }) diff --git a/packages/mobile/src/components/lineup-tile/types.ts b/packages/mobile/src/components/lineup-tile/types.ts index 8a84b074841..2727347cf02 100644 --- a/packages/mobile/src/components/lineup-tile/types.ts +++ b/packages/mobile/src/components/lineup-tile/types.ts @@ -1,10 +1,7 @@ import type { ReactNode } from 'react' import type { PlaybackSource, Collection, ID, UID } from '@audius/common/models' -import type { - EnhancedCollectionTrack, - LineupBaseActions -} from '@audius/common/store' +import type { EnhancedCollectionTrack } from '@audius/common/store' import type { StyleProp, ViewStyle } from 'react-native' import type { ImageProps } from '@audius/harmony-native' @@ -32,7 +29,6 @@ export type TrackTileProps = { variant?: LineupItemVariant index: number isTrending?: boolean - actions?: LineupBaseActions style?: StyleProp source?: LineupTileSource showArtistPick?: boolean @@ -45,7 +41,6 @@ export type CollectionTileProps = { variant?: LineupItemVariant index: number isTrending?: boolean - actions?: LineupBaseActions style?: StyleProp source?: LineupTileSource collection?: Collection diff --git a/packages/mobile/src/components/lineup/types.ts b/packages/mobile/src/components/lineup/types.ts index ab4073b18ac..457d1b1b78e 100644 --- a/packages/mobile/src/components/lineup/types.ts +++ b/packages/mobile/src/components/lineup/types.ts @@ -1,7 +1,7 @@ import type { ReactElement } from 'react' import type { Kind, ID, UID, Lineup as LineupData } from '@audius/common/models' -import type { LineupBaseActions, CommonState } from '@audius/common/store' +import type { CommonState } from '@audius/common/store' import type { Maybe } from '@audius/common/utils' import type { SectionListProps, ViewStyle } from 'react-native' @@ -27,9 +27,6 @@ export type LoadingLineupItem = { } export type LineupProps = { - /** Object containing lineup actions such as setPage */ - actions: LineupBaseActions - /** The maximum number of total tracks to fetch */ count?: number @@ -200,8 +197,6 @@ export type LineupItemTileProps = Pick< index: number togglePlay: ({ uid, id, source }: TogglePlayConfig) => void onPress?: (id: ID) => void - /** Object containing lineup actions such as play, setPage, togglePlay */ - actions: LineupBaseActions } export type LineupTileViewProps = Omit & { diff --git a/packages/mobile/src/screens/explore-screen/components/CollectionLineupCarousel.tsx b/packages/mobile/src/screens/explore-screen/components/CollectionLineupCarousel.tsx deleted file mode 100644 index dab8cb5f470..00000000000 --- a/packages/mobile/src/screens/explore-screen/components/CollectionLineupCarousel.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import React, { useCallback } from 'react' - -import type { Lineup as LineupData } from '@audius/common/models' -import { Status } from '@audius/common/models' -import type { LineupBaseActions } from '@audius/common/store' -import { ScrollView } from 'react-native' -import { useDispatch } from 'react-redux' - -import { Flex } from '@audius/harmony-native' -import type { TogglePlayConfig, LineupItem } from 'app/components/lineup/types' -import { - CollectionTile, - CollectionTileSkeleton -} from 'app/components/lineup-tile' - -interface CollectionTileCarouselProps { - lineup: LineupData - actions: LineupBaseActions - isTrending?: boolean -} - -export const CollectionLineupCarousel = ({ - lineup, - isTrending, - actions -}: CollectionTileCarouselProps) => { - const dispatch = useDispatch() - const togglePlay = useCallback( - ({ uid, id, source }: TogglePlayConfig) => { - dispatch(actions.togglePlay(uid, id, source)) - }, - [actions, dispatch] - ) - - if (lineup.status !== Status.SUCCESS) { - return ( - - - {[0, 1].map((columnIndex) => ( - - - - ))} - - - ) - } - - return !lineup.entries || lineup.entries.length === 0 ? null : ( - - - {lineup.entries.map((item, index) => ( - - - - ))} - - - ) -}