Browse Source

Add useFavorite hook, refactor components

master
jeffvli 3 years ago
parent
commit
3633e4a62c
  1. 104
      src/components/dashboard/Dashboard.tsx
  2. 41
      src/components/library/AlbumList.tsx
  3. 83
      src/components/library/AlbumView.tsx
  4. 41
      src/components/library/ArtistList.tsx
  5. 170
      src/components/library/ArtistView.tsx
  6. 51
      src/components/library/FolderList.tsx
  7. 41
      src/components/library/MusicList.tsx
  8. 51
      src/components/player/NowPlayingInfoView.tsx
  9. 22
      src/components/player/NowPlayingMiniView.tsx
  10. 22
      src/components/player/NowPlayingView.tsx
  11. 71
      src/components/player/PlayerBar.tsx
  12. 57
      src/components/playlist/PlaylistView.tsx
  13. 44
      src/components/search/SearchView.tsx
  14. 92
      src/components/starred/StarredView.tsx
  15. 75
      src/hooks/useFavorite.ts

104
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] })
}
/>
<ScrollingMenu
@ -239,7 +159,9 @@ const Dashboard = () => {
}, 50);
}}
type="album"
handleFavorite={handleFavorite}
handleFavorite={(rowData: any) =>
handleFavorite(rowData, { queryKey: ['newestAlbums', musicFolder.id] })
}
/>
<ScrollingMenu
@ -265,7 +187,9 @@ const Dashboard = () => {
}, 50);
}}
type="album"
handleFavorite={handleFavorite}
handleFavorite={(rowData: any) =>
handleFavorite(rowData, { queryKey: ['randomAlbums', musicFolder.id] })
}
/>
<ScrollingMenu
@ -291,7 +215,9 @@ const Dashboard = () => {
}, 50);
}}
type="music"
handleFavorite={handleFavorite}
handleFavorite={(rowData: any) =>
handleFavorite(rowData, { queryKey: ['frequentAlbums', musicFolder.id] })
}
/>
</>
)}

41
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));

83
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(),
}),
})
}
/>
<Whisper
trigger="hover"
@ -516,7 +477,7 @@ const AlbumView = ({ ...rest }: any) => {
'deletePlaylist',
'viewInModal',
]}
handleFavorite={handleRowFavorite}
handleFavorite={(rowData: any) => handleFavorite(rowData, { queryKey: ['album', id] })}
/>
</GenericPage>
</>

41
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));

170
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(),
}),
})
}
/>
<Whisper
trigger="hover"
@ -726,7 +622,7 @@ const ArtistView = ({ ...rest }: any) => {
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] })
}
/>
</StyledPanel>
)}
@ -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] })
}
/>
</StyledPanel>
)}
@ -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;
}
);
},
})
}
/>
</StyledPanel>
)}

51
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'),

41
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)));

51
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] })
}
/>
</InfoViewPanel>
@ -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;
}
);
},
})
}
/>
</InfoViewPanel>

22
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}
/>
</GenericPage>
</MiniViewContainer>

22
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

71
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,
});
},
});
}
}}
/>

57
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}
/>

44
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'),

92
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')
)}

75
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;
Loading…
Cancel
Save