From 15c6ef382a750b2a666d9ec600b1f09265f26f0e Mon Sep 17 00:00:00 2001 From: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Date: Mon, 8 Apr 2024 23:15:59 -0700 Subject: [PATCH] [bugfix]: fix combined title for artist, favoriting on grid pages --- .../virtual-grid/virtual-infinite-grid.tsx | 4 ++ .../cells/combined-title-cell.tsx | 2 +- .../components/album-list-grid-view.tsx | 30 +--------- .../album-artist-list-grid-view.tsx | 3 + .../components/playlist-list-grid-view.tsx | 31 +--------- .../shared/hooks/use-handle-favorite.ts | 56 +++++++++++++++++++ .../songs/components/song-list-grid-view.tsx | 30 +--------- 7 files changed, 70 insertions(+), 86 deletions(-) create mode 100644 src/renderer/features/shared/hooks/use-handle-favorite.ts diff --git a/src/renderer/components/virtual-grid/virtual-infinite-grid.tsx b/src/renderer/components/virtual-grid/virtual-infinite-grid.tsx index e313d942..c4ffe5d9 100644 --- a/src/renderer/components/virtual-grid/virtual-infinite-grid.tsx +++ b/src/renderer/components/virtual-grid/virtual-infinite-grid.tsx @@ -19,6 +19,7 @@ export type VirtualInfiniteGridRef = { resetLoadMoreItemsCache: () => void; scrollTo: (index: number) => void; setItemData: (data: any[]) => void; + updateItemData: (rule: (item: any) => any) => void; }; interface VirtualGridProps @@ -135,6 +136,9 @@ export const VirtualInfiniteGrid = forwardRef( setItemData: (data: any[]) => { setItemData(data); }, + updateItemData: (rule) => { + setItemData((data) => data.map(rule)); + }, })); if (loading) return null; diff --git a/src/renderer/components/virtual-table/cells/combined-title-cell.tsx b/src/renderer/components/virtual-table/cells/combined-title-cell.tsx index d8761576..1eb0b203 100644 --- a/src/renderer/components/virtual-table/cells/combined-title-cell.tsx +++ b/src/renderer/components/virtual-table/cells/combined-title-cell.tsx @@ -50,7 +50,7 @@ const StyledImage = styled(SimpleImg)` export const CombinedTitleCell = ({ value, rowIndex, node }: ICellRendererParams) => { const artists = useMemo(() => { if (!value) return null; - return value.artists.length ? value.artists : value.albumArtists; + return value.artists?.length ? value.artists : value.albumArtists; }, [value]); if (value === undefined) { diff --git a/src/renderer/features/albums/components/album-list-grid-view.tsx b/src/renderer/features/albums/components/album-list-grid-view.tsx index 05fe3908..86bbe461 100644 --- a/src/renderer/features/albums/components/album-list-grid-view.tsx +++ b/src/renderer/features/albums/components/album-list-grid-view.tsx @@ -19,10 +19,10 @@ import { } from '/@/renderer/components/virtual-grid'; import { useListContext } from '/@/renderer/context/list-context'; import { usePlayQueueAdd } from '/@/renderer/features/player'; -import { useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared'; import { AppRoute } from '/@/renderer/router/routes'; import { useCurrentServer, useListStoreActions, useListStoreByKey } from '/@/renderer/store'; import { CardRow, ListDisplayType } from '/@/renderer/types'; +import { useHandleFavorite } from '/@/renderer/features/shared/hooks/use-handle-favorite'; export const AlbumListGridView = ({ gridRef, itemCount }: any) => { const queryClient = useQueryClient(); @@ -36,33 +36,7 @@ export const AlbumListGridView = ({ gridRef, itemCount }: any) => { const scrollOffset = searchParams.get('scrollOffset'); const initialScrollOffset = Number(id ? scrollOffset : grid?.scrollOffset) || 0; - const createFavoriteMutation = useCreateFavorite({}); - const deleteFavoriteMutation = useDeleteFavorite({}); - - const handleFavorite = (options: { - id: string[]; - isFavorite: boolean; - itemType: LibraryItem; - }) => { - const { id, itemType, isFavorite } = options; - if (isFavorite) { - deleteFavoriteMutation.mutate({ - query: { - id, - type: itemType, - }, - serverId: server?.id, - }); - } else { - createFavoriteMutation.mutate({ - query: { - id, - type: itemType, - }, - serverId: server?.id, - }); - } - }; + const handleFavorite = useHandleFavorite({ gridRef, server }); const cardRows = useMemo(() => { const rows: CardRow[] = [ALBUM_CARD_ROWS.name]; diff --git a/src/renderer/features/artists/components/album-artist-list-grid-view.tsx b/src/renderer/features/artists/components/album-artist-list-grid-view.tsx index d9887684..95ddcfe5 100644 --- a/src/renderer/features/artists/components/album-artist-list-grid-view.tsx +++ b/src/renderer/features/artists/components/album-artist-list-grid-view.tsx @@ -20,6 +20,7 @@ import { usePlayQueueAdd } from '/@/renderer/features/player'; import { AppRoute } from '/@/renderer/router/routes'; import { useCurrentServer, useListStoreActions } from '/@/renderer/store'; import { CardRow, ListDisplayType } from '/@/renderer/types'; +import { useHandleFavorite } from '/@/renderer/features/shared/hooks/use-handle-favorite'; interface AlbumArtistListGridViewProps { gridRef: MutableRefObject; @@ -34,6 +35,7 @@ export const AlbumArtistListGridView = ({ itemCount, gridRef }: AlbumArtistListG const { pageKey } = useListContext(); const { grid, display, filter } = useListStoreByKey({ key: pageKey }); const { setGrid } = useListStoreActions(); + const handleFavorite = useHandleFavorite({ gridRef, server }); const fetchInitialData = useCallback(() => { const query: Omit = { @@ -154,6 +156,7 @@ export const AlbumArtistListGridView = ({ itemCount, gridRef }: AlbumArtistListG display={display || ListDisplayType.CARD} fetchFn={fetch} fetchInitialData={fetchInitialData} + handleFavorite={handleFavorite} handlePlayQueueAdd={handlePlayQueueAdd} height={height} initialScrollOffset={grid?.scrollOffset || 0} diff --git a/src/renderer/features/playlists/components/playlist-list-grid-view.tsx b/src/renderer/features/playlists/components/playlist-list-grid-view.tsx index 14abc68e..cd8ee5b1 100644 --- a/src/renderer/features/playlists/components/playlist-list-grid-view.tsx +++ b/src/renderer/features/playlists/components/playlist-list-grid-view.tsx @@ -20,10 +20,10 @@ import { VirtualInfiniteGridRef, } from '/@/renderer/components/virtual-grid'; import { usePlayQueueAdd } from '/@/renderer/features/player'; -import { useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared'; import { AppRoute } from '/@/renderer/router/routes'; import { useCurrentServer, useGeneralSettings, useListStoreByKey } from '/@/renderer/store'; import { CardRow, ListDisplayType } from '/@/renderer/types'; +import { useHandleFavorite } from '/@/renderer/features/shared/hooks/use-handle-favorite'; interface PlaylistListGridViewProps { gridRef: MutableRefObject; @@ -38,34 +38,7 @@ export const PlaylistListGridView = ({ gridRef, itemCount }: PlaylistListGridVie const { display, grid, filter } = useListStoreByKey({ key: pageKey }); const { setGrid } = useListStoreActions(); const { defaultFullPlaylist } = useGeneralSettings(); - - const createFavoriteMutation = useCreateFavorite({}); - const deleteFavoriteMutation = useDeleteFavorite({}); - - const handleFavorite = (options: { - id: string[]; - isFavorite: boolean; - itemType: LibraryItem; - }) => { - const { id, itemType, isFavorite } = options; - if (isFavorite) { - deleteFavoriteMutation.mutate({ - query: { - id, - type: itemType, - }, - serverId: server?.id, - }); - } else { - createFavoriteMutation.mutate({ - query: { - id, - type: itemType, - }, - serverId: server?.id, - }); - } - }; + const handleFavorite = useHandleFavorite({ gridRef, server }); const cardRows = useMemo(() => { const rows: CardRow[] = defaultFullPlaylist diff --git a/src/renderer/features/shared/hooks/use-handle-favorite.ts b/src/renderer/features/shared/hooks/use-handle-favorite.ts new file mode 100644 index 00000000..ecdc1a36 --- /dev/null +++ b/src/renderer/features/shared/hooks/use-handle-favorite.ts @@ -0,0 +1,56 @@ +import { MutableRefObject, useCallback } from 'react'; +import { LibraryItem } from '/@/renderer/api/types'; +import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid'; +import { useCreateFavorite } from '/@/renderer/features/shared/mutations/create-favorite-mutation'; +import { useDeleteFavorite } from '/@/renderer/features/shared/mutations/delete-favorite-mutation'; +import { ServerListItem } from '/@/renderer/types'; + +interface HandleFavoriteProps { + gridRef: MutableRefObject; + server: ServerListItem | null; +} + +export const useHandleFavorite = ({ gridRef, server }: HandleFavoriteProps) => { + const createFavoriteMutation = useCreateFavorite({}); + const deleteFavoriteMutation = useDeleteFavorite({}); + + const handleFavorite = useCallback( + async (options: { id: string[]; isFavorite: boolean; itemType: LibraryItem }) => { + const { id, itemType, isFavorite } = options; + try { + if (isFavorite) { + await deleteFavoriteMutation.mutateAsync({ + query: { + id, + type: itemType, + }, + serverId: server?.id, + }); + } else { + await createFavoriteMutation.mutateAsync({ + query: { + id, + type: itemType, + }, + serverId: server?.id, + }); + } + + const idSet = new Set(id); + gridRef.current?.updateItemData((data) => + idSet.has(data.id) + ? { + ...data, + userFavorite: !isFavorite, + } + : data, + ); + } catch (error) { + console.error(error); + } + }, + [createFavoriteMutation, deleteFavoriteMutation, gridRef, server?.id], + ); + + return handleFavorite; +}; diff --git a/src/renderer/features/songs/components/song-list-grid-view.tsx b/src/renderer/features/songs/components/song-list-grid-view.tsx index fae30bb1..30928a4d 100644 --- a/src/renderer/features/songs/components/song-list-grid-view.tsx +++ b/src/renderer/features/songs/components/song-list-grid-view.tsx @@ -19,10 +19,10 @@ import { } from '/@/renderer/components/virtual-grid'; import { useListContext } from '/@/renderer/context/list-context'; import { usePlayQueueAdd } from '/@/renderer/features/player'; -import { useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared'; import { AppRoute } from '/@/renderer/router/routes'; import { useCurrentServer, useListStoreActions, useListStoreByKey } from '/@/renderer/store'; import { CardRow, ListDisplayType } from '/@/renderer/types'; +import { useHandleFavorite } from '/@/renderer/features/shared/hooks/use-handle-favorite'; export const SongListGridView = ({ gridRef, itemCount }: any) => { const queryClient = useQueryClient(); @@ -36,33 +36,7 @@ export const SongListGridView = ({ gridRef, itemCount }: any) => { const scrollOffset = searchParams.get('scrollOffset'); const initialScrollOffset = Number(id ? scrollOffset : grid?.scrollOffset) || 0; - const createFavoriteMutation = useCreateFavorite({}); - const deleteFavoriteMutation = useDeleteFavorite({}); - - const handleFavorite = (options: { - id: string[]; - isFavorite: boolean; - itemType: LibraryItem; - }) => { - const { id, itemType, isFavorite } = options; - if (isFavorite) { - deleteFavoriteMutation.mutate({ - query: { - id, - type: itemType, - }, - serverId: server?.id, - }); - } else { - createFavoriteMutation.mutate({ - query: { - id, - type: itemType, - }, - serverId: server?.id, - }); - } - }; + const handleFavorite = useHandleFavorite({ gridRef, server }); const cardRows = useMemo(() => { const rows: CardRow[] = [