Fix list store for artist detail

This commit is contained in:
jeffvli 2023-03-09 18:09:59 -08:00
parent 84587da701
commit 563db1138e
10 changed files with 98 additions and 67 deletions

View File

@ -10,7 +10,7 @@ import {
import { AppRoute } from '/@/renderer/router/routes'; import { AppRoute } from '/@/renderer/router/routes';
import { ListDisplayType, CardRow } from '/@/renderer/types'; import { ListDisplayType, CardRow } from '/@/renderer/types';
import AutoSizer from 'react-virtualized-auto-sizer'; import AutoSizer from 'react-virtualized-auto-sizer';
import { MutableRefObject, useCallback, useMemo, useState } from 'react'; import { MutableRefObject, useCallback, useMemo } from 'react';
import { ListOnScrollProps } from 'react-window'; import { ListOnScrollProps } from 'react-window';
import { api } from '/@/renderer/api'; import { api } from '/@/renderer/api';
import { controller } from '/@/renderer/api/controller'; import { controller } from '/@/renderer/api/controller';
@ -21,7 +21,6 @@ import {
useCurrentServer, useCurrentServer,
useAlbumListStore, useAlbumListStore,
useAlbumListItemData, useAlbumListItemData,
AlbumListFilter,
useListStoreActions, useListStoreActions,
useAlbumListFilter, useAlbumListFilter,
} from '/@/renderer/store'; } from '/@/renderer/store';
@ -44,30 +43,23 @@ import { useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/share
import { useAlbumListContext } from '/@/renderer/features/albums/context/album-list-context'; import { useAlbumListContext } from '/@/renderer/features/albums/context/album-list-context';
interface AlbumListContentProps { interface AlbumListContentProps {
customFilters?: Partial<AlbumListFilter>;
gridRef: MutableRefObject<VirtualInfiniteGridRef | null>; gridRef: MutableRefObject<VirtualInfiniteGridRef | null>;
itemCount?: number; itemCount?: number;
tableRef: MutableRefObject<AgGridReactType | null>; tableRef: MutableRefObject<AgGridReactType | null>;
} }
export const AlbumListContent = ({ export const AlbumListContent = ({ itemCount, gridRef, tableRef }: AlbumListContentProps) => {
customFilters,
itemCount,
gridRef,
tableRef,
}: AlbumListContentProps) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const navigate = useNavigate(); const navigate = useNavigate();
const server = useCurrentServer(); const server = useCurrentServer();
const handlePlayQueueAdd = usePlayQueueAdd(); const handlePlayQueueAdd = usePlayQueueAdd();
const { itemData, setItemData } = useAlbumListItemData(); const { itemData, setItemData } = useAlbumListItemData();
const [localItemData, setLocalItemData] = useState<any[]>([]);
const { id, pageKey } = useAlbumListContext(); const { id, pageKey } = useAlbumListContext();
const filter = useAlbumListFilter({ id, key: pageKey }); const filter = useAlbumListFilter({ id, key: pageKey });
const { setTable, setTablePagination, setGrid } = useListStoreActions(); const { setTable, setTablePagination, setGrid } = useListStoreActions();
const { table, grid, display } = useAlbumListStore(); const { table, grid, display } = useAlbumListStore({ id, key: pageKey });
const isPaginationEnabled = display === ListDisplayType.TABLE_PAGINATED; const isPaginationEnabled = display === ListDisplayType.TABLE_PAGINATED;
const columnDefs: ColDef[] = useMemo(() => getColumnDefs(table.columns), [table.columns]); const columnDefs: ColDef[] = useMemo(() => getColumnDefs(table.columns), [table.columns]);
@ -83,14 +75,11 @@ export const AlbumListContent = ({
limit, limit,
startIndex, startIndex,
...filter, ...filter,
...customFilters,
jfParams: { jfParams: {
...filter.jfParams, ...filter.jfParams,
...customFilters?.jfParams,
}, },
ndParams: { ndParams: {
...filter.ndParams, ...filter.ndParams,
...customFilters?.ndParams,
}, },
}; };
@ -113,12 +102,8 @@ export const AlbumListContent = ({
rowCount: undefined, rowCount: undefined,
}; };
params.api.setDatasource(dataSource); params.api.setDatasource(dataSource);
if (!customFilters) {
params.api.ensureIndexVisible(table.scrollOffset || 0, 'top');
}
}, },
[customFilters, filter, table.scrollOffset, queryClient, server], [filter, queryClient, server],
); );
const onTablePaginationChanged = useCallback( const onTablePaginationChanged = useCallback(
@ -178,7 +163,6 @@ export const AlbumListContent = ({
const debouncedTableColumnChange = debounce(handleTableColumnChange, 200); const debouncedTableColumnChange = debounce(handleTableColumnChange, 200);
const handleTableScroll = (e: BodyScrollEvent) => { const handleTableScroll = (e: BodyScrollEvent) => {
if (customFilters) return;
const scrollOffset = Number((e.top / table.rowHeight).toFixed(0)); const scrollOffset = Number((e.top / table.rowHeight).toFixed(0));
setTable({ data: { scrollOffset }, key: pageKey }); setTable({ data: { scrollOffset }, key: pageKey });
}; };
@ -189,14 +173,11 @@ export const AlbumListContent = ({
limit: take, limit: take,
startIndex: skip, startIndex: skip,
...filter, ...filter,
...customFilters,
jfParams: { jfParams: {
...filter.jfParams, ...filter.jfParams,
...customFilters?.jfParams,
}, },
ndParams: { ndParams: {
...filter.ndParams, ...filter.ndParams,
...customFilters?.ndParams,
}, },
}; };
@ -212,15 +193,14 @@ export const AlbumListContent = ({
return api.normalize.albumList(albums, server); return api.normalize.albumList(albums, server);
}, },
[customFilters, filter, queryClient, server], [filter, queryClient, server],
); );
const handleGridScroll = useCallback( const handleGridScroll = useCallback(
(e: ListOnScrollProps) => { (e: ListOnScrollProps) => {
if (customFilters) return;
setGrid({ data: { scrollOffset: e.scrollOffset }, key: pageKey }); setGrid({ data: { scrollOffset: e.scrollOffset }, key: pageKey });
}, },
[customFilters, pageKey, setGrid], [pageKey, setGrid],
); );
const cardRows = useMemo(() => { const cardRows = useMemo(() => {
@ -334,9 +314,9 @@ export const AlbumListContent = ({
handleFavorite={handleFavorite} handleFavorite={handleFavorite}
handlePlayQueueAdd={handlePlayQueueAdd} handlePlayQueueAdd={handlePlayQueueAdd}
height={height} height={height}
initialScrollOffset={customFilters ? 0 : grid?.scrollOffset || 0} initialScrollOffset={grid?.scrollOffset || 0}
itemCount={itemCount || 0} itemCount={itemCount || 0}
itemData={customFilters ? localItemData : itemData} itemData={itemData}
itemGap={20} itemGap={20}
itemSize={150 + (grid?.size || 0)} itemSize={150 + (grid?.size || 0)}
itemType={LibraryItem.ALBUM} itemType={LibraryItem.ALBUM}
@ -346,7 +326,7 @@ export const AlbumListContent = ({
route: AppRoute.LIBRARY_ALBUMS_DETAIL, route: AppRoute.LIBRARY_ALBUMS_DETAIL,
slugs: [{ idProperty: 'id', slugProperty: 'albumId' }], slugs: [{ idProperty: 'id', slugProperty: 'albumId' }],
}} }}
setItemData={customFilters ? setLocalItemData : setItemData} setItemData={setItemData}
width={width} width={width}
onScroll={handleGridScroll} onScroll={handleGridScroll}
/> />

View File

@ -97,7 +97,7 @@ export const AlbumListHeaderFilters = ({
const server = useCurrentServer(); const server = useCurrentServer();
const { setFilter, setTablePagination, setTable, setGrid, setDisplayType, setTableColumns } = const { setFilter, setTablePagination, setTable, setGrid, setDisplayType, setTableColumns } =
useListStoreActions(); useListStoreActions();
const { display, filter, table, grid } = useAlbumListStore(); const { display, filter, table, grid } = useAlbumListStore({ id, key: pageKey });
const cq = useContainerQuery(); const cq = useContainerQuery();
const musicFoldersQuery = useMusicFolders(); const musicFoldersQuery = useMusicFolders();

View File

@ -28,6 +28,7 @@ import { ListDisplayType, Play } from '/@/renderer/types';
import { AlbumListHeaderFilters } from '/@/renderer/features/albums/components/album-list-header-filters'; import { AlbumListHeaderFilters } from '/@/renderer/features/albums/components/album-list-header-filters';
import { usePlayQueueAdd } from '/@/renderer/features/player'; import { usePlayQueueAdd } from '/@/renderer/features/player';
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
import { useAlbumListContext } from '/@/renderer/features/albums/context/album-list-context';
interface AlbumListHeaderProps { interface AlbumListHeaderProps {
customFilters?: Partial<AlbumListFilter>; customFilters?: Partial<AlbumListFilter>;
@ -48,7 +49,8 @@ export const AlbumListHeader = ({
const server = useCurrentServer(); const server = useCurrentServer();
const { setFilter, setTablePagination } = useListStoreActions(); const { setFilter, setTablePagination } = useListStoreActions();
const cq = useContainerQuery(); const cq = useContainerQuery();
const { filter, display } = useAlbumListStore(); const { id, pageKey } = useAlbumListContext();
const { filter, display } = useAlbumListStore({ id, key: pageKey });
const fetch = useCallback( const fetch = useCallback(
async (skip: number, take: number, filters: AlbumListFilter) => { async (skip: number, take: number, filters: AlbumListFilter) => {

View File

@ -23,8 +23,6 @@ export const NavidromeAlbumFilters = ({
const filter = useAlbumListFilter({ id, key: pageKey }); const filter = useAlbumListFilter({ id, key: pageKey });
const { setFilter } = useListStoreActions(); const { setFilter } = useListStoreActions();
console.log('pageKey, id', pageKey, id);
const genreListQuery = useGenreList(null); const genreListQuery = useGenreList(null);
const genreList = useMemo(() => { const genreList = useMemo(() => {
@ -74,7 +72,6 @@ export const NavidromeAlbumFilters = ({
}, },
key: pageKey, key: pageKey,
}) as AlbumListFilter; }) as AlbumListFilter;
console.log('updatedFilters :>> ', updatedFilters);
handleFilterChange(updatedFilters); handleFilterChange(updatedFilters);
}, },
value: filter.ndParams?.starred, value: filter.ndParams?.starred,

View File

@ -270,8 +270,6 @@ export const AlbumArtistDetailContent = () => {
ARTIST_CONTEXT_MENU_ITEMS, ARTIST_CONTEXT_MENU_ITEMS,
); );
console.log('topSongsQuery?.data :>> ', topSongsQuery?.data);
const topSongs = topSongsQuery?.data?.items?.slice(0, 10); const topSongs = topSongsQuery?.data?.items?.slice(0, 10);
const showBiography = const showBiography =

View File

@ -53,7 +53,6 @@ export const NavidromeSongFilters = ({
key: pageKey, key: pageKey,
}) as SongListFilter; }) as SongListFilter;
console.log('updatedFilters :>> ', updatedFilters);
handleFilterChange(updatedFilters); handleFilterChange(updatedFilters);
}, },
value: filter.ndParams?.starred, value: filter.ndParams?.starred,

View File

@ -43,9 +43,9 @@ export const SongListContent = ({ itemCount, tableRef }: SongListContentProps) =
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const server = useCurrentServer(); const server = useCurrentServer();
const { display, table } = useSongListStore();
const { id, pageKey } = useSongListContext(); const { id, pageKey } = useSongListContext();
const filter = useSongListFilter({ id, key: pageKey }); const filter = useSongListFilter({ id, key: pageKey });
const { display, table } = useSongListStore({ id, key: pageKey });
const { setTable, setTablePagination } = useListStoreActions(); const { setTable, setTablePagination } = useListStoreActions();
const handlePlayQueueAdd = usePlayQueueAdd(); const handlePlayQueueAdd = usePlayQueueAdd();
@ -155,7 +155,6 @@ export const SongListContent = ({ itemCount, tableRef }: SongListContentProps) =
const debouncedColumnChange = debounce(handleColumnChange, 200); const debouncedColumnChange = debounce(handleColumnChange, 200);
const handleScroll = (e: BodyScrollEvent) => { const handleScroll = (e: BodyScrollEvent) => {
if (id) return;
const scrollOffset = Number((e.top / table.rowHeight).toFixed(0)); const scrollOffset = Number((e.top / table.rowHeight).toFixed(0));
setTable({ data: { scrollOffset }, key: pageKey }); setTable({ data: { scrollOffset }, key: pageKey });
}; };

View File

@ -93,7 +93,7 @@ export const SongListHeaderFilters = ({
}: SongListHeaderFiltersProps) => { }: SongListHeaderFiltersProps) => {
const server = useCurrentServer(); const server = useCurrentServer();
const { id, pageKey } = useSongListContext(); const { id, pageKey } = useSongListContext();
const { display, table } = useSongListStore(); const { display, table } = useSongListStore({ id, key: pageKey });
const { setFilter, setTable, setTablePagination, setDisplayType } = useListStoreActions(); const { setFilter, setTable, setTablePagination, setDisplayType } = useListStoreActions();
const filter = useSongListFilter({ id, key: pageKey }); const filter = useSongListFilter({ id, key: pageKey });

View File

@ -36,8 +36,8 @@ export const SongListHeader = ({
tableRef, tableRef,
}: SongListHeaderProps) => { }: SongListHeaderProps) => {
const server = useCurrentServer(); const server = useCurrentServer();
const { pageKey } = useSongListContext(); const { id, pageKey } = useSongListContext();
const { filter } = useSongListStore(); const { filter } = useSongListStore({ id, key: pageKey });
const { setFilter, setTablePagination } = useListStoreActions(); const { setFilter, setTablePagination } = useListStoreActions();
const handlePlayQueueAdd = usePlayQueueAdd(); const handlePlayQueueAdd = usePlayQueueAdd();
const cq = useContainerQuery(); const cq = useContainerQuery();

View File

@ -47,7 +47,7 @@ type ItemProps<TFilter = any> = {
export interface ListState { export interface ListState {
detail: { detail: {
[key: string]: Omit<ItemProps<any>, 'display' | 'grid'>; [key: string]: Omit<ItemProps<any>, 'display'>;
}; };
item: { item: {
album: ItemProps<AlbumListFilter>; album: ItemProps<AlbumListFilter>;
@ -125,7 +125,6 @@ export const useListStore = create<ListSlice>()(
}, },
setFilter: (args) => { setFilter: (args) => {
const [, id] = args.key.split('_'); const [, id] = args.key.split('_');
console.log('args', args);
set((state) => { set((state) => {
if (id) { if (id) {
@ -158,10 +157,37 @@ export const useListStore = create<ListSlice>()(
return get()._actions.getFilter({ id, key: args.key }); return get()._actions.getFilter({ id, key: args.key });
}, },
setGrid: (args) => { setGrid: (args) => {
const [page, id] = args.key.split('_');
set((state) => { set((state) => {
if (state.item[args.key as keyof ListState['item']].grid) { if (id) {
state.item[args.key as keyof ListState['item']].grid = { if (!state.detail[args.key]) {
...state.item[args.key as keyof ListState['item']]?.grid, state.detail[args.key] = {
filter: {} as FilterType,
grid: {
scrollOffset: 0,
size: state.item[page as keyof ListState['item']].grid?.size || 200,
},
table: {
pagination: {
currentPage: 1,
itemsPerPage: 100,
totalItems: 0,
totalPages: 0,
},
} as ListTableProps,
};
}
if (state.detail[args.key as keyof ListState['item']].grid) {
state.detail[args.key as keyof ListState['item']].grid = {
...state.detail[args.key as keyof ListState['item']]?.grid,
...args.data,
};
}
} else if (state.item[page as keyof ListState['item']].grid) {
state.item[page as keyof ListState['item']].grid = {
...state.item[page as keyof ListState['item']]?.grid,
...args.data, ...args.data,
}; };
} }
@ -177,7 +203,11 @@ export const useListStore = create<ListSlice>()(
if (id) { if (id) {
if (!state.detail[args.key]) { if (!state.detail[args.key]) {
state.detail[args.key] = { state.detail[args.key] = {
filter: {} as FilterType, filter: {
...state.item[page as keyof ListState['item']].filter,
jfParams: {},
ndParams: {},
} as FilterType,
table: { table: {
pagination: { pagination: {
currentPage: 1, currentPage: 1,
@ -185,27 +215,15 @@ export const useListStore = create<ListSlice>()(
totalItems: 0, totalItems: 0,
totalPages: 0, totalPages: 0,
}, },
scrollOffset: 0,
} as ListTableProps, } as ListTableProps,
}; };
} }
if (!state.detail[args.key]?.table) { if (state.detail[args.key as keyof ListState['item']].table) {
state.detail[args.key].table = { state.detail[args.key as keyof ListState['item']].table = {
...state.item[page as keyof ListState['item']].table, ...state.detail[args.key as keyof ListState['item']]?.table,
pagination: { ...args.data,
currentPage: 1,
itemsPerPage: 100,
totalItems: 0,
totalPages: 0,
},
};
}
if (!state.detail[args.key]?.filter) {
state.detail[args.key].filter = {
...state.item[page as keyof ListState['item']].filter,
jfParams: {},
ndParams: {},
}; };
} }
} else { } else {
@ -459,12 +477,50 @@ export const useListStore = create<ListSlice>()(
export const useListStoreActions = () => useListStore((state) => state._actions); export const useListStoreActions = () => useListStore((state) => state._actions);
export const useAlbumListStore = () => useListStore((state) => state.item.album, shallow); export const useAlbumListStore = (args?: { id?: string; key?: string }) =>
useListStore((state) => {
const detail = args?.key ? state.detail[args.key] : undefined;
return {
...state.item.album,
filter: {
...state.item.album.filter,
...detail?.filter,
},
grid: {
...state.item.album.grid,
...detail?.grid,
},
table: {
...state.item.album.table,
...detail?.table,
},
};
}, shallow);
export const useAlbumArtistListStore = () => export const useAlbumArtistListStore = () =>
useListStore((state) => state.item.albumArtist, shallow); useListStore((state) => state.item.albumArtist, shallow);
export const useSongListStore = () => useListStore((state) => state.item.song, shallow); export const useSongListStore = (args?: { id?: string; key?: string }) =>
useListStore((state) => {
const detail = args?.key ? state.detail[args.key] : undefined;
return {
...state.item.song,
filter: {
...state.item.song.filter,
...detail?.filter,
},
grid: {
...state.item.song.grid,
...detail?.grid,
},
table: {
...state.item.song.table,
...detail?.table,
},
};
}, shallow);
export const useSongListFilter = (args: { id?: string; key?: string }) => export const useSongListFilter = (args: { id?: string; key?: string }) =>
useListStore((state) => { useListStore((state) => {