Update album artist list implementation

This commit is contained in:
jeffvli 2023-07-19 20:53:49 -07:00
parent 6cd27c3e88
commit 440cc04fbc
11 changed files with 187 additions and 309 deletions

View File

@ -1,15 +1,16 @@
import { MutableRefObject, useMemo } from 'react';
import type { ColDef, RowDoubleClickedEvent } from '@ag-grid-community/core';
import type { RowDoubleClickedEvent } from '@ag-grid-community/core';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { useCurrentServer, useSongListStore } from '/@/renderer/store';
import { useHandleTableContextMenu } from '/@/renderer/features/context-menu';
import { SONG_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
import { LibraryItem, QueueSong } from '/@/renderer/api/types';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { MutableRefObject } from 'react';
import { useListContext } from '../../../context/list-context';
import { LibraryItem, QueueSong, SongListQuery } from '/@/renderer/api/types';
import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid';
import { getColumnDefs, VirtualTable } from '/@/renderer/components/virtual-table';
import { VirtualTable } from '/@/renderer/components/virtual-table';
import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles';
import { useVirtualTable } from '/@/renderer/components/virtual-table/hooks/use-virtual-table';
import { SONG_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { useCurrentServer } from '/@/renderer/store';
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
interface AlbumArtistSongListContentProps {
data: QueueSong[];
@ -21,18 +22,11 @@ export const AlbumArtistDetailTopSongsListContent = ({
data,
}: AlbumArtistSongListContentProps) => {
const server = useCurrentServer();
const page = useSongListStore();
const { id, pageKey } = useListContext();
const handlePlayQueueAdd = usePlayQueueAdd();
const playButtonBehavior = usePlayButtonBehavior();
const columnDefs: ColDef[] = useMemo(
() => getColumnDefs(page.table.columns),
[page.table.columns],
);
const handleContextMenu = useHandleTableContextMenu(LibraryItem.SONG, SONG_CONTEXT_MENU_ITEMS);
const handleRowDoubleClick = (e: RowDoubleClickedEvent<QueueSong>) => {
if (!e.data) return;
@ -49,35 +43,33 @@ export const AlbumArtistDetailTopSongsListContent = ({
});
};
const customFilters: Partial<SongListQuery> = {
...(id && { artistIds: [id] }),
};
const { rowClassRules } = useCurrentSongRowStyles({ tableRef });
const tableProps = useVirtualTable({
contextMenu: SONG_CONTEXT_MENU_ITEMS,
customFilters,
itemType: LibraryItem.SONG,
pageKey,
server,
tableRef,
});
return (
<>
<VirtualGridAutoSizerContainer>
<VirtualTable
// https://github.com/ag-grid/ag-grid/issues/5284
// Key is used to force remount of table when display, rowHeight, or server changes
key={`table-${page.display}-${page.table.rowHeight}-${server?.id}`}
key={`table-${tableProps.rowHeight}-${server?.id}`}
ref={tableRef}
alwaysShowHorizontalScroll
animateRows
maintainColumnOrder
suppressCopyRowsToClipboard
suppressMoveWhenRowDragging
suppressPaginationPanel
suppressRowDrag
suppressScrollOnNewData
autoFitColumns={page.table.autoFit}
columnDefs={columnDefs}
enableCellChangeFlash={false}
{...tableProps}
getRowId={(data) => data.data.uniqueId}
rowBuffer={20}
rowClassRules={rowClassRules}
rowData={data}
rowHeight={page.table.rowHeight || 40}
rowModelType="clientSide"
rowSelection="multiple"
onCellContextMenu={handleContextMenu}
onRowDoubleClicked={handleRowDoubleClick}
/>
</VirtualGridAutoSizerContainer>

View File

@ -2,8 +2,9 @@ import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/li
import { lazy, MutableRefObject, Suspense } from 'react';
import { Spinner } from '/@/renderer/components';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { useAlbumArtistListStore } from '/@/renderer/store';
import { ListDisplayType } from '/@/renderer/types';
import { useListStoreByKey } from '../../../store/list.store';
import { useListContext } from '/@/renderer/context/list-context';
const AlbumArtistListGridView = lazy(() =>
import('/@/renderer/features/artists/components/album-artist-list-grid-view').then(
@ -32,7 +33,8 @@ export const AlbumArtistListContent = ({
gridRef,
tableRef,
}: AlbumArtistListContentProps) => {
const { display } = useAlbumArtistListStore();
const { pageKey } = useListContext();
const { display } = useListStoreByKey({ key: pageKey });
const isGrid = display === ListDisplayType.CARD || display === ListDisplayType.POSTER;
return (

View File

@ -1,22 +1,24 @@
import { useQueryClient } from '@tanstack/react-query';
import { QueryKey, useQueryClient } from '@tanstack/react-query';
import { MutableRefObject, useCallback, useMemo } from 'react';
import AutoSizer from 'react-virtualized-auto-sizer';
import { ListOnScrollProps } from 'react-window';
import { VirtualGridAutoSizerContainer } from '../../../components/virtual-grid/virtual-grid-wrapper';
import { useListStoreByKey } from '../../../store/list.store';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import { AlbumArtist, AlbumArtistListSort, LibraryItem } from '/@/renderer/api/types';
import {
AlbumArtist,
AlbumArtistListQuery,
AlbumArtistListResponse,
AlbumArtistListSort,
LibraryItem,
} from '/@/renderer/api/types';
import { ALBUMARTIST_CARD_ROWS } from '/@/renderer/components';
import { VirtualInfiniteGrid, VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { useAlbumArtistListContext } from '/@/renderer/features/artists/context/album-artist-list-context';
import { useListContext } from '/@/renderer/context/list-context';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { AppRoute } from '/@/renderer/router/routes';
import {
useAlbumArtistListFilter,
useAlbumArtistListStore,
useCurrentServer,
useListStoreActions,
} from '/@/renderer/store';
import { useCurrentServer, useListStoreActions } from '/@/renderer/store';
import { CardRow, ListDisplayType } from '/@/renderer/types';
interface AlbumArtistListGridViewProps {
@ -29,18 +31,55 @@ export const AlbumArtistListGridView = ({ itemCount, gridRef }: AlbumArtistListG
const server = useCurrentServer();
const handlePlayQueueAdd = usePlayQueueAdd();
const { id, pageKey } = useAlbumArtistListContext();
const filter = useAlbumArtistListFilter({ id, key: pageKey });
const { grid, display } = useAlbumArtistListStore();
const { pageKey } = useListContext();
const { grid, display, filter } = useListStoreByKey({ key: pageKey });
const { setGrid } = useListStoreActions();
const fetchInitialData = useCallback(() => {
const query: Omit<AlbumArtistListQuery, 'startIndex' | 'limit'> = {
...filter,
};
const queriesFromCache: [QueryKey, AlbumArtistListResponse][] = queryClient.getQueriesData({
exact: false,
fetchStatus: 'idle',
queryKey: queryKeys.albumArtists.list(server?.id || '', query),
stale: false,
});
const itemData = [];
for (const [, data] of queriesFromCache) {
const { items, startIndex } = data || {};
if (items && startIndex !== undefined) {
let itemIndex = 0;
for (
let rowIndex = startIndex;
rowIndex < startIndex + items.length;
rowIndex += 1
) {
itemData[rowIndex] = items[itemIndex];
itemIndex += 1;
}
}
}
return itemData;
}, [filter, queryClient, server?.id]);
const fetch = useCallback(
async ({ skip: startIndex, take: limit }: { skip: number; take: number }) => {
const queryKey = queryKeys.albumArtists.list(server?.id || '', {
limit,
startIndex,
...filter,
});
const queryKey = queryKeys.albumArtists.list(
server?.id || '',
{
...filter,
},
{
limit,
startIndex,
},
);
const albumArtistsRes = await queryClient.fetchQuery(
queryKey,
@ -114,6 +153,7 @@ export const AlbumArtistListGridView = ({ itemCount, gridRef }: AlbumArtistListG
cardRows={cardRows}
display={display || ListDisplayType.CARD}
fetchFn={fetch}
fetchInitialData={fetchInitialData}
handlePlayQueueAdd={handlePlayQueueAdd}
height={height}
initialScrollOffset={grid?.scrollOffset || 0}

View File

@ -5,7 +5,7 @@ import { useQueryClient } from '@tanstack/react-query';
import debounce from 'lodash/debounce';
import { ChangeEvent, MouseEvent, MutableRefObject, useCallback } from 'react';
import { RiFolder2Line, RiMoreFill, RiRefreshLine, RiSettings3Fill } from 'react-icons/ri';
import { useAlbumArtistListContext } from '../context/album-artist-list-context';
import { useListContext } from '../../../context/list-context';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import { AlbumArtistListSort, LibraryItem, SortOrder } from '/@/renderer/api/types';
@ -16,10 +16,9 @@ import { OrderToggleButton, useMusicFolders } from '/@/renderer/features/shared'
import { useContainerQuery } from '/@/renderer/hooks';
import {
AlbumArtistListFilter,
useAlbumArtistListFilter,
useAlbumArtistListStore,
useCurrentServer,
useListStoreActions,
useListStoreByKey,
} from '/@/renderer/store';
import { ListDisplayType, ServerType, TableColumn } from '/@/renderer/types';
@ -65,11 +64,10 @@ export const AlbumArtistListHeaderFilters = ({
}: AlbumArtistListHeaderFiltersProps) => {
const queryClient = useQueryClient();
const server = useCurrentServer();
const { pageKey } = useAlbumArtistListContext();
const { display, table, grid } = useAlbumArtistListStore();
const { pageKey } = useListContext();
const { display, table, grid, filter } = useListStoreByKey({ key: pageKey });
const { setFilter, setTable, setTablePagination, setDisplayType, setGrid } =
useListStoreActions();
const filter = useAlbumArtistListFilter({ key: pageKey });
const cq = useContainerQuery();
const isGrid = display === ListDisplayType.CARD || display === ListDisplayType.POSTER;

View File

@ -1,27 +1,19 @@
import type { ChangeEvent, MutableRefObject } from 'react';
import { useCallback } from 'react';
import { 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 { useQueryClient } from '@tanstack/react-query';
import debounce from 'lodash/debounce';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import type { ChangeEvent, MutableRefObject } from 'react';
import { useListContext } from '../../../context/list-context';
import { useListStoreByKey } from '../../../store/list.store';
import { FilterBar } from '../../shared/components/filter-bar';
import { LibraryItem } from '/@/renderer/api/types';
import { PageHeader, SearchInput } from '/@/renderer/components';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { AlbumArtistListHeaderFilters } from '/@/renderer/features/artists/components/album-artist-list-header-filters';
import { LibraryHeaderBar } from '/@/renderer/features/shared';
import { useContainerQuery } from '/@/renderer/hooks';
import {
AlbumArtistListFilter,
useAlbumArtistListStore,
useCurrentServer,
useListStoreActions,
} from '/@/renderer/store';
import { useListFilterRefresh } from '/@/renderer/hooks/use-list-filter-refresh';
import { AlbumArtistListFilter, useCurrentServer, useListStoreActions } from '/@/renderer/store';
import { ListDisplayType } from '/@/renderer/types';
import { AlbumArtistListHeaderFilters } from '/@/renderer/features/artists/components/album-artist-list-header-filters';
import { useAlbumArtistListContext } from '/@/renderer/features/artists/context/album-artist-list-context';
import { FilterBar } from '../../shared/components/filter-bar';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { LibraryItem } from '/@/renderer/api/types';
interface AlbumArtistListHeaderProps {
gridRef: MutableRefObject<VirtualInfiniteGridRef | null>;
@ -34,113 +26,31 @@ export const AlbumArtistListHeader = ({
gridRef,
tableRef,
}: AlbumArtistListHeaderProps) => {
const queryClient = useQueryClient();
const server = useCurrentServer();
const { pageKey } = useAlbumArtistListContext();
const { display, filter } = useAlbumArtistListStore();
const { pageKey } = useListContext();
const { display, filter } = useListStoreByKey({ key: pageKey });
const { setFilter, setTablePagination } = useListStoreActions();
const cq = useContainerQuery();
const fetch = useCallback(
async (startIndex: number, limit: number, filters: AlbumArtistListFilter) => {
const queryKey = queryKeys.albumArtists.list(server?.id || '', {
limit,
startIndex,
...filters,
});
const albums = await queryClient.fetchQuery(
queryKey,
async ({ signal }) =>
api.controller.getAlbumArtistList({
apiClientProps: {
server,
signal,
},
query: {
limit,
startIndex,
...filters,
},
}),
{ cacheTime: 1000 * 60 * 1 },
);
return albums;
},
[queryClient, server],
);
const handleFilterChange = useCallback(
async (filters: AlbumArtistListFilter) => {
if (display === ListDisplayType.TABLE || display === ListDisplayType.TABLE_PAGINATED) {
const dataSource: IDatasource = {
getRows: async (params) => {
const limit = params.endRow - params.startRow;
const startIndex = params.startRow;
const queryKey = queryKeys.albumArtists.list(server?.id || '', {
limit,
startIndex,
...filters,
});
const albumArtistsRes = await queryClient.fetchQuery(
queryKey,
async ({ signal }) =>
api.controller.getAlbumArtistList({
apiClientProps: {
server,
signal,
},
query: {
limit,
startIndex,
...filters,
},
}),
{ cacheTime: 1000 * 60 * 1 },
);
params.successCallback(
albumArtistsRes?.items || [],
albumArtistsRes?.totalRecordCount || 0,
);
},
rowCount: undefined,
};
tableRef.current?.api.setDatasource(dataSource);
tableRef.current?.api.purgeInfiniteCache();
tableRef.current?.api.ensureIndexVisible(0, 'top');
if (display === ListDisplayType.TABLE_PAGINATED) {
setTablePagination({ data: { currentPage: 0 }, key: pageKey });
}
} else {
gridRef.current?.scrollTo(0);
gridRef.current?.resetLoadMoreItemsCache();
// Refetching within the virtualized grid may be inconsistent due to it refetching
// using an outdated set of filters. To avoid this, we fetch using the updated filters
// and then set the grid's data here.
const data = await fetch(0, 200, filters);
if (!data?.items) return;
gridRef.current?.setItemData(data.items);
}
},
[display, tableRef, server, queryClient, setTablePagination, pageKey, gridRef, fetch],
);
const { handleRefreshGrid, handleRefreshTable } = useListFilterRefresh({
itemType: LibraryItem.ALBUM_ARTIST,
server,
});
const handleSearch = debounce((e: ChangeEvent<HTMLInputElement>) => {
const previousSearchTerm = filter.searchTerm;
const searchTerm = e.target.value === '' ? undefined : e.target.value;
const updatedFilters = setFilter({
data: { searchTerm },
itemType: LibraryItem.ALBUM_ARTIST,
key: pageKey,
}) as AlbumArtistListFilter;
if (previousSearchTerm !== searchTerm) handleFilterChange(updatedFilters);
if (display === ListDisplayType.TABLE || display === ListDisplayType.TABLE_PAGINATED) {
handleRefreshTable(tableRef, updatedFilters);
setTablePagination({ data: { currentPage: 0 }, key: pageKey });
} else {
handleRefreshGrid(gridRef, updatedFilters);
}
}, 500);
return (

View File

@ -1,22 +1,12 @@
import { MutableRefObject, useCallback } from 'react';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { AlbumArtistListQuery, AlbumArtistListResponse, LibraryItem } from '/@/renderer/api/types';
import {
AgGridFetchFn,
useVirtualTable,
} from '/@/renderer/components/virtual-table/hooks/use-virtual-table';
import { useAlbumArtistListContext } from '/@/renderer/features/artists/context/album-artist-list-context';
import { MutableRefObject } from 'react';
import { useListContext } from '../../../context/list-context';
import { ARTIST_CONTEXT_MENU_ITEMS } from '../../context-menu/context-menu-items';
import {
useAlbumArtistListFilter,
useAlbumArtistListStore,
useCurrentServer,
useListStoreActions,
} from '/@/renderer/store';
import { LibraryItem } from '/@/renderer/api/types';
import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid';
import { VirtualTable } from '/@/renderer/components/virtual-table';
import { useVirtualTable } from '/@/renderer/components/virtual-table/hooks/use-virtual-table';
import { useCurrentServer } from '/@/renderer/store';
interface AlbumArtistListTableViewProps {
itemCount?: number;
@ -28,53 +18,14 @@ export const AlbumArtistListTableView = ({
tableRef,
}: AlbumArtistListTableViewProps) => {
const server = useCurrentServer();
const { id, pageKey } = useAlbumArtistListContext();
const filter = useAlbumArtistListFilter({ id, key: pageKey });
const listProperties = useAlbumArtistListStore();
const { setTable, setTablePagination } = useListStoreActions();
const { pageKey } = useListContext();
const fetchFn: AgGridFetchFn<
AlbumArtistListResponse,
Omit<AlbumArtistListQuery, 'startIndex'>
> = useCallback(
async ({ filter, limit, startIndex }, signal) => {
const res = api.controller.getAlbumArtistList({
apiClientProps: {
server,
signal,
},
query: {
...filter,
limit,
sortBy: filter.sortBy,
sortOrder: filter.sortOrder,
startIndex,
},
});
return res;
},
[server],
);
const tableProps = useVirtualTable<
AlbumArtistListResponse,
Omit<AlbumArtistListQuery, 'startIndex'>
>({
const tableProps = useVirtualTable({
contextMenu: ARTIST_CONTEXT_MENU_ITEMS,
fetch: {
filter,
fn: fetchFn,
itemCount,
queryKey: queryKeys.albums.list,
server,
},
itemCount,
itemType: LibraryItem.SONG,
itemType: LibraryItem.ALBUM_ARTIST,
pageKey,
properties: listProperties,
setTable,
setTablePagination,
server,
tableRef,
});
@ -83,7 +34,7 @@ export const AlbumArtistListTableView = ({
<VirtualTable
// https://github.com/ag-grid/ag-grid/issues/5284
// Key is used to force remount of table when display, rowHeight, or server changes
key={`table-${listProperties.display}-${listProperties.table.rowHeight}-${server?.id}`}
key={`table-${tableProps.rowHeight}-${server?.id}`}
ref={tableRef}
{...tableProps}
/>

View File

@ -1,11 +0,0 @@
import { createContext, useContext } from 'react';
import { ListKey } from '/@/renderer/store';
export const AlbumArtistDetailSongListContext = createContext<{ id?: string; pageKey: ListKey }>({
pageKey: 'albumArtist',
});
export const useAlbumArtistDetailSongListContext = () => {
const ctxValue = useContext(AlbumArtistDetailSongListContext);
return ctxValue;
};

View File

@ -1,11 +0,0 @@
import { createContext, useContext } from 'react';
import { ListKey } from '/@/renderer/store';
export const AlbumArtistListContext = createContext<{ id?: string; pageKey: ListKey }>({
pageKey: 'albumArtist',
});
export const useAlbumArtistListContext = () => {
const ctxValue = useContext(AlbumArtistListContext);
return ctxValue;
};

View File

@ -6,12 +6,15 @@ import { AlbumArtistDetailTopSongsListHeader } from '/@/renderer/features/artist
import { useAlbumArtistDetail } from '/@/renderer/features/artists/queries/album-artist-detail-query';
import { useTopSongsList } from '/@/renderer/features/artists/queries/top-songs-list-query';
import { AnimatedPage } from '/@/renderer/features/shared';
import { LibraryItem } from '../../../api/types';
import { useCurrentServer } from '../../../store/auth.store';
import { ListContext } from '/@/renderer/context/list-context';
const AlbumArtistDetailTopSongsListRoute = () => {
const tableRef = useRef<AgGridReactType | null>(null);
const { albumArtistId } = useParams() as { albumArtistId: string };
const server = useCurrentServer();
const pageKey = LibraryItem.SONG;
const detailQuery = useAlbumArtistDetail({
query: { id: albumArtistId },
@ -30,15 +33,17 @@ const AlbumArtistDetailTopSongsListRoute = () => {
return (
<AnimatedPage>
<AlbumArtistDetailTopSongsListHeader
data={topSongsQuery?.data?.items || []}
itemCount={itemCount}
title={detailQuery?.data?.name || 'Unknown'}
/>
<AlbumArtistDetailTopSongsListContent
data={topSongsQuery?.data?.items || []}
tableRef={tableRef}
/>
<ListContext.Provider value={{ id: albumArtistId, pageKey }}>
<AlbumArtistDetailTopSongsListHeader
data={topSongsQuery?.data?.items || []}
itemCount={itemCount}
title={detailQuery?.data?.name || 'Unknown'}
/>
<AlbumArtistDetailTopSongsListContent
data={topSongsQuery?.data?.items || []}
tableRef={tableRef}
/>
</ListContext.Provider>
</AnimatedPage>
);
};

View File

@ -1,21 +1,22 @@
import { AlbumArtistListHeader } from '/@/renderer/features/artists/components/album-artist-list-header';
import { AnimatedPage } from '/@/renderer/features/shared';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { useRef } from 'react';
import { AlbumArtistListContent } from '/@/renderer/features/artists/components/album-artist-list-content';
import { useAlbumArtistList } from '/@/renderer/features/artists/queries/album-artist-list-query';
import { generatePageKey, useAlbumArtistListFilter } from '/@/renderer/store';
import { AlbumArtistListContext } from '/@/renderer/features/artists/context/album-artist-list-context';
import { useCurrentServer } from '../../../store/auth.store';
import { useListFilterByKey } from '../../../store/list.store';
import { LibraryItem } from '/@/renderer/api/types';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { ListContext } from '/@/renderer/context/list-context';
import { AlbumArtistListContent } from '/@/renderer/features/artists/components/album-artist-list-content';
import { AlbumArtistListHeader } from '/@/renderer/features/artists/components/album-artist-list-header';
import { useAlbumArtistList } from '/@/renderer/features/artists/queries/album-artist-list-query';
import { AnimatedPage } from '/@/renderer/features/shared';
const AlbumArtistListRoute = () => {
const gridRef = useRef<VirtualInfiniteGridRef | null>(null);
const tableRef = useRef<AgGridReactType | null>(null);
const pageKey = generatePageKey('albumArtist', undefined);
const pageKey = LibraryItem.ALBUM_ARTIST;
const server = useCurrentServer();
const albumArtistListFilter = useAlbumArtistListFilter({ id: undefined, key: pageKey });
const albumArtistListFilter = useListFilterByKey({ key: pageKey });
const itemCountCheck = useAlbumArtistList({
options: {
@ -37,7 +38,7 @@ const AlbumArtistListRoute = () => {
return (
<AnimatedPage>
<AlbumArtistListContext.Provider value={{ id: undefined, pageKey }}>
<ListContext.Provider value={{ id: undefined, pageKey }}>
<AlbumArtistListHeader
gridRef={gridRef}
itemCount={itemCount}
@ -48,7 +49,7 @@ const AlbumArtistListRoute = () => {
itemCount={itemCount}
tableRef={tableRef}
/>
</AlbumArtistListContext.Provider>
</ListContext.Provider>
</AnimatedPage>
);
};

View File

@ -55,6 +55,7 @@ export interface ListState {
item: {
album: ListItemProps<AlbumListFilter>;
albumArtist: ListItemProps<AlbumArtistListFilter>;
albumArtistSong: ListItemProps<SongListFilter>;
albumDetail: ListItemProps<any>;
playlist: ListItemProps<PlaylistListFilter>;
song: ListItemProps<SongListFilter>;
@ -379,6 +380,43 @@ export const useListStore = create<ListSlice>()(
scrollOffset: 0,
},
},
albumArtistSong: {
display: ListDisplayType.TABLE,
filter: {
sortBy: SongListSort.RECENTLY_ADDED,
sortOrder: SortOrder.DESC,
},
grid: { itemsPerRow: 5, scrollOffset: 0 },
table: {
autoFit: true,
columns: [
{
column: TableColumn.ROW_INDEX,
width: 50,
},
{
column: TableColumn.TITLE_COMBINED,
width: 500,
},
{
column: TableColumn.ALBUM,
width: 300,
},
{
column: TableColumn.DURATION,
width: 100,
},
],
pagination: {
currentPage: 1,
itemsPerPage: 100,
totalItems: 1,
totalPages: 1,
},
rowHeight: 60,
scrollOffset: 0,
},
},
albumDetail: {
display: ListDisplayType.TABLE,
filter: {
@ -450,28 +488,12 @@ export const useListStore = create<ListSlice>()(
column: TableColumn.TITLE_COMBINED,
width: 500,
},
{
column: TableColumn.DURATION,
width: 100,
},
{
column: TableColumn.ALBUM,
width: 300,
},
{
column: TableColumn.ARTIST,
width: 100,
},
{
column: TableColumn.YEAR,
width: 100,
},
{
column: TableColumn.DATE_ADDED,
width: 100,
},
{
column: TableColumn.PLAY_COUNT,
column: TableColumn.DURATION,
width: 100,
},
],
@ -552,9 +574,6 @@ export const useAlbumListStore = (args?: { id?: string; key?: string }) =>
};
}, shallow);
export const useAlbumArtistListStore = () =>
useListStore((state) => state.item.albumArtist, shallow);
export const useSongListStore = (args?: { id?: string; key?: string }) =>
useListStore((state) => {
const detail = args?.key ? state.detail[args.key] : undefined;
@ -597,15 +616,6 @@ export const usePlaylistListStore = (args?: { key?: string }) =>
};
}, shallow);
export const useSongListFilter = (args: { id?: string; key?: string }) =>
useListStore((state) => {
return state._actions.getFilter({
id: args.id,
itemType: LibraryItem.SONG,
key: args.key,
}) as SongListFilter;
}, shallow);
export const useAlbumListFilter = (args: { id?: string; key?: string }) =>
useListStore((state) => {
return state._actions.getFilter({
@ -615,13 +625,4 @@ export const useAlbumListFilter = (args: { id?: string; key?: string }) =>
}) as AlbumListFilter;
}, shallow);
export const useAlbumArtistListFilter = (args: { id?: string; key?: string }) =>
useListStore((state) => {
return state._actions.getFilter({
id: args.id,
itemType: LibraryItem.ALBUM_ARTIST,
key: args.key,
}) as AlbumArtistListFilter;
}, shallow);
export const useListDetail = (key: string) => useListStore((state) => state.detail[key], shallow);