diff --git a/src/renderer/features/albums/components/album-detail-content.tsx b/src/renderer/features/albums/components/album-detail-content.tsx index fd44dd779..5c4a5eb53 100644 --- a/src/renderer/features/albums/components/album-detail-content.tsx +++ b/src/renderer/features/albums/components/album-detail-content.tsx @@ -15,6 +15,8 @@ import { albumQueries } from '/@/renderer/features/albums/api/album-api'; import { AlbumInfiniteCarousel } from '/@/renderer/features/albums/components/album-infinite-carousel'; import { usePlayer } from '/@/renderer/features/player/context/player-context'; import { ListConfigMenu } from '/@/renderer/features/shared/components/list-config-menu'; +import { ListSortByDropdownControlled } from '/@/renderer/features/shared/components/list-sort-by-dropdown'; +import { ListSortOrderToggleButtonControlled } from '/@/renderer/features/shared/components/list-sort-order-toggle-button'; import { searchLibraryItems } from '/@/renderer/features/shared/utils'; import { useContainerQuery } from '/@/renderer/hooks'; import { AppRoute } from '/@/renderer/router/routes'; @@ -28,6 +30,7 @@ import { } from '/@/renderer/utils'; import { replaceURLWithHTMLLinks } from '/@/renderer/utils/linkify'; import { normalizeReleaseTypes } from '/@/renderer/utils/normalize-release-types'; +import { sortSongList } from '/@/shared/api/utils'; import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; import { Checkbox } from '/@/shared/components/checkbox/checkbox'; import { Flex } from '/@/shared/components/flex/flex'; @@ -46,6 +49,7 @@ import { ExplicitStatus, LibraryItem, Song, + SongListSort, SortOrder, } from '/@/shared/types/domain-types'; import { ItemListKey, ListDisplayType, Play } from '/@/shared/types/types'; @@ -426,13 +430,20 @@ const AlbumDetailSongsTable = ({ songs }: AlbumDetailSongsTableProps) => { const currentSong = usePlayerSong(); + const [sortBy, setSortBy] = useState(SongListSort.ID); + const [sortOrder, setSortOrder] = useState(SortOrder.ASC); + const columns = useMemo(() => { return tableConfig?.columns || []; }, [tableConfig?.columns]); const filteredSongs = useMemo(() => { - return searchLibraryItems(songs, searchTerm, LibraryItem.SONG); - }, [songs, searchTerm]); + return sortSongList( + searchLibraryItems(songs, searchTerm, LibraryItem.SONG), + sortBy, + sortOrder, + ); + }, [songs, searchTerm, sortBy, sortOrder]); const { handleColumnReordered } = useItemListColumnReorder({ itemListKey: ItemListKey.ALBUM_DETAIL, @@ -484,6 +495,11 @@ const AlbumDetailSongsTable = ({ songs }: AlbumDetailSongsTableProps) => { return undefined; } + // Remove groups when sorting + if (sortBy !== SongListSort.ID) { + return undefined; + } + if (discGroups.length <= 1) { return undefined; } @@ -561,7 +577,7 @@ const AlbumDetailSongsTable = ({ songs }: AlbumDetailSongsTableProps) => { }, rowHeight: 40, })); - }, [discGroups, t, searchTerm]); + }, [searchTerm, sortBy, discGroups, t]); const player = usePlayer(); @@ -630,6 +646,15 @@ const AlbumDetailSongsTable = ({ songs }: AlbumDetailSongsTableProps) => { }} value={searchTerm} /> + setSortBy(value as SongListSort)} + sortBy={sortBy} + /> + setSortOrder(value as SortOrder)} + sortOrder={sortOrder} + /> void; @@ -72,6 +75,57 @@ export const ListSortByDropdown = ({ ); }; +interface ListSortByDropdownControlledProps { + disabled?: boolean; + itemType: LibraryItem; + setSortBy: Dispatch>; + sortBy: string; + target?: React.ReactNode; +} + +export const ListSortByDropdownControlled = ({ + disabled, + itemType, + setSortBy, + sortBy, + target, +}: ListSortByDropdownControlledProps) => { + const server = useCurrentServer(); + + const sortByLabel = + (itemType && FILTERS[itemType][server.type].find((f) => f.value === sortBy)?.name) || '—'; + + const handleSortByChange = (sortBy: string) => { + setSortBy(sortBy); + }; + + return ( + + + {target ? ( + target + ) : ( + + )} + + + {FILTERS[itemType][server.type].map((f) => ( + handleSortByChange(f.value)} + value={f.value} + > + {f.name} + + ))} + + + ); +}; + const CLIENT_SIDE_SONG_FILTERS = [ { defaultOrder: SortOrder.ASC, diff --git a/src/renderer/features/shared/components/list-sort-order-toggle-button.tsx b/src/renderer/features/shared/components/list-sort-order-toggle-button.tsx index 34c09168a..700de236e 100644 --- a/src/renderer/features/shared/components/list-sort-order-toggle-button.tsx +++ b/src/renderer/features/shared/components/list-sort-order-toggle-button.tsx @@ -29,3 +29,25 @@ export const ListSortOrderToggleButton = ({ /> ); }; + +interface ListSortOrderToggleButtonControlledProps { + disabled?: boolean; + setSortOrder: (sortOrder: SortOrder) => void; + sortOrder: SortOrder; +} + +export const ListSortOrderToggleButtonControlled = ({ + disabled, + setSortOrder, + sortOrder, +}: ListSortOrderToggleButtonControlledProps) => { + return ( + + setSortOrder(sortOrder === SortOrder.ASC ? SortOrder.DESC : SortOrder.ASC) + } + sortOrder={sortOrder as SortOrder} + /> + ); +};