From 6cd27c3e8830abc457a4088ba6a5f755e1c7c8f1 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 19 Jul 2023 20:04:56 -0700 Subject: [PATCH] Update song list implementation --- .../components/jellyfin-song-filters.tsx | 31 +++-- .../components/navidrome-song-filters.tsx | 28 +++-- .../songs/components/song-list-content.tsx | 8 +- .../components/song-list-header-filters.tsx | 119 +++++++----------- .../songs/components/song-list-header.tsx | 83 ++++-------- .../songs/components/song-list-table-view.tsx | 64 ++-------- .../songs/context/song-list-context.tsx | 18 --- .../features/songs/routes/song-list-route.tsx | 25 ++-- 8 files changed, 131 insertions(+), 245 deletions(-) delete mode 100644 src/renderer/features/songs/context/song-list-context.tsx diff --git a/src/renderer/features/songs/components/jellyfin-song-filters.tsx b/src/renderer/features/songs/components/jellyfin-song-filters.tsx index f0f3e0dd..16ee6055 100644 --- a/src/renderer/features/songs/components/jellyfin-song-filters.tsx +++ b/src/renderer/features/songs/components/jellyfin-song-filters.tsx @@ -1,26 +1,27 @@ -import { ChangeEvent, useMemo } from 'react'; import { Divider, Group, Stack } from '@mantine/core'; -import { MultiSelect, NumberInput, Switch, Text } from '/@/renderer/components'; -import { SongListFilter, useListStoreActions, useSongListFilter } from '/@/renderer/store'; import debounce from 'lodash/debounce'; -import { useGenreList } from '/@/renderer/features/genres'; +import { ChangeEvent, useMemo } from 'react'; +import { useListFilterByKey } from '../../../store/list.store'; import { LibraryItem } from '/@/renderer/api/types'; +import { MultiSelect, NumberInput, Switch, Text } from '/@/renderer/components'; +import { useGenreList } from '/@/renderer/features/genres'; +import { SongListFilter, useListStoreActions } from '/@/renderer/store'; interface JellyfinSongFiltersProps { - handleFilterChange: (filters: SongListFilter) => void; - id?: string; + customFilters?: Partial; + onFilterChange: (filters: SongListFilter) => void; pageKey: string; serverId?: string; } export const JellyfinSongFilters = ({ - id, + customFilters, pageKey, - handleFilterChange, + onFilterChange, serverId, }: JellyfinSongFiltersProps) => { const { setFilter } = useListStoreActions(); - const filter = useSongListFilter({ id, key: pageKey }); + const { filter } = useListFilterByKey({ key: pageKey }); // TODO - eventually replace with /items/filters endpoint to fetch genres and tags specific to the selected library const genreListQuery = useGenreList({ query: null, serverId }); @@ -42,6 +43,7 @@ export const JellyfinSongFilters = ({ label: 'Is favorited', onChange: (e: ChangeEvent) => { const updatedFilters = setFilter({ + customFilters, data: { _custom: { ...filter._custom, @@ -55,7 +57,7 @@ export const JellyfinSongFilters = ({ itemType: LibraryItem.SONG, key: pageKey, }) as SongListFilter; - handleFilterChange(updatedFilters); + onFilterChange(updatedFilters); }, value: filter._custom?.jellyfin?.IsFavorite, }, @@ -64,6 +66,7 @@ export const JellyfinSongFilters = ({ const handleMinYearFilter = debounce((e: number | string) => { if (typeof e === 'number' && (e < 1700 || e > 2300)) return; const updatedFilters = setFilter({ + customFilters, data: { _custom: { ...filter._custom, @@ -77,12 +80,13 @@ export const JellyfinSongFilters = ({ itemType: LibraryItem.SONG, key: pageKey, }) as SongListFilter; - handleFilterChange(updatedFilters); + onFilterChange(updatedFilters); }, 500); const handleMaxYearFilter = debounce((e: number | string) => { if (typeof e === 'number' && (e < 1700 || e > 2300)) return; const updatedFilters = setFilter({ + customFilters, data: { _custom: { ...filter._custom, @@ -96,12 +100,13 @@ export const JellyfinSongFilters = ({ itemType: LibraryItem.SONG, key: pageKey, }) as SongListFilter; - handleFilterChange(updatedFilters); + onFilterChange(updatedFilters); }, 500); const handleGenresFilter = debounce((e: string[] | undefined) => { const genreFilterString = e?.length ? e.join(',') : undefined; const updatedFilters = setFilter({ + customFilters, data: { _custom: { ...filter._custom, @@ -115,7 +120,7 @@ export const JellyfinSongFilters = ({ itemType: LibraryItem.SONG, key: pageKey, }) as SongListFilter; - handleFilterChange(updatedFilters); + onFilterChange(updatedFilters); }, 250); return ( diff --git a/src/renderer/features/songs/components/navidrome-song-filters.tsx b/src/renderer/features/songs/components/navidrome-song-filters.tsx index 5dd83649..e62591fb 100644 --- a/src/renderer/features/songs/components/navidrome-song-filters.tsx +++ b/src/renderer/features/songs/components/navidrome-song-filters.tsx @@ -1,26 +1,26 @@ -import { ChangeEvent, useMemo } from 'react'; import { Divider, Group, Stack } from '@mantine/core'; -import { NumberInput, Select, Switch, Text } from '/@/renderer/components'; -import { SongListFilter, useListStoreActions, useSongListFilter } from '/@/renderer/store'; import debounce from 'lodash/debounce'; -import { useGenreList } from '/@/renderer/features/genres'; +import { ChangeEvent, useMemo } from 'react'; import { LibraryItem } from '/@/renderer/api/types'; +import { NumberInput, Select, Switch, Text } from '/@/renderer/components'; +import { useGenreList } from '/@/renderer/features/genres'; +import { SongListFilter, useListFilterByKey, useListStoreActions } from '/@/renderer/store'; interface NavidromeSongFiltersProps { - handleFilterChange: (filters: SongListFilter) => void; - id?: string; + customFilters?: Partial; + onFilterChange: (filters: SongListFilter) => void; pageKey: string; serverId?: string; } export const NavidromeSongFilters = ({ - handleFilterChange, + customFilters, + onFilterChange, pageKey, - id, serverId, }: NavidromeSongFiltersProps) => { const { setFilter } = useListStoreActions(); - const filter = useSongListFilter({ id, key: pageKey }); + const filter = useListFilterByKey({ key: pageKey }); const genreListQuery = useGenreList({ query: null, serverId }); @@ -34,6 +34,7 @@ export const NavidromeSongFilters = ({ const handleGenresFilter = debounce((e: string | null) => { const updatedFilters = setFilter({ + customFilters, data: { _custom: { ...filter._custom, @@ -45,7 +46,8 @@ export const NavidromeSongFilters = ({ itemType: LibraryItem.SONG, key: pageKey, }) as SongListFilter; - handleFilterChange(updatedFilters); + + onFilterChange(updatedFilters); }, 250); const toggleFilters = [ @@ -53,6 +55,7 @@ export const NavidromeSongFilters = ({ label: 'Is favorited', onChange: (e: ChangeEvent) => { const updatedFilters = setFilter({ + customFilters, data: { _custom: { ...filter._custom, @@ -65,7 +68,7 @@ export const NavidromeSongFilters = ({ key: pageKey, }) as SongListFilter; - handleFilterChange(updatedFilters); + onFilterChange(updatedFilters); }, value: filter._custom?.navidrome?.starred, }, @@ -73,6 +76,7 @@ export const NavidromeSongFilters = ({ const handleYearFilter = debounce((e: number | string) => { const updatedFilters = setFilter({ + customFilters, data: { _custom: { ...filter._custom, @@ -85,7 +89,7 @@ export const NavidromeSongFilters = ({ key: pageKey, }) as SongListFilter; - handleFilterChange(updatedFilters); + onFilterChange(updatedFilters); }, 500); return ( diff --git a/src/renderer/features/songs/components/song-list-content.tsx b/src/renderer/features/songs/components/song-list-content.tsx index f6de2f9e..30f1dc74 100644 --- a/src/renderer/features/songs/components/song-list-content.tsx +++ b/src/renderer/features/songs/components/song-list-content.tsx @@ -1,8 +1,8 @@ import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import { lazy, MutableRefObject, Suspense } from 'react'; import { Spinner } from '/@/renderer/components'; -import { useSongListContext } from '/@/renderer/features/songs/context/song-list-context'; -import { useSongListStore } from '/@/renderer/store'; +import { useListContext } from '/@/renderer/context/list-context'; +import { useListStoreByKey } from '/@/renderer/store'; import { ListDisplayType } from '/@/renderer/types'; const SongListTableView = lazy(() => @@ -17,8 +17,8 @@ interface SongListContentProps { } export const SongListContent = ({ itemCount, tableRef }: SongListContentProps) => { - const { id, pageKey } = useSongListContext(); - const { display } = useSongListStore({ id, key: pageKey }); + const { pageKey } = useListContext(); + const { display } = useListStoreByKey({ key: pageKey }); const isGrid = display === ListDisplayType.CARD || display === ListDisplayType.POSTER; diff --git a/src/renderer/features/songs/components/song-list-header-filters.tsx b/src/renderer/features/songs/components/song-list-header-filters.tsx index b2623f9a..a24ad6f5 100644 --- a/src/renderer/features/songs/components/song-list-header-filters.tsx +++ b/src/renderer/features/songs/components/song-list-header-filters.tsx @@ -1,37 +1,31 @@ -import { useCallback, useMemo, ChangeEvent, MutableRefObject, MouseEvent } from 'react'; -import { IDatasource } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import { Divider, Flex, Group, Stack } from '@mantine/core'; import { openModal } from '@mantine/modals'; +import { ChangeEvent, MouseEvent, MutableRefObject, useCallback, useMemo } from 'react'; import { - RiFolder2Line, - RiMoreFill, - RiSettings3Fill, - RiPlayFill, RiAddBoxFill, RiAddCircleFill, - RiRefreshLine, RiFilterFill, + RiFolder2Line, + RiMoreFill, + RiPlayFill, + RiRefreshLine, + RiSettings3Fill, } from 'react-icons/ri'; -import { api } from '/@/renderer/api'; +import { useListStoreByKey } from '../../../store/list.store'; import { queryKeys } from '/@/renderer/api/query-keys'; -import { LibraryItem, SongListQuery, SongListSort, SortOrder } from '/@/renderer/api/types'; -import { DropdownMenu, Button, Slider, MultiSelect, Switch, Text } from '/@/renderer/components'; +import { LibraryItem, SongListSort, SortOrder } from '/@/renderer/api/types'; +import { Button, DropdownMenu, MultiSelect, Slider, Switch, Text } from '/@/renderer/components'; +import { SONG_TABLE_COLUMNS } from '/@/renderer/components/virtual-table'; +import { useListContext } from '/@/renderer/context/list-context'; import { OrderToggleButton, useMusicFolders } from '/@/renderer/features/shared'; import { JellyfinSongFilters } from '/@/renderer/features/songs/components/jellyfin-song-filters'; import { NavidromeSongFilters } from '/@/renderer/features/songs/components/navidrome-song-filters'; import { useContainerQuery } from '/@/renderer/hooks'; +import { useListFilterRefresh } from '/@/renderer/hooks/use-list-filter-refresh'; import { queryClient } from '/@/renderer/lib/react-query'; -import { - SongListFilter, - useCurrentServer, - useListStoreActions, - useSongListFilter, - useSongListStore, -} from '/@/renderer/store'; -import { ListDisplayType, ServerType, Play, TableColumn } from '/@/renderer/types'; -import { useSongListContext } from '/@/renderer/features/songs/context/song-list-context'; -import { SONG_TABLE_COLUMNS } from '/@/renderer/components/virtual-table'; +import { SongListFilter, useCurrentServer, useListStoreActions } from '/@/renderer/store'; +import { ListDisplayType, Play, ServerType, TableColumn } from '/@/renderer/types'; const FILTERS = { jellyfin: [ @@ -83,10 +77,14 @@ interface SongListHeaderFiltersProps { export const SongListHeaderFilters = ({ tableRef }: SongListHeaderFiltersProps) => { const server = useCurrentServer(); - const { id, pageKey, handlePlay } = useSongListContext(); - const { display, table } = useSongListStore({ id, key: pageKey }); + const { pageKey, handlePlay, customFilters } = useListContext(); + const { display, table, filter } = useListStoreByKey({ key: pageKey }); const { setFilter, setTable, setTablePagination, setDisplayType } = useListStoreActions(); - const filter = useSongListFilter({ id, key: pageKey }); + + const { handleRefreshTable } = useListFilterRefresh({ + itemType: LibraryItem.SONG, + server, + }); const cq = useContainerQuery(); @@ -99,48 +97,6 @@ export const SongListHeaderFilters = ({ tableRef }: SongListHeaderFiltersProps) ).find((f) => f.value === filter.sortBy)?.name) || 'Unknown'; - const handleFilterChange = useCallback( - async (filters?: SongListFilter) => { - const dataSource: IDatasource = { - getRows: async (params) => { - const limit = params.endRow - params.startRow; - const startIndex = params.startRow; - - const pageFilters = filters || filter; - - const query: SongListQuery = { - limit, - startIndex, - ...pageFilters, - }; - - const queryKey = queryKeys.songs.list(server?.id || '', query); - - const songsRes = await queryClient.fetchQuery( - queryKey, - async ({ signal }) => - api.controller.getSongList({ - apiClientProps: { - server, - signal, - }, - query, - }), - { cacheTime: 1000 * 60 * 1 }, - ); - - params.successCallback(songsRes?.items || [], songsRes?.totalRecordCount || 0); - }, - rowCount: undefined, - }; - tableRef.current?.api.setDatasource(dataSource); - tableRef.current?.api.purgeInfiniteCache(); - tableRef.current?.api.ensureIndexVisible(0, 'top'); - setTablePagination({ data: { currentPage: 0 }, key: pageKey }); - }, - [filter, pageKey, server, setTablePagination, tableRef], - ); - const handleSetSortBy = useCallback( (e: MouseEvent) => { if (!e.currentTarget?.value || !server?.type) return; @@ -150,6 +106,7 @@ export const SongListHeaderFilters = ({ tableRef }: SongListHeaderFiltersProps) )?.defaultOrder; const updatedFilters = setFilter({ + customFilters, data: { sortBy: e.currentTarget.value as SongListSort, sortOrder: sortOrder || SortOrder.ASC, @@ -158,9 +115,9 @@ export const SongListHeaderFilters = ({ tableRef }: SongListHeaderFiltersProps) key: pageKey, }) as SongListFilter; - handleFilterChange(updatedFilters); + handleRefreshTable(tableRef, updatedFilters); }, - [handleFilterChange, pageKey, server?.type, setFilter], + [customFilters, handleRefreshTable, pageKey, server?.type, setFilter, tableRef], ); const handleSetMusicFolder = useCallback( @@ -170,32 +127,35 @@ export const SongListHeaderFilters = ({ tableRef }: SongListHeaderFiltersProps) let updatedFilters = null; if (e.currentTarget.value === String(filter.musicFolderId)) { updatedFilters = setFilter({ + customFilters, data: { musicFolderId: undefined }, itemType: LibraryItem.SONG, key: pageKey, }) as SongListFilter; } else { updatedFilters = setFilter({ + customFilters, data: { musicFolderId: e.currentTarget.value }, itemType: LibraryItem.SONG, key: pageKey, }) as SongListFilter; } - handleFilterChange(updatedFilters); + handleRefreshTable(tableRef, updatedFilters); }, - [filter.musicFolderId, handleFilterChange, setFilter, pageKey], + [filter.musicFolderId, handleRefreshTable, tableRef, setFilter, customFilters, pageKey], ); const handleToggleSortOrder = useCallback(() => { const newSortOrder = filter.sortOrder === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC; const updatedFilters = setFilter({ + customFilters, data: { sortOrder: newSortOrder }, itemType: LibraryItem.SONG, key: pageKey, }) as SongListFilter; - handleFilterChange(updatedFilters); - }, [filter.sortOrder, handleFilterChange, pageKey, setFilter]); + handleRefreshTable(tableRef, updatedFilters); + }, [customFilters, filter.sortOrder, handleRefreshTable, pageKey, setFilter, tableRef]); const handleSetViewType = useCallback( (e: MouseEvent) => { @@ -258,7 +218,14 @@ export const SongListHeaderFilters = ({ tableRef }: SongListHeaderFiltersProps) const handleRefresh = () => { queryClient.invalidateQueries(queryKeys.songs.list(server?.id || '')); - handleFilterChange(filter); + handleRefreshTable(tableRef, filter); + }; + + const onFilterChange = (filter: SongListFilter) => { + handleRefreshTable(tableRef, { + ...filter, + ...customFilters, + }); }; const handleOpenFiltersModal = () => { @@ -267,15 +234,15 @@ export const SongListHeaderFilters = ({ tableRef }: SongListHeaderFiltersProps) <> {server?.type === ServerType.NAVIDROME ? ( ) : ( )} diff --git a/src/renderer/features/songs/components/song-list-header.tsx b/src/renderer/features/songs/components/song-list-header.tsx index 963979f4..5e691d4f 100644 --- a/src/renderer/features/songs/components/song-list-header.tsx +++ b/src/renderer/features/songs/components/song-list-header.tsx @@ -1,24 +1,18 @@ -import type { IDatasource } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import { Flex, Group, Stack } from '@mantine/core'; import debounce from 'lodash/debounce'; -import { ChangeEvent, MutableRefObject, useCallback } from 'react'; -import { api } from '/@/renderer/api'; -import { queryKeys } from '/@/renderer/api/query-keys'; -import { LibraryItem, SongListQuery } from '/@/renderer/api/types'; +import { ChangeEvent, MutableRefObject } from 'react'; +import { useListStoreByKey } from '../../../store/list.store'; +import { LibraryItem } from '/@/renderer/api/types'; import { PageHeader, SearchInput } from '/@/renderer/components'; +import { useListContext } from '/@/renderer/context/list-context'; import { FilterBar, LibraryHeaderBar } from '/@/renderer/features/shared'; import { SongListHeaderFilters } from '/@/renderer/features/songs/components/song-list-header-filters'; -import { useSongListContext } from '/@/renderer/features/songs/context/song-list-context'; import { useContainerQuery } from '/@/renderer/hooks'; -import { queryClient } from '/@/renderer/lib/react-query'; -import { - SongListFilter, - useCurrentServer, - useListStoreActions, - useSongListFilter, -} from '/@/renderer/store'; +import { useListFilterRefresh } from '/@/renderer/hooks/use-list-filter-refresh'; +import { SongListFilter, useCurrentServer, useListStoreActions } from '/@/renderer/store'; import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; +import { ListDisplayType } from '/@/renderer/types'; interface SongListHeaderProps { itemCount?: number; @@ -28,62 +22,35 @@ interface SongListHeaderProps { export const SongListHeader = ({ title, itemCount, tableRef }: SongListHeaderProps) => { const server = useCurrentServer(); - const { id, pageKey, handlePlay } = useSongListContext(); - const filter = useSongListFilter({ id, key: pageKey }); + const { pageKey, handlePlay, customFilters } = useListContext(); const { setFilter, setTablePagination } = useListStoreActions(); + const { display, filter } = useListStoreByKey({ key: pageKey }); const cq = useContainerQuery(); - const handleFilterChange = useCallback( - async (filters?: SongListFilter) => { - const dataSource: IDatasource = { - getRows: async (params) => { - const limit = params.endRow - params.startRow; - const startIndex = params.startRow; - - const pageFilters = filters || filter; - - const query: SongListQuery = { - limit, - startIndex, - ...pageFilters, - }; - - const queryKey = queryKeys.songs.list(server?.id || '', query); - - const songsRes = await queryClient.fetchQuery( - queryKey, - async ({ signal }) => - api.controller.getSongList({ - apiClientProps: { - server, - signal, - }, - query, - }), - { cacheTime: 1000 * 60 * 1 }, - ); - - params.successCallback(songsRes?.items || [], songsRes?.totalRecordCount || 0); - }, - rowCount: undefined, - }; - tableRef.current?.api.setDatasource(dataSource); - tableRef.current?.api.purgeInfiniteCache(); - tableRef.current?.api.ensureIndexVisible(0, 'top'); - setTablePagination({ data: { currentPage: 0 }, key: pageKey }); - }, - [filter, pageKey, server, setTablePagination, tableRef], - ); + const { handleRefreshTable } = useListFilterRefresh({ + itemType: LibraryItem.SONG, + server, + }); const handleSearch = debounce((e: ChangeEvent) => { - const previousSearchTerm = filter.searchTerm; const searchTerm = e.target.value === '' ? undefined : e.target.value; const updatedFilters = setFilter({ data: { searchTerm }, itemType: LibraryItem.SONG, key: pageKey, }) as SongListFilter; - if (previousSearchTerm !== searchTerm) handleFilterChange(updatedFilters); + + const filterWithCustom = { + ...updatedFilters, + ...customFilters, + }; + + if (display === ListDisplayType.TABLE || display === ListDisplayType.TABLE_PAGINATED) { + handleRefreshTable(tableRef, filterWithCustom); + setTablePagination({ data: { currentPage: 0 }, key: pageKey }); + } else { + // handleRefreshGrid(gridRef, filterWithCustom); + } }, 500); const playButtonBehavior = usePlayButtonBehavior(); diff --git a/src/renderer/features/songs/components/song-list-table-view.tsx b/src/renderer/features/songs/components/song-list-table-view.tsx index ffd292ca..f23ed4eb 100644 --- a/src/renderer/features/songs/components/song-list-table-view.tsx +++ b/src/renderer/features/songs/components/song-list-table-view.tsx @@ -1,25 +1,14 @@ import { RowDoubleClickedEvent } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; -import { MutableRefObject, useCallback } from 'react'; -import { api } from '/@/renderer/api'; -import { queryKeys } from '/@/renderer/api/query-keys'; -import { LibraryItem, QueueSong, SongListQuery, SongListResponse } from '/@/renderer/api/types'; +import { MutableRefObject } from 'react'; +import { LibraryItem, QueueSong, SongListQuery } from '/@/renderer/api/types'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; import { VirtualTable } from '/@/renderer/components/virtual-table'; import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; -import { - AgGridFetchFn, - useVirtualTable, -} from '/@/renderer/components/virtual-table/hooks/use-virtual-table'; +import { useVirtualTable } from '/@/renderer/components/virtual-table/hooks/use-virtual-table'; +import { useListContext } from '/@/renderer/context/list-context'; import { SONG_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items'; -import { useSongListContext } from '/@/renderer/features/songs/context/song-list-context'; -import { - useCurrentServer, - useListStoreActions, - usePlayButtonBehavior, - useSongListFilter, - useSongListStore, -} from '/@/renderer/store'; +import { useCurrentServer, usePlayButtonBehavior } from '/@/renderer/store'; interface SongListTableViewProps { itemCount?: number; @@ -28,50 +17,17 @@ interface SongListTableViewProps { export const SongListTableView = ({ tableRef, itemCount }: SongListTableViewProps) => { const server = useCurrentServer(); - const { id, pageKey, handlePlay } = useSongListContext(); - const filter = useSongListFilter({ id, key: pageKey }); - const listProperties = useSongListStore({ id, key: pageKey }); - - const { setTable, setTablePagination } = useListStoreActions(); - - const fetchFn: AgGridFetchFn> = useCallback( - async ({ filter, limit, startIndex }, signal) => { - const res = api.controller.getSongList({ - apiClientProps: { - server, - signal, - }, - query: { - ...filter, - limit, - sortBy: filter.sortBy, - sortOrder: filter.sortOrder, - startIndex, - }, - }); - - return res; - }, - [server], - ); + const { pageKey, handlePlay, customFilters } = useListContext(); const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); - const tableProps = useVirtualTable>({ + const tableProps = useVirtualTable({ contextMenu: SONG_CONTEXT_MENU_ITEMS, - fetch: { - filter, - fn: fetchFn, - itemCount, - queryKey: queryKeys.albums.list, - server, - }, + customFilters, itemCount, itemType: LibraryItem.SONG, pageKey, - properties: listProperties, - setTable, - setTablePagination, + server, tableRef, }); @@ -86,7 +42,7 @@ export const SongListTableView = ({ tableRef, itemCount }: SongListTableViewProp void; - id?: string; - pageKey: ListKey; -} - -export const SongListContext = createContext({ - pageKey: 'song', -}); - -export const useSongListContext = () => { - const ctxValue = useContext(SongListContext); - return ctxValue; -}; diff --git a/src/renderer/features/songs/routes/song-list-route.tsx b/src/renderer/features/songs/routes/song-list-route.tsx index 906d6984..9192b51c 100644 --- a/src/renderer/features/songs/routes/song-list-route.tsx +++ b/src/renderer/features/songs/routes/song-list-route.tsx @@ -1,14 +1,14 @@ import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import { useCallback, useRef } from 'react'; import { useParams, useSearchParams } from 'react-router-dom'; -import { SongListQuery, LibraryItem } from '/@/renderer/api/types'; +import { LibraryItem, SongListQuery } from '/@/renderer/api/types'; +import { ListContext } from '/@/renderer/context/list-context'; import { usePlayQueueAdd } from '/@/renderer/features/player'; import { AnimatedPage } from '/@/renderer/features/shared'; import { SongListContent } from '/@/renderer/features/songs/components/song-list-content'; import { SongListHeader } from '/@/renderer/features/songs/components/song-list-header'; -import { SongListContext } from '/@/renderer/features/songs/context/song-list-context'; import { useSongList } from '/@/renderer/features/songs/queries/song-list-query'; -import { generatePageKey, useCurrentServer, useSongListFilter } from '/@/renderer/store'; +import { useCurrentServer, useListFilterByKey } from '/@/renderer/store'; import { Play } from '/@/renderer/types'; const TrackListRoute = () => { @@ -16,13 +16,18 @@ const TrackListRoute = () => { const server = useCurrentServer(); const [searchParams] = useSearchParams(); const { albumArtistId } = useParams(); - const pageKey = generatePageKey( - 'song', - albumArtistId ? `${albumArtistId}_${server?.id}` : undefined, - ); + const pageKey = albumArtistId ? `albumArtistSong` : 'song'; + + const customFilters = { + ...(albumArtistId && { artistIds: [albumArtistId] }), + }; const handlePlayQueueAdd = usePlayQueueAdd(); - const songListFilter = useSongListFilter({ id: albumArtistId, key: pageKey }); + const songListFilter = useListFilterByKey({ + filter: customFilters, + key: pageKey, + }); + const itemCountCheck = useSongList({ options: { cacheTime: 1000 * 60, @@ -74,7 +79,7 @@ const TrackListRoute = () => { return ( - + { itemCount={itemCount} tableRef={tableRef} /> - + ); };