Add album view for playlists (#1700)

* update client side song ordering to include album order

* add compact styling to LibraryHeader

* move search button to top right of LibraryHeader
This commit is contained in:
Jeff
2026-02-11 21:48:25 -08:00
committed by GitHub
parent 9cde569c7d
commit e6f49b9f1f
20 changed files with 918 additions and 103 deletions
@@ -4,6 +4,7 @@ import { useEffect } from 'react';
import { useGridRows } from '/@/renderer/components/item-list/helpers/use-grid-rows';
import { useItemListScrollPersist } from '/@/renderer/components/item-list/helpers/use-item-list-scroll-persist';
import { ItemGridList } from '/@/renderer/components/item-list/item-grid-list/item-grid-list';
import { ItemListWithPagination } from '/@/renderer/components/item-list/item-list-pagination/item-list-pagination';
import { ItemListGridComponentProps } from '/@/renderer/components/item-list/types';
import { useListContext } from '/@/renderer/context/list-context';
import { usePlaylistSongListFilters } from '/@/renderer/features/playlists/hooks/use-playlist-song-list-filters';
@@ -15,40 +16,52 @@ import {
LibraryItem,
PlaylistSongListQuery,
PlaylistSongListResponse,
Song,
} from '/@/shared/types/domain-types';
import { ItemListKey } from '/@/shared/types/types';
interface PlaylistDetailSongListGridProps
extends Omit<ItemListGridComponentProps<PlaylistSongListQuery>, 'query'> {
currentPage?: number;
data: PlaylistSongListResponse;
items?: Song[];
itemsPerPage?: number;
onPageChange?: (page: number) => void;
}
export const PlaylistDetailSongListGrid = forwardRef<any, PlaylistDetailSongListGridProps>(
({ data, saveScrollOffset = true }) => {
({
currentPage,
data,
items: itemsProp,
itemsPerPage,
onPageChange,
saveScrollOffset = true,
}) => {
const { handleOnScrollEnd, scrollOffset } = useItemListScrollPersist({
enabled: saveScrollOffset,
});
const { searchTerm } = useSearchTermFilter();
const { query } = usePlaylistSongListFilters();
const { setListData } = useListContext();
const songData = useMemo(() => {
let items = data?.items || [];
const songDataFromData = useMemo(() => {
let list = data?.items || [];
if (searchTerm) {
items = searchLibraryItems(items, searchTerm, LibraryItem.SONG);
return items;
list = searchLibraryItems(list, searchTerm, LibraryItem.SONG);
return list;
}
return sortSongList(items, query.sortBy, query.sortOrder);
return sortSongList(list, query.sortBy, query.sortOrder);
}, [data?.items, searchTerm, query.sortBy, query.sortOrder]);
const { setListData } = useListContext();
const songData = itemsProp ?? songDataFromData;
useEffect(() => {
if (setListData) {
setListData(songData);
if (itemsProp == null && setListData) {
setListData(songDataFromData);
}
}, [songData, setListData]);
}, [itemsProp, songDataFromData, setListData]);
const gridProps = useListSettings(ItemListKey.PLAYLIST_SONG).grid;
@@ -59,9 +72,22 @@ export const PlaylistDetailSongListGrid = forwardRef<any, PlaylistDetailSongList
);
const { enableGridMultiSelect } = useGeneralSettings();
return (
const isPaginated =
typeof currentPage === 'number' &&
typeof itemsPerPage === 'number' &&
typeof onPageChange === 'function';
const totalCount = songData.length;
const pageCount = Math.max(1, Math.ceil(totalCount / (itemsPerPage ?? 1)));
const paginatedData = useMemo(() => {
if (!isPaginated || currentPage == null || itemsPerPage == null) return songData;
const start = currentPage * itemsPerPage;
return songData.slice(start, start + itemsPerPage);
}, [currentPage, isPaginated, itemsPerPage, songData]);
const dataToRender = isPaginated ? paginatedData : songData;
const grid = (
<ItemGridList
data={songData}
data={dataToRender}
enableMultiSelect={enableGridMultiSelect}
gap={gridProps.itemGap}
initialTop={{
@@ -75,5 +101,21 @@ export const PlaylistDetailSongListGrid = forwardRef<any, PlaylistDetailSongList
size={gridProps.size}
/>
);
if (isPaginated && itemsPerPage != null) {
return (
<ItemListWithPagination
currentPage={currentPage!}
itemsPerPage={itemsPerPage}
onChange={onPageChange!}
pageCount={pageCount}
totalItemCount={totalCount}
>
{grid}
</ItemListWithPagination>
);
}
return grid;
},
);