diff --git a/packages/common/src/api/library.ts b/packages/common/src/api/library.ts index d6fc097add..99000a9d0a 100644 --- a/packages/common/src/api/library.ts +++ b/packages/common/src/api/library.ts @@ -37,7 +37,7 @@ const fetchLibraryCollections = async ({ offset, limit, category, - query, + query = '', sortMethod = 'added_date', sortDirection = 'desc' } = args diff --git a/packages/common/src/models/Analytics.ts b/packages/common/src/models/Analytics.ts index 66cfa99e4b..d40e88b8aa 100644 --- a/packages/common/src/models/Analytics.ts +++ b/packages/common/src/models/Analytics.ts @@ -586,7 +586,7 @@ export enum RepostSource { TRACK_PAGE = 'page', COLLECTION_PAGE = 'collection page', HISTORY_PAGE = 'history page', - LIBRARY_PAGE = 'library page', + FAVORITES_PAGE = 'favorites page', OVERFLOW = 'overflow', TRACK_LIST = 'track list' } @@ -597,7 +597,7 @@ export enum FavoriteSource { TRACK_PAGE = 'page', COLLECTION_PAGE = 'collection page', HISTORY_PAGE = 'history page', - LIBRARY_PAGE = 'library page', + FAVORITES_PAGE = 'favorites page', OVERFLOW = 'overflow', TRACK_LIST = 'track list', SIGN_UP = 'sign up', @@ -685,7 +685,7 @@ export enum CreatePlaylistSource { NAV = 'nav', CREATE_PAGE = 'create page', FROM_TRACK = 'from track', - LIBRARY_PAGE = 'library page', + FAVORITES_PAGE = 'favorites page', PROFILE_PAGE = 'profile page' } @@ -1025,7 +1025,7 @@ export enum PlaybackSource { PLAYLIST_TRACK = 'playlist page track list', PLAYLIST_TILE_TRACK = 'playlist track tile', HISTORY_PAGE = 'history page', - LIBRARY_PAGE = 'library page', + FAVORITES_PAGE = 'favorites page', PASSIVE = 'passive', EMBED_PLAYER = 'embed player', CHAT_TRACK = 'chat_track', diff --git a/packages/common/src/store/cache/collections/selectors.ts b/packages/common/src/store/cache/collections/selectors.ts index df835914e9..217e5fe9a3 100644 --- a/packages/common/src/store/cache/collections/selectors.ts +++ b/packages/common/src/store/cache/collections/selectors.ts @@ -195,7 +195,7 @@ export const getTracksFromCollection = ( .filter(Boolean) as EnhancedCollectionTrack[] } -export type EnhancedCollection = Collection & { user: User } +type EnhancedCollection = Collection & { user: User } export const getCollectionWithUser = ( state: CommonState, props: { id?: ID } diff --git a/packages/common/src/store/cache/collections/utils/index.ts b/packages/common/src/store/cache/collections/utils/index.ts index 36c65f4890..cf6599bab6 100644 --- a/packages/common/src/store/cache/collections/utils/index.ts +++ b/packages/common/src/store/cache/collections/utils/index.ts @@ -1,4 +1,3 @@ -// TODO: Finish common migration - migrate utils from packages/web/common/store/cache/collections/utils to here: -// https://linear.app/audius/issue/C-1280/migrate-remaining-webcommon-to-common +// TODO: Migrate utils from packages/web/common/store/cache/collections/utils to here export * from './reformatCollection' diff --git a/packages/common/src/store/pages/index.ts b/packages/common/src/store/pages/index.ts index 473e9870c2..f26f5360fa 100644 --- a/packages/common/src/store/pages/index.ts +++ b/packages/common/src/store/pages/index.ts @@ -61,7 +61,6 @@ export { tracksActions as savedPageTracksLineupActions } from './saved-page/line export * as savedPageActions from './saved-page/actions' export * as savedPageSelectors from './saved-page/selectors' export * from './saved-page/types' -export * from './saved-page/utils' export { default as savedPageReducer } from './saved-page/reducer' export { diff --git a/packages/common/src/store/pages/saved-page/actions.ts b/packages/common/src/store/pages/saved-page/actions.ts index 57fc4e738a..13c303faf8 100644 --- a/packages/common/src/store/pages/saved-page/actions.ts +++ b/packages/common/src/store/pages/saved-page/actions.ts @@ -1,7 +1,5 @@ -import { Favorite } from 'models/Favorite' - -import { LibraryCategory, LibraryCategoryType, SavedPageTabs } from './types' - +// @ts-nocheck +// TODO(nkang) - convert to TS export const FETCH_SAVES = 'SAVED/FETCH_SAVES' export const FETCH_SAVES_REQUESTED = 'SAVED/FETCH_SAVES_REQUESTED' export const FETCH_SAVES_SUCCEEDED = 'SAVED/FETCH_SAVES_SUCCEEDED' @@ -15,21 +13,12 @@ export const FETCH_MORE_SAVES_FAILED = 'SAVED/FETCH_MORE_SAVES_FAILED' // Usually when filtering export const END_FETCHING = 'SAVED/END_FETCHING' -export const ADD_LOCAL_TRACK = 'SAVED/ADD_LOCAL_TRACK' -export const REMOVE_LOCAL_TRACK = 'SAVED/REMOVE_LOCAL_TRACK' -export const ADD_LOCAL_COLLECTION = 'SAVED/ADD_LOCAL_COLLECTION' -export const REMOVE_LOCAL_COLLECTION = 'SAVED/REMOVE_LOCAL_COLLECTION' - -export const SET_SELECTED_CATEGORY = 'SAVED/SET_SELECTED_CATEGORY' -export const INIT_COLLECTIONS_CATEGORY_FROM_LOCAL_STORAGE = - 'SAVED/INIT_COLLECTIONS_CATEGORY_FROM_LOCAL_STORAGE' -export const INIT_TRACKS_CATEGORY_FROM_LOCAL_STORAGE = - 'SAVED/INIT_TRACKS_CATEGORY_FROM_LOCAL_STORAGE' +export const ADD_LOCAL_SAVE = 'SAVED/ADD_LOCAL_SAVE' +export const REMOVE_LOCAL_SAVE = 'SAVED/REMOVE_LOCAL_SAVE' export const fetchSaves = ( // the filter query for the "get tracks" query query = '', - category: LibraryCategoryType = LibraryCategory.Favorite, // the sort method for the "get tracks" query sortMethod = '', // the sort direction for the "get tracks" query @@ -40,7 +29,6 @@ export const fetchSaves = ( limit = 50 ) => ({ type: FETCH_SAVES, - category, offset, limit, query, @@ -51,7 +39,6 @@ export const fetchSaves = ( export const fetchMoreSaves = ( // the filter query for the "get tracks" query query = '', - category: LibraryCategoryType = LibraryCategory.Favorite, // the sort method for the "get tracks" query sortMethod = '', // the sort direction for the "get tracks" query @@ -62,7 +49,6 @@ export const fetchMoreSaves = ( limit = 50 ) => ({ type: FETCH_MORE_SAVES, - category, offset, limit, query, @@ -74,7 +60,7 @@ export const fetchSavesRequested = () => ({ type: FETCH_SAVES_REQUESTED }) -export const fetchSavesSucceeded = (saves: Favorite[]) => ({ +export const fetchSavesSucceeded = (saves) => ({ type: FETCH_SAVES_SUCCEEDED, saves }) @@ -83,7 +69,7 @@ export const fetchSavesFailed = () => ({ type: FETCH_SAVES_FAILED }) -export const fetchMoreSavesSucceeded = (saves: Favorite[], offset: number) => ({ +export const fetchMoreSavesSucceeded = (saves, offset) => ({ type: FETCH_MORE_SAVES_SUCCEEDED, saves, offset @@ -93,90 +79,18 @@ export const fetchMoreSavesFailed = () => ({ type: FETCH_MORE_SAVES_FAILED }) -export const endFetching = (endIndex: number) => ({ +export const endFetching = (endIndex) => ({ type: END_FETCHING, endIndex }) -export const addLocalTrack = ({ +export const addLocalSave = (trackId, uid) => ({ + type: ADD_LOCAL_SAVE, trackId, - uid, - category -}: { - trackId: number - uid: string - category: LibraryCategoryType -}) => ({ - type: ADD_LOCAL_TRACK, - trackId, - uid, - category -}) - -export const removeLocalTrack = ({ - trackId, - category -}: { - trackId: number - category: LibraryCategoryType -}) => ({ - type: REMOVE_LOCAL_TRACK, - trackId, - category -}) - -export const addLocalCollection = ({ - collectionId, - isAlbum, - category -}: { - collectionId: number - isAlbum: boolean - category: LibraryCategoryType -}) => ({ - type: ADD_LOCAL_COLLECTION, - collectionId, - isAlbum, - category -}) - -export const removeLocalCollection = ({ - collectionId, - isAlbum, - category -}: { - collectionId: number - isAlbum: boolean - category: LibraryCategoryType -}) => ({ - type: REMOVE_LOCAL_COLLECTION, - collectionId, - isAlbum, - category -}) - -export const initializeTracksCategoryFromLocalStorage = ( - category: LibraryCategoryType -) => ({ - type: INIT_TRACKS_CATEGORY_FROM_LOCAL_STORAGE, - category -}) - -export const initializeCollectionsCategoryFromLocalStorage = ( - category: LibraryCategoryType -) => ({ - type: INIT_COLLECTIONS_CATEGORY_FROM_LOCAL_STORAGE, - category + uid }) -export const setSelectedCategory = ({ - category, - currentTab -}: { - category: LibraryCategoryType - currentTab: SavedPageTabs -}) => ({ - type: SET_SELECTED_CATEGORY, - category, - currentTab +export const removeLocalSave = (trackId) => ({ + type: REMOVE_LOCAL_SAVE, + trackId }) diff --git a/packages/common/src/store/pages/saved-page/reducer.ts b/packages/common/src/store/pages/saved-page/reducer.ts index 9b55f42c47..a6f430f588 100644 --- a/packages/common/src/store/pages/saved-page/reducer.ts +++ b/packages/common/src/store/pages/saved-page/reducer.ts @@ -1,102 +1,42 @@ -import { ID } from 'models/Identifiers' +// @ts-nocheck +// TODO(nkang) - convert to TS import { asLineup } from 'store/lineup/reducer' import { - ADD_LOCAL_COLLECTION, - ADD_LOCAL_TRACK, - END_FETCHING, - FETCH_MORE_SAVES, - FETCH_MORE_SAVES_FAILED, - FETCH_MORE_SAVES_SUCCEEDED, FETCH_SAVES, - FETCH_SAVES_FAILED, FETCH_SAVES_REQUESTED, FETCH_SAVES_SUCCEEDED, - INIT_COLLECTIONS_CATEGORY_FROM_LOCAL_STORAGE, - INIT_TRACKS_CATEGORY_FROM_LOCAL_STORAGE, - REMOVE_LOCAL_COLLECTION, - REMOVE_LOCAL_TRACK, - SET_SELECTED_CATEGORY + FETCH_SAVES_FAILED, + FETCH_MORE_SAVES, + FETCH_MORE_SAVES_SUCCEEDED, + FETCH_MORE_SAVES_FAILED, + ADD_LOCAL_SAVE, + REMOVE_LOCAL_SAVE, + END_FETCHING } from 'store/pages/saved-page/actions' import tracksReducer, { initialState as initialLineupState } from 'store/pages/saved-page/lineups/tracks/reducer' import { signOut } from 'store/sign-out/slice' -import { ActionsMap } from 'utils/reducer' import { PREFIX as tracksPrefix } from './lineups/tracks/actions' -import { LibraryCategory, LibraryCategoryType, SavedPageState } from './types' -import { calculateNewLibraryCategories } from './utils' const initialState = { - trackSaves: [], + // id => uid + localSaves: {}, + saves: [], initialFetch: false, hasReachedEnd: false, fetchingMore: false, - tracks: initialLineupState, - tracksCategory: LibraryCategory.Favorite, - collectionsCategory: LibraryCategory.Favorite, - local: { - track: { - favorites: { - added: {}, - removed: {} - }, - reposts: { - added: {}, - removed: {} - }, - purchased: { - added: {} - } - }, - album: { - favorites: { - added: [], - removed: [] - }, - reposts: { - added: [], - removed: [] - }, - purchased: { - added: [] - } - }, - playlist: { - favorites: { - added: [], - removed: [] - }, - reposts: { - added: [], - removed: [] - } - } - } -} as SavedPageState - -const getCategoryLocalStateKey = ( - category: Omit -) => { - switch (category) { - case LibraryCategory.Favorite: - return 'favorites' - case LibraryCategory.Purchase: - return 'purchased' - case LibraryCategory.Repost: - return 'reposts' - default: - return 'favorites' - } + tracks: initialLineupState } -const actionsMap: ActionsMap = { - [FETCH_SAVES](state) { +const actionsMap = { + [FETCH_SAVES](state, action) { return { ...state } }, - [FETCH_SAVES_REQUESTED](state) { + [FETCH_SAVES_REQUESTED](state, action) { return { ...state, initialFetch: true, @@ -106,122 +46,70 @@ const actionsMap: ActionsMap = { [FETCH_SAVES_SUCCEEDED](state, action) { return { ...state, - trackSaves: action.saves, + saves: action.saves, initialFetch: false } }, - [FETCH_MORE_SAVES](state) { + [FETCH_MORE_SAVES](state, action) { return { ...state, fetchingMore: true } }, - [FETCH_SAVES_FAILED](state) { + [FETCH_SAVES_FAILED](state, action) { return { ...state, fetchingMore: false, - trackSaves: [] + saves: [] } }, [FETCH_MORE_SAVES_SUCCEEDED](state, action) { - const savesCopy = state.trackSaves.slice() + const savesCopy = state.saves.slice() savesCopy.splice(action.offset, action.saves.length, ...action.saves) return { ...state, fetchingMore: false, - trackSaves: savesCopy + saves: savesCopy } }, - [FETCH_MORE_SAVES_FAILED](state) { + [FETCH_MORE_SAVES_FAILED](state, action) { return { ...state } }, [END_FETCHING](state, action) { - const savesCopy = state.trackSaves.slice(0, action.endIndex) + const savesCopy = state.saves.slice(0, action.endIndex) return { ...state, - trackSaves: savesCopy, + saves: savesCopy, hasReachedEnd: true } }, - [ADD_LOCAL_TRACK](state, action) { - const categoryKey = getCategoryLocalStateKey(action.category) - const newState = { ...state } - newState.local.track[categoryKey].added = { - ...newState.local.track[categoryKey].added, - [action.trackId]: action.uid + [ADD_LOCAL_SAVE](state, action) { + return { + ...state, + localSaves: { + ...state.localSaves, + [action.trackId]: action.uid + } } - return newState }, - [REMOVE_LOCAL_TRACK](state, action) { - const categoryKey = getCategoryLocalStateKey(action.category) + [REMOVE_LOCAL_SAVE](state, action) { const newState = { ...state } - delete newState.local.track[categoryKey].added[action.trackId] - - newState.trackSaves = newState.trackSaves.filter( + delete newState.localSaves[action.trackId] + newState.saves = newState.saves.filter( ({ save_item_id: id }) => id !== action.trackId ) return newState }, - [ADD_LOCAL_COLLECTION](state, action) { - const kindKey = action.isAlbum ? 'album' : 'playlist' - const categoryKey = getCategoryLocalStateKey(action.category) - const newState = { ...state } - newState.local[kindKey][categoryKey].added = [ - action.collectionId, - ...newState.local[kindKey][categoryKey].added - ] - newState.local[kindKey][categoryKey].removed = newState.local[kindKey][ - categoryKey - ].removed.filter((id: ID) => id !== action.collectionId) - - return newState - }, - [REMOVE_LOCAL_COLLECTION](state, action) { - const kindKey = action.isAlbum ? 'album' : 'playlist' - const categoryKey = getCategoryLocalStateKey(action.category) - const newState = { ...state } - newState.local[kindKey][categoryKey].removed = [ - action.collectionId, - ...newState.local[kindKey][categoryKey].removed - ] - newState.local[kindKey][categoryKey].added = newState.local[kindKey][ - categoryKey - ].added.filter((id: ID) => id !== action.collectionId) - - return newState - }, - [SET_SELECTED_CATEGORY](state, action) { - return { - ...state, - ...calculateNewLibraryCategories({ - currentTab: action.currentTab, - chosenCategory: action.category, - prevTracksCategory: state.tracksCategory - }) - } - }, - [INIT_TRACKS_CATEGORY_FROM_LOCAL_STORAGE](state, action) { - return { - ...state, - tracksCategory: action.category - } - }, - [INIT_COLLECTIONS_CATEGORY_FROM_LOCAL_STORAGE](state, action) { - return { - ...state, - collectionsCategory: action.category - } - }, - [signOut.type]() { + [signOut.type](state) { return initialState } } const tracksLineupReducer = asLineup(tracksPrefix, tracksReducer) -const reducer = (state = initialState, action: any) => { - const tracks = tracksLineupReducer(state.tracks as any, action) +const reducer = (state = initialState, action) => { + const tracks = tracksLineupReducer(state.tracks, action) if (tracks !== state.tracks) return { ...state, tracks } const matchingReduceFunction = actionsMap[action.type] diff --git a/packages/common/src/store/pages/saved-page/selectors.ts b/packages/common/src/store/pages/saved-page/selectors.ts index fed17b8c01..98358fbb2d 100644 --- a/packages/common/src/store/pages/saved-page/selectors.ts +++ b/packages/common/src/store/pages/saved-page/selectors.ts @@ -1,166 +1,13 @@ -import { uniq } from 'lodash' - import { CommonState } from 'store/commonStore' import { ID } from '../../../models/Identifiers' -import { LibraryCategory, SavedPageTabs } from './types' - export const getSaved = (state: CommonState) => state.pages.savedPage -export const getTrackSaves = (state: CommonState) => - state.pages.savedPage.trackSaves - -export const getCollectionsCategory = (state: CommonState) => { - return state.pages.savedPage.collectionsCategory -} - -export const getTracksCategory = (state: CommonState) => { - return state.pages.savedPage.tracksCategory -} - -export const getCategory = ( - state: CommonState, - props: { currentTab: SavedPageTabs } -) => { - if (props.currentTab === SavedPageTabs.TRACKS) { - return getTracksCategory(state) - } else { - return getCollectionsCategory(state) - } -} - -export const getLocalTrackFavorites = (state: CommonState) => - state.pages.savedPage.local.track.favorites.added -export const getLocalTrackFavorite = (state: CommonState, props: { id: ID }) => - state.pages.savedPage.local.track.favorites.added[props.id] -export const getLocalTrackReposts = (state: CommonState) => - state.pages.savedPage.local.track.reposts.added -export const getLocalTrackRepost = (state: CommonState, props: { id: ID }) => - state.pages.savedPage.local.track.reposts.added[props.id] -export const getLocalTrackPurchases = (state: CommonState) => - state.pages.savedPage.local.track.purchased.added -export const getLocalTrackPurchase = (state: CommonState, props: { id: ID }) => - state.pages.savedPage.local.track.purchased.added[props.id] - -export const getLocalAlbumFavorites = (state: CommonState) => - state.pages.savedPage.local.album.favorites.added -export const getLocalAlbumReposts = (state: CommonState) => - state.pages.savedPage.local.album.reposts.added -export const getLocalAlbumPurchases = (state: CommonState) => - state.pages.savedPage.local.album.purchased.added -export const getLocalRemovedAlbumFavorites = (state: CommonState) => - state.pages.savedPage.local.album.favorites.removed -export const getLocalRemovedAlbumReposts = (state: CommonState) => - state.pages.savedPage.local.album.reposts.removed - -export const getLocalPlaylistFavorites = (state: CommonState) => - state.pages.savedPage.local.playlist.favorites.added -export const getLocalPlaylistReposts = (state: CommonState) => - state.pages.savedPage.local.playlist.reposts.added -export const getLocalRemovedPlaylistFavorites = (state: CommonState) => - state.pages.savedPage.local.playlist.favorites.removed -export const getLocalRemovedPlaylistReposts = (state: CommonState) => - state.pages.savedPage.local.playlist.favorites.removed - -/** Get the tracks in currently selected category that have been added to the library in current session */ -export const getSelectedCategoryLocalTrackAdds = (state: CommonState) => { - const selectedCategory = getCategory(state, { - currentTab: SavedPageTabs.TRACKS - }) - const localFavorites = getLocalTrackFavorites(state) - const localPurchases = getLocalTrackPurchases(state) - const localReposts = getLocalTrackReposts(state) - let localLibraryAdditions - if (selectedCategory === LibraryCategory.Favorite) { - localLibraryAdditions = localFavorites - } else if (selectedCategory === LibraryCategory.Purchase) { - localLibraryAdditions = localPurchases - } else if (selectedCategory === LibraryCategory.Repost) { - localLibraryAdditions = localReposts - } else { - // Category = ALL - localLibraryAdditions = { - ...localReposts, - ...localFavorites, - ...localPurchases - } - } - - return localLibraryAdditions -} - -const getSelectedCategoryLocalCollectionUpdates = ( - state: CommonState, - props: { collectionType: 'album' | 'playlist'; updateType: 'add' | 'remove' } -) => { - const { collectionType, updateType } = props - const currentTab = - collectionType === 'album' ? SavedPageTabs.ALBUMS : SavedPageTabs.PLAYLISTS - const selectedCategory = getCategory(state, { currentTab }) - let localFavorites: ID[], localPurchases: ID[], localReposts: ID[] - if (updateType === 'add') { - localFavorites = - collectionType === 'album' - ? getLocalAlbumFavorites(state) - : getLocalPlaylistFavorites(state) - localPurchases = - collectionType === 'album' ? getLocalAlbumPurchases(state) : [] // Can't buy playlists - localReposts = - collectionType === 'album' - ? getLocalAlbumReposts(state) - : getLocalPlaylistReposts(state) - } else { - localFavorites = - collectionType === 'album' - ? getLocalRemovedAlbumFavorites(state) - : getLocalRemovedPlaylistFavorites(state) - localPurchases = [] // Can't remove purchases - localReposts = - collectionType === 'album' - ? getLocalRemovedAlbumReposts(state) - : getLocalRemovedPlaylistReposts(state) - } - - switch (selectedCategory) { - case LibraryCategory.Favorite: - return localFavorites - case LibraryCategory.Purchase: - return localPurchases - case LibraryCategory.Repost: - return localReposts - default: - // Category = ALL - return uniq([...localReposts, ...localFavorites, ...localPurchases]) - } -} - -export const getSelectedCategoryLocalAlbumAdds = (state: CommonState) => { - return getSelectedCategoryLocalCollectionUpdates(state, { - collectionType: 'album', - updateType: 'add' - }) -} -export const getSelectedCategoryLocalAlbumRemovals = (state: CommonState) => { - return getSelectedCategoryLocalCollectionUpdates(state, { - collectionType: 'album', - updateType: 'remove' - }) -} -export const getSelectedCategoryLocalPlaylistRemovals = ( - state: CommonState -) => { - return getSelectedCategoryLocalCollectionUpdates(state, { - collectionType: 'playlist', - updateType: 'remove' - }) -} -export const getSelectedCategoryLocalPlaylistAdds = (state: CommonState) => { - return getSelectedCategoryLocalCollectionUpdates(state, { - collectionType: 'playlist', - updateType: 'add' - }) -} - +export const getSaves = (state: CommonState) => state.pages.savedPage.saves +export const getLocalSaves = (state: CommonState) => + state.pages.savedPage.localSaves +export const getLocalSave = (state: CommonState, props: { id: ID }) => + state.pages.savedPage.localSaves[props.id] export const getInitialFetchStatus = (state: CommonState) => state.pages.savedPage.initialFetch export const getIsFetchingMore = (state: CommonState) => diff --git a/packages/common/src/store/pages/saved-page/types.ts b/packages/common/src/store/pages/saved-page/types.ts index de22d7d3e0..8d4ceae3dc 100644 --- a/packages/common/src/store/pages/saved-page/types.ts +++ b/packages/common/src/store/pages/saved-page/types.ts @@ -1,8 +1,5 @@ -import { full } from '@audius/sdk' import { Moment } from 'moment' -import { ValueOf } from 'utils/typeUtils' - import { UID, ID, @@ -12,63 +9,13 @@ import { LineupTrack } from '../../../models' -export const LIBRARY_TRACKS_CATEGORY_LS_KEY = 'libraryTracksCategory' - -export const LIBRARY_COLLECTIONS_CATEGORY_LS_KEY = 'libraryCollectionsCategory' - -export const LibraryCategory = full.GetUserLibraryTracksTypeEnum -export type LibraryCategoryType = ValueOf - -export function isLibraryCategory(value: string): value is LibraryCategoryType { - return Object.values(LibraryCategory).includes(value as LibraryCategoryType) -} export interface SavedPageState { - local: { - track: { - favorites: { - added: { [id: number]: UID } - removed: { [id: number]: UID } - } - reposts: { - added: { [id: number]: UID } - removed: { [id: number]: UID } - } - purchased: { - added: { [id: number]: UID } - } - } - album: { - favorites: { - added: ID[] - removed: ID[] - } - reposts: { - added: ID[] - removed: ID[] - } - purchased: { - added: ID[] - } - } - playlist: { - favorites: { - added: ID[] - removed: ID[] - } - reposts: { - added: ID[] - removed: ID[] - } - } - } + localSaves: { [id: number]: UID } tracks: LineupState - trackSaves: Favorite[] + saves: Favorite[] hasReachedEnd: boolean initialFetch: boolean fetchingMore: boolean - - tracksCategory: LibraryCategoryType - collectionsCategory: LibraryCategoryType } export enum SavedPageTabs { diff --git a/packages/common/src/store/pages/saved-page/utils.ts b/packages/common/src/store/pages/saved-page/utils.ts deleted file mode 100644 index 6be4938463..0000000000 --- a/packages/common/src/store/pages/saved-page/utils.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { LibraryCategory, LibraryCategoryType, SavedPageTabs } from './types' - -export const calculateNewLibraryCategories = ({ - currentTab, - chosenCategory, - prevTracksCategory -}: { - currentTab: SavedPageTabs - chosenCategory: LibraryCategoryType - prevTracksCategory: unknown -}) => { - if ( - currentTab === SavedPageTabs.TRACKS && - chosenCategory === LibraryCategory.Purchase - ) { - // If the category is changed to "Purchased" on the tracks tab, change the collections tabs category to "All" because collections tabs don't have "Purchased". - return { - tracksCategory: chosenCategory, - collectionsCategory: LibraryCategory.All - } - } - if ( - (currentTab === SavedPageTabs.ALBUMS || - currentTab === SavedPageTabs.PLAYLISTS) && - prevTracksCategory === LibraryCategory.Purchase - ) { - // If tracks tab is on "Purchased", we want it to stay on "Purchased" until the user goes back to it. - return { - tracksCategory: prevTracksCategory, - collectionsCategory: chosenCategory - } - } - - // Default behavior: change category for all tabs. - return { - collectionsCategory: chosenCategory, - tracksCategory: chosenCategory - } -} diff --git a/packages/common/src/utils/collectionUtils.ts b/packages/common/src/utils/collectionUtils.ts index 207acb897e..de47479459 100644 --- a/packages/common/src/utils/collectionUtils.ts +++ b/packages/common/src/utils/collectionUtils.ts @@ -1,26 +1,22 @@ import { AccountCollection } from 'store/account' -import { EnhancedCollection } from 'store/cache/collections/selectors' type FilterCollectionsOptions = { filterText?: string } -export const isAccountCollection = ( - collection: AccountCollection | EnhancedCollection -): collection is AccountCollection => { - return (collection as AccountCollection).name !== undefined -} - -export function filterCollections< - T extends AccountCollection | EnhancedCollection ->(collections: T[], { filterText = '' }: FilterCollectionsOptions): T[] { - return collections.filter((item: AccountCollection | EnhancedCollection) => { - const name = isAccountCollection(item) ? item.name : item.playlist_name - const matchesPlaylistName = - name.toLowerCase().indexOf(filterText.toLowerCase()) > -1 - const matchesOwnerName = - item.user.handle.toLowerCase().indexOf(filterText.toLowerCase()) > -1 +export function filterCollections( + collections: AccountCollection[], + { filterText = '' }: FilterCollectionsOptions +): AccountCollection[] { + return collections.filter((item: AccountCollection) => { + if (filterText) { + const matchesPlaylistName = + item.name.toLowerCase().indexOf(filterText.toLowerCase()) > -1 + const matchesOwnerName = + item.user.handle.toLowerCase().indexOf(filterText.toLowerCase()) > -1 - return matchesPlaylistName || matchesOwnerName + return matchesPlaylistName || matchesOwnerName + } + return true }) } diff --git a/packages/common/src/utils/typeUtils.ts b/packages/common/src/utils/typeUtils.ts index 31a8ced79b..6898a9b20b 100644 --- a/packages/common/src/utils/typeUtils.ts +++ b/packages/common/src/utils/typeUtils.ts @@ -29,5 +29,3 @@ export type Maybe = T | undefined * */ export type Brand = T & { _brand: U } - -export type ValueOf = T[keyof T] diff --git a/packages/mobile/android/app/src/main/res/raw/library_dark.riv b/packages/mobile/android/app/src/main/res/raw/library_dark.riv deleted file mode 100755 index b252efd15c..0000000000 Binary files a/packages/mobile/android/app/src/main/res/raw/library_dark.riv and /dev/null differ diff --git a/packages/mobile/android/app/src/main/res/raw/library_default.riv b/packages/mobile/android/app/src/main/res/raw/library_default.riv deleted file mode 100755 index 4ebdb7524a..0000000000 Binary files a/packages/mobile/android/app/src/main/res/raw/library_default.riv and /dev/null differ diff --git a/packages/mobile/android/app/src/main/res/raw/library_matrix.riv b/packages/mobile/android/app/src/main/res/raw/library_matrix.riv deleted file mode 100755 index 119ba630b2..0000000000 Binary files a/packages/mobile/android/app/src/main/res/raw/library_matrix.riv and /dev/null differ diff --git a/packages/mobile/ios/Assets/library_dark.riv b/packages/mobile/ios/Assets/library_dark.riv deleted file mode 100755 index b252efd15c..0000000000 Binary files a/packages/mobile/ios/Assets/library_dark.riv and /dev/null differ diff --git a/packages/mobile/ios/Assets/library_default.riv b/packages/mobile/ios/Assets/library_default.riv deleted file mode 100755 index 4ebdb7524a..0000000000 Binary files a/packages/mobile/ios/Assets/library_default.riv and /dev/null differ diff --git a/packages/mobile/ios/Assets/library_matrix.riv b/packages/mobile/ios/Assets/library_matrix.riv deleted file mode 100755 index 119ba630b2..0000000000 Binary files a/packages/mobile/ios/Assets/library_matrix.riv and /dev/null differ diff --git a/packages/mobile/ios/AudiusReactNative.xcodeproj/project.pbxproj b/packages/mobile/ios/AudiusReactNative.xcodeproj/project.pbxproj index e1f28104e8..3a68ee0937 100644 --- a/packages/mobile/ios/AudiusReactNative.xcodeproj/project.pbxproj +++ b/packages/mobile/ios/AudiusReactNative.xcodeproj/project.pbxproj @@ -26,10 +26,6 @@ 23C6F6592977C46F00F66384 /* trending_matrix.riv in Resources */ = {isa = PBXBuildFile; fileRef = 23C6F6542977C46F00F66384 /* trending_matrix.riv */; }; 23C6F65A2977C46F00F66384 /* notifications_matrix.riv in Resources */ = {isa = PBXBuildFile; fileRef = 23C6F6552977C46F00F66384 /* notifications_matrix.riv */; }; 23C6F65B2977C46F00F66384 /* feed_matrix.riv in Resources */ = {isa = PBXBuildFile; fileRef = 23C6F6562977C46F00F66384 /* feed_matrix.riv */; }; - AA7D28012A68C20F008DF4D3 /* library_dark.riv in Resources */ = {isa = PBXBuildFile; fileRef = AA7D27FE2A68C20F008DF4D3 /* library_dark.riv */; }; - AA7D28022A68C20F008DF4D3 /* library_matrix.riv in Resources */ = {isa = PBXBuildFile; fileRef = AA7D27FF2A68C20F008DF4D3 /* library_matrix.riv */; }; - AA7D28032A68C20F008DF4D3 /* library_default.riv in Resources */ = {isa = PBXBuildFile; fileRef = AA7D28002A68C20F008DF4D3 /* library_default.riv */; }; - B84EBFE7A8480433FB2462D9 /* libPods-AudiusReactNative.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 673EB20B90B4A9514D739B99 /* libPods-AudiusReactNative.a */; }; 2FD70DEA0D63544E733CB96F /* libPods-AudiusReactNative.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DDFBD1F0A838E1F603A49CAD /* libPods-AudiusReactNative.a */; }; 32FE1B49FE7E47B69CF28E06 /* AvenirNextLTPro-Bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = EA6D8E31A68B4451B423AFF0 /* AvenirNextLTPro-Bold.otf */; }; 5983D8FED74747CCA45F8FC4 /* AvenirNextLTPro-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 33E11CC84EEA4109B8A1AE2C /* AvenirNextLTPro-Medium.otf */; }; @@ -93,9 +89,6 @@ 8C29422A63AC4C07972EBA59 /* Pods-AudiusReactNative.staging.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AudiusReactNative.staging.release.xcconfig"; path = "Target Support Files/Pods-AudiusReactNative/Pods-AudiusReactNative.staging.release.xcconfig"; sourceTree = ""; }; 8FFE615B56774422849C5A08 /* AvenirNextLTPro-Light.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "AvenirNextLTPro-Light.otf"; path = "../src/assets/fonts/AvenirNextLTPro-Light.otf"; sourceTree = ""; }; A20D1DBF23ABDA2B003D6530 /* Audius Music.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = "Audius Music.entitlements"; path = "AudiusReactNative/Audius Music.entitlements"; sourceTree = ""; }; - AA7D27FE2A68C20F008DF4D3 /* library_dark.riv */ = {isa = PBXFileReference; lastKnownFileType = file; name = library_dark.riv; path = Assets/library_dark.riv; sourceTree = ""; }; - AA7D27FF2A68C20F008DF4D3 /* library_matrix.riv */ = {isa = PBXFileReference; lastKnownFileType = file; name = library_matrix.riv; path = Assets/library_matrix.riv; sourceTree = ""; }; - AA7D28002A68C20F008DF4D3 /* library_default.riv */ = {isa = PBXFileReference; lastKnownFileType = file; name = library_default.riv; path = Assets/library_default.riv; sourceTree = ""; }; BAEB40775EC64F48AC1983F7 /* AvenirNextLTPro-Thin.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "AvenirNextLTPro-Thin.otf"; path = "../src/assets/fonts/AvenirNextLTPro-Thin.otf"; sourceTree = ""; }; CCC75FDE7026DD7C68CFC0BA /* Pods-AudiusReactNative.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AudiusReactNative.debug.xcconfig"; path = "Target Support Files/Pods-AudiusReactNative/Pods-AudiusReactNative.debug.xcconfig"; sourceTree = ""; }; D40C2F0A0A4641D18D426558 /* AvenirNextLTPro-Heavy.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "AvenirNextLTPro-Heavy.otf"; path = "../src/assets/fonts/AvenirNextLTPro-Heavy.otf"; sourceTree = ""; }; @@ -158,9 +151,6 @@ 23C6F63D2977C23800F66384 /* Assets */ = { isa = PBXGroup; children = ( - AA7D27FE2A68C20F008DF4D3 /* library_dark.riv */, - AA7D28002A68C20F008DF4D3 /* library_default.riv */, - AA7D27FF2A68C20F008DF4D3 /* library_matrix.riv */, 71F51B7A29885F9700650D0A /* downloading_dark.riv */, 71F51B7B29885F9700650D0A /* downloading_default.riv */, 71F51B7C29885F9700650D0A /* downloading_matrix.riv */, @@ -348,17 +338,14 @@ 32FE1B49FE7E47B69CF28E06 /* AvenirNextLTPro-Bold.otf in Resources */, 71F51B7E29885F9700650D0A /* downloading_default.riv in Resources */, 23C6F64D2977C27A00F66384 /* feed_default.riv in Resources */, - AA7D28032A68C20F008DF4D3 /* library_default.riv in Resources */, C48560F6F96345AC8C69506F /* AvenirNextLTPro-Heavy.otf in Resources */, 5983D8FED74747CCA45F8FC4 /* AvenirNextLTPro-Medium.otf in Resources */, - AA7D28012A68C20F008DF4D3 /* library_dark.riv in Resources */, 9204DC5D38C1495FA330CF12 /* AvenirNextLTPro-Regular.otf in Resources */, 23B4E1CE297889CB00016FEE /* notifications_dark.riv in Resources */, 71F51B7F29885F9700650D0A /* downloading_matrix.riv in Resources */, CFE33B15004249189EB75CDC /* AvenirNextLTPro-UltLt.otf in Resources */, F50849B3CA2D48F3852465FA /* AvenirNextLTPro-Light.otf in Resources */, 71F51B7D29885F9700650D0A /* downloading_dark.riv in Resources */, - AA7D28022A68C20F008DF4D3 /* library_matrix.riv in Resources */, 23C6F6502977C27A00F66384 /* explore_dark.riv in Resources */, 9A21B5C22EF94A738EBABFED /* AvenirNextLTPro-Thin.otf in Resources */, 23C6F64F2977C27A00F66384 /* notifications_default.riv in Resources */, diff --git a/packages/mobile/src/app/Drawers.tsx b/packages/mobile/src/app/Drawers.tsx index 2c4e6a28e2..43824bd6db 100644 --- a/packages/mobile/src/app/Drawers.tsx +++ b/packages/mobile/src/app/Drawers.tsx @@ -45,8 +45,7 @@ import { RemoveDownloadedCollectionDrawer, RemoveDownloadedFavoritesDrawer, UnfavoriteDownloadedCollectionDrawer, - DeleteTrackConfirmationDrawer, - OfflineListeningDrawer + DeleteTrackConfirmationDrawer } from '../components/drawers' import { ShareToStoryProgressDrawer } from '../components/share-drawer/useShareToStory' import { VipDiscordDrawer } from '../components/vip-discord-drawer' @@ -115,7 +114,6 @@ const commonDrawersMap: { [Modal in Modals]?: ComponentType } = { const nativeDrawersMap: { [DrawerName in Drawer]?: ComponentType } = { EnablePushNotifications: EnablePushNotificationsDrawer, - OfflineListening: OfflineListeningDrawer, DownloadTrackProgress: DownloadTrackProgressDrawer, ForgotPassword: ForgotPasswordDrawer, DeleteTrackConfirmation: DeleteTrackConfirmationDrawer, diff --git a/packages/mobile/src/assets/images/iconLibrary.svg b/packages/mobile/src/assets/images/iconLibrary.svg deleted file mode 100644 index e178b6edbb..0000000000 --- a/packages/mobile/src/assets/images/iconLibrary.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/packages/mobile/src/components/bottom-tab-bar/bottom-tab-bar-buttons/FavoritesButton.tsx b/packages/mobile/src/components/bottom-tab-bar/bottom-tab-bar-buttons/FavoritesButton.tsx new file mode 100644 index 0000000000..ba4f80efda --- /dev/null +++ b/packages/mobile/src/components/bottom-tab-bar/bottom-tab-bar-buttons/FavoritesButton.tsx @@ -0,0 +1,8 @@ +import type { BaseBottomTabBarButtonProps } from './BottomTabBarButton' +import { BottomTabBarButton } from './BottomTabBarButton' + +type FavoritesButtonProps = BaseBottomTabBarButtonProps + +export const FavoritesButton = (props: FavoritesButtonProps) => { + return +} diff --git a/packages/mobile/src/components/bottom-tab-bar/bottom-tab-bar-buttons/LibraryButton.tsx b/packages/mobile/src/components/bottom-tab-bar/bottom-tab-bar-buttons/LibraryButton.tsx deleted file mode 100644 index b97bfcd69e..0000000000 --- a/packages/mobile/src/components/bottom-tab-bar/bottom-tab-bar-buttons/LibraryButton.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import type { BaseBottomTabBarButtonProps } from './BottomTabBarButton' -import { BottomTabBarButton } from './BottomTabBarButton' - -type LibraryButtonProps = BaseBottomTabBarButtonProps - -export const LibraryButton = (props: LibraryButtonProps) => { - return -} diff --git a/packages/mobile/src/components/bottom-tab-bar/bottom-tab-bar-buttons/index.ts b/packages/mobile/src/components/bottom-tab-bar/bottom-tab-bar-buttons/index.ts index 97588d6162..72c8cdea1c 100644 --- a/packages/mobile/src/components/bottom-tab-bar/bottom-tab-bar-buttons/index.ts +++ b/packages/mobile/src/components/bottom-tab-bar/bottom-tab-bar-buttons/index.ts @@ -1,6 +1,6 @@ import { ExploreButton } from './ExploreButton' +import { FavoritesButton } from './FavoritesButton' import { FeedButton } from './FeedButton' -import { LibraryButton } from './LibraryButton' import { NotificationsButton } from './NotificationsButton' import { TrendingButton } from './TrendingButton' @@ -8,12 +8,12 @@ export const bottomTabBarButtons = { feed: FeedButton, trending: TrendingButton, explore: ExploreButton, - library: LibraryButton, + favorites: FavoritesButton, notifications: NotificationsButton } export * from './ExploreButton' -export * from './LibraryButton' +export * from './FavoritesButton' export * from './FeedButton' export * from './TrendingButton' export * from './NotificationsButton' diff --git a/packages/mobile/src/components/collection-list/AddCollectionCard.tsx b/packages/mobile/src/components/collection-list/AddCollectionCard.tsx index 6aba004914..0a2dc53ac1 100644 --- a/packages/mobile/src/components/collection-list/AddCollectionCard.tsx +++ b/packages/mobile/src/components/collection-list/AddCollectionCard.tsx @@ -41,7 +41,7 @@ const useStyles = makeStyles(({ spacing }) => ({ export const AddCollectionCard = ({ onCreate, - source = CreatePlaylistSource.LIBRARY_PAGE, + source = CreatePlaylistSource.FAVORITES_PAGE, sourceTrackId = null }: AddCollectionCardProps) => { const styles = useStyles() diff --git a/packages/mobile/src/components/collection-list/CollectionList.tsx b/packages/mobile/src/components/collection-list/CollectionList.tsx index e2f1fe9f9d..131a756a11 100644 --- a/packages/mobile/src/components/collection-list/CollectionList.tsx +++ b/packages/mobile/src/components/collection-list/CollectionList.tsx @@ -46,7 +46,7 @@ const FullCollectionList = (props: FullCollectionListProps) => { collection, collectionIdsToNumTracks, showCreatePlaylistTile = false, - createPlaylistSource = CreatePlaylistSource.LIBRARY_PAGE, + createPlaylistSource = CreatePlaylistSource.FAVORITES_PAGE, createPlaylistTrackId, createPlaylistCallback, renderItem, @@ -99,7 +99,7 @@ const CollectionIDList = (props: CollectionIdListProps) => { const { collectionIds, showCreatePlaylistTile = false, - createPlaylistSource = CreatePlaylistSource.LIBRARY_PAGE, + createPlaylistSource = CreatePlaylistSource.FAVORITES_PAGE, createPlaylistTrackId, createPlaylistCallback, ...other diff --git a/packages/mobile/src/components/core/HarmonyModalHeader.tsx b/packages/mobile/src/components/core/HarmonyModalHeader.tsx deleted file mode 100644 index d62fdab5f7..0000000000 --- a/packages/mobile/src/components/core/HarmonyModalHeader.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import type { ComponentType } from 'react' - -import { View } from 'react-native' -import type { SvgProps } from 'react-native-svg' - -import { Text } from 'app/components/core' -import { makeStyles } from 'app/styles' -import { useThemeColors } from 'app/utils/theme' - -const useStyles = makeStyles(({ spacing, palette }) => ({ - container: { - width: '100%', - flexDirection: 'row', - justifyContent: 'center', - alignItems: 'center', - paddingBottom: spacing(4), - borderBottomColor: palette.neutralLight8, - borderBottomWidth: 1 - }, - titleIcon: { - marginRight: spacing(2) - } -})) - -type HarmonyModalHeaderProps = { - icon: ComponentType - title: string -} - -export const HarmonyModalHeader = ({ - icon: Icon, - title -}: HarmonyModalHeaderProps) => { - const styles = useStyles() - const { neutralLight2 } = useThemeColors() - - return ( - - - - {title} - - - ) -} diff --git a/packages/mobile/src/components/drawers/OfflineListeningDrawer.tsx b/packages/mobile/src/components/drawers/OfflineListeningDrawer.tsx deleted file mode 100644 index bdaac17ffa..0000000000 --- a/packages/mobile/src/components/drawers/OfflineListeningDrawer.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import type { ComponentType } from 'react' -import { useCallback, useState } from 'react' - -import { View } from 'react-native' -import type { SvgProps } from 'react-native-svg' -import { useDispatch } from 'react-redux' - -import IconCart from 'app/assets/images/iconCart.svg' -import IconDownload from 'app/assets/images/iconDownloadQueued.svg' -import IconFavorite from 'app/assets/images/iconFavorite.svg' -import IconRepost from 'app/assets/images/iconRepost.svg' -import { Button, Switch, Text } from 'app/components/core' -import { useDrawer } from 'app/hooks/useDrawer' -import { setVisibility } from 'app/store/drawers/slice' -import { requestDownloadAllFavorites } from 'app/store/offline-downloads/slice' -import { makeStyles } from 'app/styles' -import { useThemeColors } from 'app/utils/theme' - -import { HarmonyModalHeader } from '../core/HarmonyModalHeader' -import { NativeDrawer } from '../drawer' - -const useDrawerStyles = makeStyles(({ spacing, palette, typography }) => ({ - container: { - paddingVertical: spacing(6), - flexDirection: 'column', - paddingHorizontal: spacing(4), - rowGap: spacing(6), - alignItems: 'center' - }, - descriptionText: { - textAlign: 'center', - lineHeight: typography.fontSize.large * 1.3 - }, - titleIcon: { - position: 'relative', - top: 7, - color: palette.neutral, - marginRight: spacing(3) - } -})) - -const useToggleStyles = makeStyles(({ spacing, palette }) => ({ - toggleContainer: { - flexDirection: 'row', - justifyContent: 'space-between', - width: '100%', - alignItems: 'center' - }, - titleContainer: { - columnGap: spacing(2), - flexDirection: 'row' - } -})) - -const messages = { - offlineListeningTitle: 'Offline Listening', - offlineListeningDescription: - 'Use the toggles to select what you’d like synced for offline streaming.', - comingSoonToggleSuffix: '(coming soon...)', - favorites: 'Favorites', - reposts: 'Reposts', - purchased: 'Purchased', - saveChanges: 'Save Changes' -} - -type OfflineListeningOptionToggleProps = { - title: string - icon: ComponentType - value: boolean - onValueChange?: (value: boolean) => void | Promise - disabled?: boolean -} - -const OfflineListeningOptionToggle = ({ - title, - icon: Icon, - value, - onValueChange, - disabled -}: OfflineListeningOptionToggleProps) => { - const styles = useToggleStyles() - const { neutral, neutralLight4 } = useThemeColors() - - return ( - - - - - {title} - - - - - ) -} - -export const OfflineListeningDrawer = () => { - const styles = useDrawerStyles() - const dispatch = useDispatch() - const { data, onClose } = useDrawer('OfflineListening') - const { isFavoritesMarkedForDownload, onSaveChanges } = data - - const [isFavoritesOn, setIsFavoritesOn] = useState( - isFavoritesMarkedForDownload - ) - - const handleSaveChanges = useCallback(() => { - if (isFavoritesMarkedForDownload && !isFavoritesOn) { - dispatch( - setVisibility({ - drawer: 'RemoveDownloadedFavorites', - visible: true - }) - ) - onSaveChanges(isFavoritesOn) - } else if (!isFavoritesMarkedForDownload && isFavoritesOn) { - dispatch(requestDownloadAllFavorites()) - onSaveChanges(isFavoritesOn) - } - - onClose() - }, [ - dispatch, - isFavoritesMarkedForDownload, - isFavoritesOn, - onClose, - onSaveChanges - ]) - - const handleToggleFavorites = useCallback((value: boolean) => { - setIsFavoritesOn(value) - }, []) - - return ( - - - - - {messages.offlineListeningDescription} - - - - -