From 3633e4a62ce1b5ebd88f4be097728e654365e0b9 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sun, 13 Feb 2022 20:08:37 -0800 Subject: [PATCH] Add useFavorite hook, refactor components --- src/components/dashboard/Dashboard.tsx | 104 ++---------- src/components/library/AlbumList.tsx | 41 +---- src/components/library/AlbumView.tsx | 83 +++------ src/components/library/ArtistList.tsx | 41 +---- src/components/library/ArtistView.tsx | 170 +++++-------------- src/components/library/FolderList.tsx | 51 +++--- src/components/library/MusicList.tsx | 41 +---- src/components/player/NowPlayingInfoView.tsx | 51 +++--- src/components/player/NowPlayingMiniView.tsx | 22 +-- src/components/player/NowPlayingView.tsx | 22 +-- src/components/player/PlayerBar.tsx | 71 ++++---- src/components/playlist/PlaylistView.tsx | 57 +------ src/components/search/SearchView.tsx | 44 ++++- src/components/starred/StarredView.tsx | 92 +++++----- src/hooks/useFavorite.ts | 75 ++++++++ 15 files changed, 353 insertions(+), 612 deletions(-) create mode 100644 src/hooks/useFavorite.ts diff --git a/src/components/dashboard/Dashboard.tsx b/src/components/dashboard/Dashboard.tsx index 146cabe..edc32d1 100644 --- a/src/components/dashboard/Dashboard.tsx +++ b/src/components/dashboard/Dashboard.tsx @@ -1,23 +1,21 @@ import React, { useEffect, useState } from 'react'; -import _ from 'lodash'; import { useHistory } from 'react-router-dom'; -import { useQuery, useQueryClient } from 'react-query'; +import { useQuery } from 'react-query'; import { useTranslation } from 'react-i18next'; import GenericPage from '../layout/GenericPage'; import GenericPageHeader from '../layout/GenericPageHeader'; import ScrollingMenu from '../scrollingmenu/ScrollingMenu'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; -import { setStar } from '../../redux/playQueueSlice'; import { apiController } from '../../api/controller'; import { Item, Server } from '../../types'; import { setFilter, setPagination } from '../../redux/viewSlice'; import CenterLoader from '../loader/CenterLoader'; +import useFavorite from '../../hooks/useFavorite'; const Dashboard = () => { const { t } = useTranslation(); const history = useHistory(); const dispatch = useAppDispatch(); - const queryClient = useQueryClient(); const folder = useAppSelector((state) => state.folder); const config = useAppSelector((state) => state.config); const [musicFolder, setMusicFolder] = useState({ loaded: false, id: undefined }); @@ -94,87 +92,7 @@ const Dashboard = () => { } ); - const handleFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'album' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'star' })); - queryClient.setQueryData(['recentAlbums', musicFolder.id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = Date.now(); - }); - - return oldData; - }); - queryClient.setQueryData(['newestAlbums', musicFolder.id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = Date.now(); - }); - - return oldData; - }); - queryClient.setQueryData(['randomAlbums', musicFolder.id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = Date.now(); - }); - - return oldData; - }); - queryClient.setQueryData(['frequentAlbums', musicFolder.id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = Date.now(); - }); - - return oldData; - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'album' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'unstar' })); - queryClient.setQueryData(['recentAlbums', musicFolder.id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = undefined; - }); - - return oldData; - }); - queryClient.setQueryData(['newestAlbums', musicFolder.id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = undefined; - }); - - return oldData; - }); - queryClient.setQueryData(['randomAlbums', musicFolder.id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = undefined; - }); - - return oldData; - }); - queryClient.setQueryData(['frequentAlbums', musicFolder.id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = undefined; - }); - - return oldData; - }); - } - }; + const { handleFavorite } = useFavorite(); if ( isLoadingRecent || @@ -213,7 +131,9 @@ const Dashboard = () => { }, 50); }} type="music" - handleFavorite={handleFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['recentAlbums', musicFolder.id] }) + } /> { }, 50); }} type="album" - handleFavorite={handleFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['newestAlbums', musicFolder.id] }) + } /> { }, 50); }} type="album" - handleFavorite={handleFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['randomAlbums', musicFolder.id] }) + } /> { }, 50); }} type="music" - handleFavorite={handleFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['frequentAlbums', musicFolder.id] }) + } /> )} diff --git a/src/components/library/AlbumList.tsx b/src/components/library/AlbumList.tsx index 453038b..2148f54 100644 --- a/src/components/library/AlbumList.tsx +++ b/src/components/library/AlbumList.tsx @@ -31,6 +31,7 @@ import useGridScroll from '../../hooks/useGridScroll'; import useListScroll from '../../hooks/useListScroll'; import useListClickHandler from '../../hooks/useListClickHandler'; import Popup from '../shared/Popup'; +import useFavorite from '../../hooks/useFavorite'; export const ALBUM_SORT_TYPES = [ { label: i18n.t('A-Z (Name)'), value: 'alphabeticalByName', role: i18n.t('Default') }, @@ -210,37 +211,7 @@ const AlbumList = () => { setIsRefreshing(false); }; - const handleRowFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'album' }, - }); - queryClient.setQueryData(['albumList', view.album.filter, musicFolder.id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = Date.now(); - }); - - return oldData; - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'album' }, - }); - queryClient.setQueryData(['albumList', view.album.filter, musicFolder.id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = undefined; - }); - - return oldData; - }); - } - }; + const { handleFavorite } = useFavorite(); const handleRowRating = (rowData: any, e: number) => { apiController({ @@ -440,7 +411,9 @@ const AlbumList = () => { 'viewInFolder', ]} loading={isLoading} - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['albumList', view.album.filter, musicFolder.id] }) + } initialScrollOffset={Number(localStorage.getItem('scroll_list_albumList'))} onScroll={(scrollIndex: number) => { localStorage.setItem('scroll_list_albumList', String(Math.abs(scrollIndex))); @@ -514,7 +487,9 @@ const AlbumList = () => { playClick={{ type: 'album', idProperty: 'id' }} size={config.lookAndFeel.gridView.cardSize} cacheType="album" - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['albumList', view.album.filter, musicFolder.id] }) + } initialScrollOffset={Number(localStorage.getItem('scroll_grid_albumList'))} onScroll={(scrollIndex: number) => { localStorage.setItem('scroll_grid_albumList', String(scrollIndex)); diff --git a/src/components/library/AlbumView.tsx b/src/components/library/AlbumView.tsx index 832d4da..e79c0cb 100644 --- a/src/components/library/AlbumView.tsx +++ b/src/components/library/AlbumView.tsx @@ -15,12 +15,7 @@ import { PlayButton, } from '../shared/ToolbarButtons'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; -import { - fixPlayer2Index, - setPlayQueueByRowClick, - setRate, - setStar, -} from '../../redux/playQueueSlice'; +import { fixPlayer2Index, setPlayQueueByRowClick, setRate } from '../../redux/playQueueSlice'; import useSearchQuery from '../../hooks/useSearchQuery'; import GenericPage from '../layout/GenericPage'; import ListViewType from '../viewtypes/ListViewType'; @@ -44,6 +39,7 @@ import CenterLoader from '../loader/CenterLoader'; import useListClickHandler from '../../hooks/useListClickHandler'; import Popup from '../shared/Popup'; import usePlayQueueHandler from '../../hooks/usePlayQueueHandler'; +import useFavorite from '../../hooks/useFavorite'; interface AlbumParams { id: string; @@ -95,58 +91,7 @@ const AlbumView = ({ ...rest }: any) => { }); const { handlePlayQueueAdd } = usePlayQueueHandler(); - - const handleFavorite = async () => { - if (!data.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: data.id, type: 'album' }, - }); - queryClient.setQueryData(['album', id], { ...data, starred: Date.now() }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: data.id, type: 'album' }, - }); - queryClient.setQueryData(['album', id], { ...data, starred: undefined }); - } - }; - - const handleRowFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'star' })); - queryClient.setQueryData(['album', id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData?.song, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.song[index].starred = Date.now(); - }); - - return oldData; - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'unstar' })); - queryClient.setQueryData(['album', id], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData?.song, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.song[index].starred = undefined; - }); - - return oldData; - }); - } - }; + const { handleFavorite } = useFavorite(); const handleDownload = async (type: 'copy' | 'download') => { if (config.serverType === Server.Jellyfin) { @@ -271,7 +216,15 @@ const AlbumView = ({ ...rest }: any) => { details={data} playClick={{ type: 'album', id: data.id }} url={`/library/album/${data.id}`} - handleFavorite={handleFavorite} + handleFavorite={() => + handleFavorite(data, { + custom: () => + queryClient.setQueryData(['album', id], { + ...data, + starred: data?.starred ? undefined : Date.now(), + }), + }) + } /> } cacheImages={{ @@ -459,7 +412,15 @@ const AlbumView = ({ ...rest }: any) => { size="lg" appearance="subtle" isFavorite={data.starred} - onClick={handleFavorite} + onClick={() => + handleFavorite(data, { + custom: () => + queryClient.setQueryData(['album', id], { + ...data, + starred: data?.starred ? undefined : Date.now(), + }), + }) + } /> { 'deletePlaylist', 'viewInModal', ]} - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => handleFavorite(rowData, { queryKey: ['album', id] })} /> diff --git a/src/components/library/ArtistList.tsx b/src/components/library/ArtistList.tsx index 9f7679f..46a7268 100644 --- a/src/components/library/ArtistList.tsx +++ b/src/components/library/ArtistList.tsx @@ -19,6 +19,7 @@ import useColumnSort from '../../hooks/useColumnSort'; import { setSort } from '../../redux/artistSlice'; import { StyledTag } from '../shared/styled'; import useListClickHandler from '../../hooks/useListClickHandler'; +import useFavorite from '../../hooks/useFavorite'; const ArtistList = () => { const { t } = useTranslation(); @@ -65,37 +66,7 @@ const ArtistList = () => { setIsRefreshing(false); }; - const handleRowFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'artist' }, - }); - queryClient.setQueryData(['artistList', musicFolder], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData[index].starred = Date.now(); - }); - - return oldData; - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'artist' }, - }); - queryClient.setQueryData(['artistList', musicFolder], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData[index].starred = undefined; - }); - - return oldData; - }); - } - }; + const { handleFavorite } = useFavorite(); const handleRowRating = (rowData: any, e: number) => { apiController({ @@ -211,7 +182,9 @@ const ArtistList = () => { 'deletePlaylist', 'viewInFolder', ]} - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['artistList', musicFolder] }) + } initialScrollOffset={Number(localStorage.getItem('scroll_list_artistList'))} onScroll={(scrollIndex: number) => { localStorage.setItem('scroll_list_artistList', String(Math.abs(scrollIndex))); @@ -236,7 +209,9 @@ const ArtistList = () => { playClick={{ type: 'artist', idProperty: 'id' }} size={config.lookAndFeel.gridView.cardSize} cacheType="artist" - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['artistList', musicFolder] }) + } initialScrollOffset={Number(localStorage.getItem('scroll_grid_artistList'))} onScroll={(scrollIndex: number) => { localStorage.setItem('scroll_grid_artistList', String(scrollIndex)); diff --git a/src/components/library/ArtistView.tsx b/src/components/library/ArtistView.tsx index bf23390..9139242 100644 --- a/src/components/library/ArtistView.tsx +++ b/src/components/library/ArtistView.tsx @@ -41,6 +41,7 @@ import CenterLoader from '../loader/CenterLoader'; import useListClickHandler from '../../hooks/useListClickHandler'; import Popup from '../shared/Popup'; import usePlayQueueHandler from '../../hooks/usePlayQueueHandler'; +import useFavorite from '../../hooks/useFavorite'; const fac = new FastAverageColor(); @@ -155,122 +156,9 @@ const ArtistView = ({ ...rest }: any) => { }, }); - const handleFavorite = async () => { - if (!data.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: data.id, type: 'artist' }, - }); - queryClient.setQueryData(['artist', artistId, musicFolder], { ...data, starred: Date.now() }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: data.id, type: 'artist' }, - }); - queryClient.setQueryData(['artist', artistId, musicFolder], { ...data, starred: undefined }); - } - }; - + const { handleFavorite } = useFavorite(); const { handlePlayQueueAdd } = usePlayQueueHandler(); - const handleRowFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'album' }, - }); - queryClient.setQueryData(['artist', artistId, musicFolder], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData?.album, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.album[index].starred = Date.now(); - }); - - return oldData; - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'album' }, - }); - queryClient.setQueryData(['artist', artistId, musicFolder], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData?.album, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.album[index].starred = undefined; - }); - - return oldData; - }); - } - }; - - const handleSimilarArtistRowFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'artist' }, - }); - queryClient.setQueryData(['artist', artistId, musicFolder], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData?.info?.similarArtist, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.info.similarArtist[index].starred = Date.now(); - }); - - return oldData; - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'artist' }, - }); - queryClient.setQueryData(['artist', artistId, musicFolder], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData?.info?.similarArtist, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.info.similarArtist[index].starred = undefined; - }); - - return oldData; - }); - } - }; - - const handleMusicRowFavorite = async (rowData: any, query: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'music' }, - }); - queryClient.setQueryData(query, (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData[index].starred = Date.now(); - }); - - return oldData; - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'music' }, - }); - queryClient.setQueryData(query, (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData[index].starred = undefined; - }); - - return oldData; - }); - } - }; - const handleRowRating = async (rowData: any, e: number, query: any) => { apiController({ serverType: config.serverType, @@ -650,7 +538,15 @@ const ArtistView = ({ ...rest }: any) => { size="lg" appearance="subtle" isFavorite={data.starred} - onClick={() => handleFavorite()} + onClick={() => + handleFavorite(data, { + custom: () => + queryClient.setQueryData(['artist', artistId, musicFolder], { + ...data, + starred: data?.starred ? undefined : Date.now(), + }), + }) + } /> { dnd disabledContextMenuOptions={['deletePlaylist', 'viewInModal']} handleFavorite={(rowData: any) => - handleMusicRowFavorite(rowData, ['artistSongs', artistId]) + handleFavorite(rowData, { queryKey: ['artistSongs', artistId] }) } handleRating={(rowData: any, e: number) => handleRowRating(rowData, e, ['artistSongs', artistId]) @@ -763,7 +659,9 @@ const ArtistView = ({ ...rest }: any) => { 'deletePlaylist', 'viewInFolder', ]} - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['artist', artistId, musicFolder] }) + } /> )} @@ -789,7 +687,9 @@ const ArtistView = ({ ...rest }: any) => { size={config.lookAndFeel.gridView.cardSize} cacheType="album" isModal={rest.isModal} - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['artist', artistId, musicFolder] }) + } /> )} @@ -811,7 +711,7 @@ const ArtistView = ({ ...rest }: any) => { dnd disabledContextMenuOptions={['deletePlaylist', 'viewInModal']} handleFavorite={(rowData: any) => - handleMusicRowFavorite(rowData, ['artistTopSongs', data?.title]) + handleFavorite(rowData, { queryKey: ['artistTopSongs', data?.title] }) } handleRating={(rowData: any, e: number) => handleRowRating(rowData, e, ['artistTopSongs', data?.title]) @@ -892,7 +792,7 @@ const ArtistView = ({ ...rest }: any) => { isModal={false} miniView={false} handleFavorite={(rowData: any) => - handleMusicRowFavorite(rowData, ['artistTopSongs', data.title]) + handleFavorite(rowData, { queryKey: ['artistTopSongs', data.title] }) } handleRowClick={handleRowClick} handleRowDoubleClick={(e: any) => handleRowDoubleClick(e, topSongs)} @@ -973,7 +873,9 @@ const ArtistView = ({ ...rest }: any) => { cardSize={config.lookAndFeel.gridView.cardSize} type="album" noScrollbar - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['artist', artistId, musicFolder] }) + } /> )} @@ -1032,7 +934,9 @@ const ArtistView = ({ ...rest }: any) => { cardSize={config.lookAndFeel.gridView.cardSize} type="album" noScrollbar - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['artist', artistId, musicFolder] }) + } /> )} @@ -1098,7 +1002,27 @@ const ArtistView = ({ ...rest }: any) => { cardSize={config.lookAndFeel.gridView.cardSize} type="artist" noScrollbar - handleFavorite={handleSimilarArtistRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { + custom: () => { + queryClient.setQueryData( + ['artist', artistId, musicFolder], + (oldData: any) => { + const starredIndices = _.keys( + _.pickBy(oldData?.info?.similarArtist, { id: rowData.id }) + ); + starredIndices.forEach((index) => { + oldData.info.similarArtist[index].starred = rowData.starred + ? undefined + : Date.now(); + }); + + return oldData; + } + ); + }, + }) + } /> )} diff --git a/src/components/library/FolderList.tsx b/src/components/library/FolderList.tsx index 389397b..6d453e8 100644 --- a/src/components/library/FolderList.tsx +++ b/src/components/library/FolderList.tsx @@ -20,6 +20,7 @@ import { apiController } from '../../api/controller'; import { setPlaylistRate } from '../../redux/playlistSlice'; import CenterLoader from '../loader/CenterLoader'; import useListClickHandler from '../../hooks/useListClickHandler'; +import useFavorite from '../../hooks/useFavorite'; const FolderList = () => { const { t } = useTranslation(); @@ -94,37 +95,7 @@ const FolderList = () => { }, }); - const handleRowFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'album' }, - }); - queryClient.setQueryData(['folder', folder.currentViewedFolder], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.child, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.child[index].starred = Date.now(); - }); - - return oldData; - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'album' }, - }); - queryClient.setQueryData(['folder', folder.currentViewedFolder], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.child, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.child[index].starred = undefined; - }); - - return oldData; - }); - } - }; + const { handleFavorite } = useFavorite(); const handleRowRating = (rowData: any, e: number) => { apiController({ @@ -218,7 +189,23 @@ const FolderList = () => { fontSize={Number(settings.getSync('musicListFontSize'))} handleRowClick={handleRowClick} handleRowDoubleClick={handleRowDoubleClick} - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { + custom: () => { + queryClient.setQueryData( + ['folder', folder.currentViewedFolder], + (oldData: any) => { + const starredIndices = _.keys(_.pickBy(oldData.child, { id: rowData.id })); + starredIndices.forEach((index) => { + oldData.child[index].starred = rowData.starred ? undefined : Date.now(); + }); + + return oldData; + } + ); + }, + }) + } handleRating={handleRowRating} cacheImages={{ enabled: settings.getSync('cacheImages'), diff --git a/src/components/library/MusicList.tsx b/src/components/library/MusicList.tsx index 1531813..ca3083f 100644 --- a/src/components/library/MusicList.tsx +++ b/src/components/library/MusicList.tsx @@ -16,11 +16,12 @@ import { setSearchQuery } from '../../redux/miscSlice'; import { apiController } from '../../api/controller'; import { Item } from '../../types'; import useColumnSort from '../../hooks/useColumnSort'; -import { fixPlayer2Index, setPlayQueueByRowClick, setStar } from '../../redux/playQueueSlice'; +import { fixPlayer2Index, setPlayQueueByRowClick } from '../../redux/playQueueSlice'; import { setFilter, setPagination } from '../../redux/viewSlice'; import { setStatus } from '../../redux/playerSlice'; import useListScroll from '../../hooks/useListScroll'; import useListClickHandler from '../../hooks/useListClickHandler'; +import useFavorite from '../../hooks/useFavorite'; // prettier-ignore export const MUSIC_SORT_TYPES = [ @@ -179,41 +180,7 @@ const MusicList = () => { setIsRefreshing(false); }; - const handleRowFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'star' })); - - queryClient.setQueryData(currentQueryKey, (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = Date.now(); - }); - - return oldData; - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'unstar' })); - - queryClient.setQueryData(currentQueryKey, (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.data[index].starred = undefined; - }); - - return oldData; - }); - } - }; + const { handleFavorite } = useFavorite(); const handleRowRating = (rowData: any, e: number) => { apiController({ @@ -316,7 +283,7 @@ const MusicList = () => { 'viewInFolder', ]} loading={isLoading} - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => handleFavorite(rowData, { queryKey: currentQueryKey })} initialScrollOffset={Number(localStorage.getItem('scroll_list_musicList'))} onScroll={(scrollIndex: number) => { localStorage.setItem('scroll_list_musicList', String(Math.abs(scrollIndex))); diff --git a/src/components/player/NowPlayingInfoView.tsx b/src/components/player/NowPlayingInfoView.tsx index d7333d3..cf39d40 100644 --- a/src/components/player/NowPlayingInfoView.tsx +++ b/src/components/player/NowPlayingInfoView.tsx @@ -29,6 +29,7 @@ import Card from '../card/Card'; import { setFilter, setPagination } from '../../redux/viewSlice'; import { setPlaylistRate } from '../../redux/playlistSlice'; import useListClickHandler from '../../hooks/useListClickHandler'; +import useFavorite from '../../hooks/useFavorite'; const NowPlayingInfoView = () => { const { t } = useTranslation(); @@ -94,24 +95,7 @@ const NowPlayingInfoView = () => { }, }); - const handleRowFavorite = async (rowData: any, queryKey: any) => { - console.log(rowData); - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: rowData.type }, - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: rowData.type }, - }); - } - - await queryClient.refetchQueries(queryKey); - }; + const { handleFavorite } = useFavorite(); const handleRowRating = async (rowData: any, e: number) => { apiController({ @@ -298,12 +282,9 @@ const NowPlayingInfoView = () => { miniView={false} loading={isLoadingSimilarToSong} handleFavorite={(rowData: any) => - handleRowFavorite(rowData, [ - 'similarSongs', - currentArtistId, - musicFolder, - 50, - ]) + handleFavorite(rowData, { + queryKey: ['similarSongs', currentArtistId, musicFolder, 50], + }) } handleRowClick={handleRowClick} handleRowDoubleClick={(e: any) => handleRowDoubleClick(e)} @@ -339,7 +320,7 @@ const NowPlayingInfoView = () => { type="album" noScrollbar handleFavorite={(rowData: any) => - handleRowFavorite(rowData, ['artist', currentArtistId, musicFolder]) + handleFavorite(rowData, { queryKey: ['artist', currentArtistId, musicFolder] }) } /> @@ -359,7 +340,25 @@ const NowPlayingInfoView = () => { type="artist" noScrollbar handleFavorite={(rowData: any) => - handleRowFavorite(rowData, ['artist', currentArtistId, musicFolder]) + handleFavorite(rowData, { + custom: () => { + queryClient.setQueryData( + ['artist', currentArtistId, musicFolder], + (oldData: any) => { + const starredIndices = _.keys( + _.pickBy(oldData?.info?.similarArtist, { id: rowData.id }) + ); + starredIndices.forEach((index) => { + oldData.info.similarArtist[index].starred = rowData.starred + ? undefined + : Date.now(); + }); + + return oldData; + } + ); + }, + }) } /> diff --git a/src/components/player/NowPlayingMiniView.tsx b/src/components/player/NowPlayingMiniView.tsx index 95df8c5..25c1897 100644 --- a/src/components/player/NowPlayingMiniView.tsx +++ b/src/components/player/NowPlayingMiniView.tsx @@ -14,7 +14,6 @@ import { toggleShuffle, setPlaybackSetting, removeFromPlayQueue, - setStar, setPlayQueue, appendPlayQueue, moveToTop, @@ -52,6 +51,7 @@ import { apiController } from '../../api/controller'; import { Server, Song } from '../../types'; import useListClickHandler from '../../hooks/useListClickHandler'; import Popup from '../shared/Popup'; +import useFavorite from '../../hooks/useFavorite'; const NowPlayingMiniView = () => { const { t } = useTranslation(); @@ -216,23 +216,7 @@ const NowPlayingMiniView = () => { return notifyToast('warning', t('No songs found, adjust your filters')); }; - const handleRowFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'star' })); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'unstar' })); - } - }; + const { handleFavorite } = useFavorite(); return ( <> @@ -474,7 +458,7 @@ const NowPlayingMiniView = () => { nowPlaying dnd disabledContextMenuOptions={['deletePlaylist', 'viewInModal']} - handleFavorite={handleRowFavorite} + handleFavorite={handleFavorite} /> diff --git a/src/components/player/NowPlayingView.tsx b/src/components/player/NowPlayingView.tsx index c9cf1b6..65918ae 100644 --- a/src/components/player/NowPlayingView.tsx +++ b/src/components/player/NowPlayingView.tsx @@ -16,7 +16,6 @@ import { removeFromPlayQueue, setPlayQueue, appendPlayQueue, - setStar, setRate, moveToTop, moveToBottom, @@ -57,6 +56,7 @@ import NowPlayingInfoView from './NowPlayingInfoView'; import CenterLoader from '../loader/CenterLoader'; import useListClickHandler from '../../hooks/useListClickHandler'; import Popup from '../shared/Popup'; +import useFavorite from '../../hooks/useFavorite'; const NowPlayingView = () => { const { t } = useTranslation(); @@ -229,23 +229,7 @@ const NowPlayingView = () => { return notifyToast('warning', t('No songs found, adjust your filters')); }; - const handleRowFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'star' })); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'unstar' })); - } - }; + const { handleFavorite } = useFavorite(); const handleRowRating = (rowData: any, e: number) => { apiController({ @@ -529,7 +513,7 @@ const NowPlayingView = () => { nowPlaying dnd disabledContextMenuOptions={['deletePlaylist', 'viewInModal']} - handleFavorite={handleRowFavorite} + handleFavorite={handleFavorite} handleRating={handleRowRating} initialScrollOffset={ playQueue.scrollWithCurrentSong diff --git a/src/components/player/PlayerBar.tsx b/src/components/player/PlayerBar.tsx index 83e72e6..993d1f4 100644 --- a/src/components/player/PlayerBar.tsx +++ b/src/components/player/PlayerBar.tsx @@ -19,7 +19,7 @@ import { LinkButton, CoverArtContainer, } from './styled'; -import { setVolume, setStar, setRate } from '../../redux/playQueueSlice'; +import { setVolume, setRate } from '../../redux/playQueueSlice'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; import Player from './Player'; import CustomTooltip from '../shared/CustomTooltip'; @@ -36,6 +36,7 @@ import useGetLyrics from '../../hooks/useGetLyrics'; import usePlayerControls from '../../hooks/usePlayerControls'; import { setSidebar } from '../../redux/configSlice'; import Popup from '../shared/Popup'; +import useFavorite from '../../hooks/useFavorite'; const DiscordRPC = require('discord-rpc'); @@ -295,43 +296,7 @@ const PlayerBar = () => { return () => clearTimeout(debounce); }, [config.serverType, isDragging, manualSeek, playQueue.currentPlayer]); - const handleFavorite = async () => { - if (!playQueue[currentEntryList][playQueue.currentIndex].starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: playQueue[currentEntryList][playQueue.currentIndex].id, type: 'music' }, - }); - dispatch( - setStar({ - id: [playQueue[currentEntryList][playQueue.currentIndex].id], - type: 'star', - }) - ); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: playQueue[currentEntryList][playQueue.currentIndex].id, type: 'music' }, - }); - dispatch( - setStar({ - id: [playQueue[currentEntryList][playQueue.currentIndex].id], - type: 'unstar', - }) - ); - } - - await queryClient.refetchQueries(['album'], { - active: true, - }); - await queryClient.refetchQueries(['starred'], { - active: true, - }); - await queryClient.refetchQueries(['playlist'], { - active: true, - }); - }; + const { handleFavorite } = useFavorite(); const handleRating = (e: number) => { apiController({ @@ -710,10 +675,36 @@ const PlayerBar = () => { ? 'true' : 'false' } - onClick={handleFavorite} + onClick={() => + handleFavorite(playQueue[currentEntryList][playQueue.currentIndex], { + custom: async () => { + await queryClient.refetchQueries(['album'], { + active: true, + }); + await queryClient.refetchQueries(['starred'], { + active: true, + }); + await queryClient.refetchQueries(['playlist'], { + active: true, + }); + }, + }) + } onKeyDown={(e: any) => { if (e.key === ' ') { - handleFavorite(); + handleFavorite(playQueue[currentEntryList][playQueue.currentIndex].id, { + custom: async () => { + await queryClient.refetchQueries(['album'], { + active: true, + }); + await queryClient.refetchQueries(['starred'], { + active: true, + }); + await queryClient.refetchQueries(['playlist'], { + active: true, + }); + }, + }); } }} /> diff --git a/src/components/playlist/PlaylistView.tsx b/src/components/playlist/PlaylistView.tsx index 2796c6d..12cfd8f 100644 --- a/src/components/playlist/PlaylistView.tsx +++ b/src/components/playlist/PlaylistView.tsx @@ -18,12 +18,7 @@ import { UndoButton, } from '../shared/ToolbarButtons'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; -import { - fixPlayer2Index, - setPlayQueueByRowClick, - setStar, - setRate, -} from '../../redux/playQueueSlice'; +import { fixPlayer2Index, setPlayQueueByRowClick, setRate } from '../../redux/playQueueSlice'; import { clearSelected } from '../../redux/multiSelectSlice'; import { createRecoveryFile, @@ -45,12 +40,7 @@ import { setStatus } from '../../redux/playerSlice'; import { notifyToast } from '../shared/toast'; import { addProcessingPlaylist, removeProcessingPlaylist } from '../../redux/miscSlice'; import { StyledButton, StyledCheckbox, StyledInput, StyledLink } from '../shared/styled'; -import { - removeFromPlaylist, - setPlaylistData, - setPlaylistRate, - setPlaylistStar, -} from '../../redux/playlistSlice'; +import { removeFromPlaylist, setPlaylistData, setPlaylistRate } from '../../redux/playlistSlice'; import { PageHeaderSubtitleDataLine } from '../layout/styled'; import CustomTooltip from '../shared/CustomTooltip'; import { apiController } from '../../api/controller'; @@ -60,6 +50,7 @@ import CenterLoader from '../loader/CenterLoader'; import useListClickHandler from '../../hooks/useListClickHandler'; import Popup from '../shared/Popup'; import usePlayQueueHandler from '../../hooks/usePlayQueueHandler'; +import useFavorite from '../../hooks/useFavorite'; interface PlaylistParams { id: string; @@ -359,43 +350,7 @@ const PlaylistView = ({ ...rest }) => { } }; - const handleRowFavorite = async (rowData: any) => { - if (!rowData.starred) { - await apiController({ - serverType: config.serverType, - endpoint: 'star', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'star' })); - dispatch(setPlaylistStar({ id: [rowData.id], type: 'star' })); - - queryClient.setQueryData(['playlist', playlistId], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.song, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.song[index].starred = Date.now(); - }); - - return oldData; - }); - } else { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'unstar' })); - dispatch(setPlaylistStar({ id: [rowData.id], type: 'unstar' })); - - queryClient.setQueryData(['playlist', playlistId], (oldData: any) => { - const starredIndices = _.keys(_.pickBy(oldData.song, { id: rowData.id })); - starredIndices.forEach((index) => { - oldData.song[index].starred = undefined; - }); - - return oldData; - }); - } - }; + const { handleFavorite } = useFavorite(); const handleRowRating = (rowData: any, e: number) => { apiController({ @@ -653,7 +608,9 @@ const PlaylistView = ({ ...rest }) => { dnd isModal={rest.isModal} disabledContextMenuOptions={['deletePlaylist', 'viewInModal']} - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { queryKey: ['playlist', playlistId] }) + } handleRating={handleRowRating} loading={isLoading} /> diff --git a/src/components/search/SearchView.tsx b/src/components/search/SearchView.tsx index ce66b51..4d2e318 100644 --- a/src/components/search/SearchView.tsx +++ b/src/components/search/SearchView.tsx @@ -3,7 +3,7 @@ import _ from 'lodash'; import settings from 'electron-settings'; import { Icon, Nav } from 'rsuite'; import { useHistory } from 'react-router-dom'; -import { useInfiniteQuery } from 'react-query'; +import { useInfiniteQuery, useQueryClient } from 'react-query'; import { useTranslation } from 'react-i18next'; import useRouterQuery from '../../hooks/useRouterQuery'; import GenericPage from '../layout/GenericPage'; @@ -22,10 +22,12 @@ import { apiController } from '../../api/controller'; import { Album, Artist, Item, Song } from '../../types'; import useListClickHandler from '../../hooks/useListClickHandler'; import ListViewType from '../viewtypes/ListViewType'; +import useFavorite from '../../hooks/useFavorite'; const SearchView = () => { const { t } = useTranslation(); const dispatch = useAppDispatch(); + const queryClient = useQueryClient(); const history = useHistory(); const query = useRouterQuery(); const urlQuery = query.get('query') || ''; @@ -58,8 +60,6 @@ const SearchView = () => { [history] ); - useEffect(() => {}); - const { data: songResults, isLoading: isLoadingSongs, @@ -174,6 +174,8 @@ const SearchView = () => { ); }, [artistResults]); + const { handleFavorite } = useFavorite(); + const { handleRowClick, handleRowDoubleClick } = useListClickHandler({ doubleClick: (rowData: any) => { if (rowData.isDir) { @@ -314,7 +316,17 @@ const SearchView = () => { handleRowClick={handleRowClick} handleRowDoubleClick={handleRowDoubleClick} handleRating={() => {}} - handleFavorite={() => {}} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { + custom: () => + queryClient.refetchQueries([ + 'searchpage', + debouncedSearchQuery, + { type: Item.Music, count: 50 }, + musicFolder.id, + ]), + }) + } listType="music" cacheImages={{ enabled: settings.getSync('cacheImages'), @@ -341,7 +353,17 @@ const SearchView = () => { handleRowClick={handleAlbumRowClick} handleRowDoubleClick={handleAlbumRowDoubleClick} handleRating={() => {}} - handleFavorite={() => {}} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { + custom: () => + queryClient.refetchQueries([ + 'searchpage', + debouncedSearchQuery, + { type: Item.Album, count: 25 }, + musicFolder.id, + ]), + }) + } listType="album" cacheImages={{ enabled: settings.getSync('cacheImages'), @@ -368,7 +390,17 @@ const SearchView = () => { handleRowClick={handleArtistRowClick} handleRowDoubleClick={handleArtistRowDoubleClick} handleRating={() => {}} - handleFavorite={() => {}} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { + custom: () => + queryClient.refetchQueries([ + 'searchpage', + debouncedSearchQuery, + { type: Item.Artist, count: 15 }, + musicFolder.id, + ]), + }) + } listType="artist" cacheImages={{ enabled: settings.getSync('cacheImages'), diff --git a/src/components/starred/StarredView.tsx b/src/components/starred/StarredView.tsx index b5eeb7c..200f5f6 100644 --- a/src/components/starred/StarredView.tsx +++ b/src/components/starred/StarredView.tsx @@ -6,12 +6,7 @@ import settings from 'electron-settings'; import { useTranslation } from 'react-i18next'; import useSearchQuery from '../../hooks/useSearchQuery'; import { useAppDispatch, useAppSelector } from '../../redux/hooks'; -import { - fixPlayer2Index, - setPlayQueueByRowClick, - setRate, - setStar, -} from '../../redux/playQueueSlice'; +import { fixPlayer2Index, setPlayQueueByRowClick, setRate } from '../../redux/playQueueSlice'; import GenericPage from '../layout/GenericPage'; import GenericPageHeader from '../layout/GenericPageHeader'; import ListViewType from '../viewtypes/ListViewType'; @@ -27,6 +22,7 @@ import { FilterButton } from '../shared/ToolbarButtons'; import ColumnSortPopover from '../shared/ColumnSortPopover'; import CenterLoader from '../loader/CenterLoader'; import useListClickHandler from '../../hooks/useListClickHandler'; +import useFavorite from '../../hooks/useFavorite'; const StarredView = () => { const { t } = useTranslation(); @@ -96,39 +92,7 @@ const StarredView = () => { }, }); - const handleRowFavorite = async (rowData: any) => { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'music' }, - }); - dispatch(setStar({ id: [rowData.id], type: 'unstar' })); - await queryClient.refetchQueries(['starred', musicFolder], { - active: true, - }); - }; - - const handleRowFavoriteAlbum = async (rowData: any) => { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'album' }, - }); - await queryClient.refetchQueries(['starred', musicFolder], { - active: true, - }); - }; - - const handleRowFavoriteArtist = async (rowData: any) => { - await apiController({ - serverType: config.serverType, - endpoint: 'unstar', - args: { id: rowData.id, type: 'artist' }, - }); - await queryClient.refetchQueries(['starred', musicFolder], { - active: true, - }); - }; + const { handleFavorite } = useFavorite(); const handleRowRating = async (rowData: any, e: number) => { apiController({ @@ -323,7 +287,15 @@ const StarredView = () => { 'deletePlaylist', 'viewInModal', ]} - handleFavorite={handleRowFavorite} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { + custom: async () => { + await queryClient.refetchQueries(['starred', musicFolder], { + active: true, + }); + }, + }) + } initialScrollOffset={Number(localStorage.getItem('scroll_list_starredMusicList'))} onScroll={(scrollIndex: number) => { localStorage.setItem('scroll_list_starredMusicList', String(Math.abs(scrollIndex))); @@ -355,7 +327,15 @@ const StarredView = () => { 'moveSelectedTo', 'deletePlaylist', ]} - handleFavorite={handleRowFavoriteAlbum} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { + custom: async () => { + await queryClient.refetchQueries(['starred', musicFolder], { + active: true, + }); + }, + }) + } initialScrollOffset={Number(localStorage.getItem('scroll_list_starredAlbumList'))} onScroll={(scrollIndex: number) => { localStorage.setItem( @@ -383,7 +363,15 @@ const StarredView = () => { playClick={{ type: 'album', idProperty: 'id' }} size={config.lookAndFeel.gridView.cardSize} cacheType="album" - handleFavorite={handleRowFavoriteAlbum} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { + custom: async () => { + await queryClient.refetchQueries(['starred', musicFolder], { + active: true, + }); + }, + }) + } initialScrollOffset={Number(localStorage.getItem('scroll_grid_starredAlbumList'))} onScroll={(scrollIndex: number) => { localStorage.setItem('scroll_grid_starredAlbumList', String(scrollIndex)); @@ -418,7 +406,15 @@ const StarredView = () => { 'addToPlaylist', 'deletePlaylist', ]} - handleFavorite={handleRowFavoriteArtist} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { + custom: async () => { + await queryClient.refetchQueries(['starred', musicFolder], { + active: true, + }); + }, + }) + } initialScrollOffset={Number( localStorage.getItem('scroll_list_starredArtistList') )} @@ -446,7 +442,15 @@ const StarredView = () => { playClick={{ type: 'artist', idProperty: 'id' }} size={config.lookAndFeel.gridView.cardSize} cacheType="artist" - handleFavorite={handleRowFavoriteArtist} + handleFavorite={(rowData: any) => + handleFavorite(rowData, { + custom: async () => { + await queryClient.refetchQueries(['starred', musicFolder], { + active: true, + }); + }, + }) + } initialScrollOffset={Number( localStorage.getItem('scroll_grid_starredArtistList') )} diff --git a/src/hooks/useFavorite.ts b/src/hooks/useFavorite.ts new file mode 100644 index 0000000..27cfe68 --- /dev/null +++ b/src/hooks/useFavorite.ts @@ -0,0 +1,75 @@ +import _ from 'lodash'; +import { useCallback } from 'react'; +import { useQueryClient } from 'react-query'; +import { useAppDispatch, useAppSelector } from '../redux/hooks'; +import { apiController } from '../api/controller'; +import { setStar } from '../redux/playQueueSlice'; +import { setPlaylistStar } from '../redux/playlistSlice'; + +const useFavorite = () => { + const dispatch = useAppDispatch(); + const config = useAppSelector((state) => state.config); + const queryClient = useQueryClient(); + + const handleFavorite = useCallback( + async (rowData, options?: { queryKey?: any; custom?: any }) => { + const favorite = !rowData.starred; + + await apiController({ + serverType: config.serverType, + endpoint: favorite ? 'star' : 'unstar', + args: { id: rowData.id, type: rowData.type }, + }); + + if (options?.queryKey) { + queryClient.setQueryData(options.queryKey, (oldData: any) => { + if (oldData?.data) { + const starredIndices = _.keys(_.pickBy(oldData.data, { id: rowData.id })); + starredIndices.forEach((index) => { + oldData.data[index].starred = favorite ? Date.now() : undefined; + }); + + return oldData; + } + + if (oldData?.album) { + const starredIndices = _.keys(_.pickBy(oldData.album, { id: rowData.id })); + starredIndices.forEach((index) => { + oldData.album[index].starred = favorite ? Date.now() : undefined; + }); + + return oldData; + } + + if (oldData?.song) { + const starredIndices = _.keys(_.pickBy(oldData.song, { id: rowData.id })); + starredIndices.forEach((index) => { + oldData.song[index].starred = favorite ? Date.now() : undefined; + }); + + return oldData; + } + + const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id })); + starredIndices.forEach((index) => { + oldData[index].starred = favorite ? Date.now() : undefined; + }); + + return oldData; + }); + } + + if (options?.custom) { + options.custom(); + } + + dispatch(setStar({ id: [rowData.id], type: favorite ? 'star' : 'unstar' })); + dispatch(setPlaylistStar({ id: [rowData.id], type: favorite ? 'star' : 'unstar' })); + }, + [config.serverType, dispatch, queryClient] + ); + + return { handleFavorite }; +}; + +export default useFavorite;