add client-side sort to artist favorite songs (#1691)

This commit is contained in:
jeffvli
2026-03-09 20:58:02 -07:00
parent 8825fc1e84
commit 66e7b44d75
3 changed files with 61 additions and 10 deletions
@@ -30,6 +30,7 @@ import {
} from '/@/renderer/features/shared/components/list-config-menu'; } from '/@/renderer/features/shared/components/list-config-menu';
import { import {
CLIENT_SIDE_ALBUM_FILTERS, CLIENT_SIDE_ALBUM_FILTERS,
CLIENT_SIDE_SONG_FILTERS,
ListSortByDropdownControlled, ListSortByDropdownControlled,
} from '/@/renderer/features/shared/components/list-sort-by-dropdown'; } from '/@/renderer/features/shared/components/list-sort-by-dropdown';
import { ListSortOrderToggleButtonControlled } from '/@/renderer/features/shared/components/list-sort-order-toggle-button'; import { ListSortOrderToggleButtonControlled } from '/@/renderer/features/shared/components/list-sort-order-toggle-button';
@@ -57,7 +58,7 @@ import {
useSettingsStore, useSettingsStore,
} from '/@/renderer/store/settings.store'; } from '/@/renderer/store/settings.store';
import { sanitize } from '/@/renderer/utils/sanitize'; import { sanitize } from '/@/renderer/utils/sanitize';
import { sortAlbumList } from '/@/shared/api/utils'; import { sortAlbumList, sortSongList } from '/@/shared/api/utils';
import { ActionIcon, ActionIconGroup } from '/@/shared/components/action-icon/action-icon'; import { ActionIcon, ActionIconGroup } from '/@/shared/components/action-icon/action-icon';
import { Badge } from '/@/shared/components/badge/badge'; import { Badge } from '/@/shared/components/badge/badge';
import { Button } from '/@/shared/components/button/button'; import { Button } from '/@/shared/components/button/button';
@@ -86,6 +87,7 @@ import {
RelatedArtist, RelatedArtist,
ServerType, ServerType,
Song, Song,
SongListSort,
SortOrder, SortOrder,
} from '/@/shared/types/domain-types'; } from '/@/shared/types/domain-types';
import { ItemListKey, ListDisplayType, Play } from '/@/shared/types/types'; import { ItemListKey, ListDisplayType, Play } from '/@/shared/types/types';
@@ -615,6 +617,14 @@ const AlbumArtistMetadataFavoriteSongs = ({
const { t } = useTranslation(); const { t } = useTranslation();
const [searchTerm, setSearchTerm] = useState(''); const [searchTerm, setSearchTerm] = useState('');
const [debouncedSearchTerm] = useDebouncedValue(searchTerm, 300); const [debouncedSearchTerm] = useDebouncedValue(searchTerm, 300);
const albumArtistDetailFavoriteSongsSort = useAppStore(
(state) => state.albumArtistDetailFavoriteSongsSort,
);
const setAlbumArtistDetailFavoriteSongsSort = useAppStore(
(state) => state.actions.setAlbumArtistDetailFavoriteSongsSort,
);
const sortBy = albumArtistDetailFavoriteSongsSort.sortBy;
const sortOrder = albumArtistDetailFavoriteSongsSort.sortOrder;
const tableConfig = useSettingsStore((state) => state.lists[ItemListKey.SONG]?.table); const tableConfig = useSettingsStore((state) => state.lists[ItemListKey.SONG]?.table);
const currentSong = usePlayerSong(); const currentSong = usePlayerSong();
const player = usePlayer(); const player = usePlayer();
@@ -639,8 +649,12 @@ const AlbumArtistMetadataFavoriteSongs = ({
}, [tableConfig?.columns]); }, [tableConfig?.columns]);
const filteredSongs = useMemo(() => { const filteredSongs = useMemo(() => {
return searchLibraryItems(songs, debouncedSearchTerm, LibraryItem.SONG); return sortSongList(
}, [songs, debouncedSearchTerm]); searchLibraryItems(songs, debouncedSearchTerm, LibraryItem.SONG),
sortBy,
sortOrder,
);
}, [songs, debouncedSearchTerm, sortBy, sortOrder]);
const { handleColumnReordered } = useItemListColumnReorder({ const { handleColumnReordered } = useItemListColumnReorder({
itemListKey: ItemListKey.SONG, itemListKey: ItemListKey.SONG,
@@ -798,6 +812,26 @@ const AlbumArtistMetadataFavoriteSongs = ({
}} }}
value={searchTerm} value={searchTerm}
/> />
<ListSortByDropdownControlled
filters={CLIENT_SIDE_SONG_FILTERS}
itemType={LibraryItem.SONG}
setSortBy={(value) =>
setAlbumArtistDetailFavoriteSongsSort(
value as SongListSort,
sortOrder,
)
}
sortBy={sortBy}
/>
<ListSortOrderToggleButtonControlled
setSortOrder={(value) =>
setAlbumArtistDetailFavoriteSongsSort(
sortBy,
value as SortOrder,
)
}
sortOrder={sortOrder}
/>
<ListConfigMenu <ListConfigMenu
displayTypes={[ displayTypes={[
{ hidden: true, value: ListDisplayType.GRID }, { hidden: true, value: ListDisplayType.GRID },
+18 -1
View File
@@ -6,11 +6,12 @@ import { devtools, persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer'; import { immer } from 'zustand/middleware/immer';
import { createWithEqualityFn } from 'zustand/traditional'; import { createWithEqualityFn } from 'zustand/traditional';
import { AlbumListSort, SortOrder } from '/@/shared/types/domain-types'; import { AlbumListSort, SongListSort, SortOrder } from '/@/shared/types/domain-types';
import { Platform } from '/@/shared/types/types'; import { Platform } from '/@/shared/types/types';
export interface AppSlice extends AppState { export interface AppSlice extends AppState {
actions: { actions: {
setAlbumArtistDetailFavoriteSongsSort: (sortBy: SongListSort, sortOrder: SortOrder) => void;
setAlbumArtistDetailGroupingType: (groupingType: 'all' | 'primary') => void; setAlbumArtistDetailGroupingType: (groupingType: 'all' | 'primary') => void;
setAlbumArtistDetailSort: (sortBy: AlbumListSort, sortOrder: SortOrder) => void; setAlbumArtistDetailSort: (sortBy: AlbumListSort, sortOrder: SortOrder) => void;
setAlbumArtistIdsMode: (mode: 'and' | 'or') => void; setAlbumArtistIdsMode: (mode: 'and' | 'or') => void;
@@ -30,6 +31,10 @@ export interface AppSlice extends AppState {
} }
export interface AppState { export interface AppState {
albumArtistDetailFavoriteSongsSort: {
sortBy: SongListSort;
sortOrder: SortOrder;
};
albumArtistDetailSort: { albumArtistDetailSort: {
groupingType: 'all' | 'primary'; groupingType: 'all' | 'primary';
sortBy: AlbumListSort; sortBy: AlbumListSort;
@@ -83,6 +88,14 @@ export const useAppStore = createWithEqualityFn<AppSlice>()(
devtools( devtools(
immer((set, get) => ({ immer((set, get) => ({
actions: { actions: {
setAlbumArtistDetailFavoriteSongsSort: (sortBy, sortOrder) => {
set((state) => {
state.albumArtistDetailFavoriteSongsSort = {
sortBy,
sortOrder,
};
});
},
setAlbumArtistDetailGroupingType: (groupingType) => { setAlbumArtistDetailGroupingType: (groupingType) => {
set((state) => { set((state) => {
state.albumArtistDetailSort.groupingType = groupingType; state.albumArtistDetailSort.groupingType = groupingType;
@@ -161,6 +174,10 @@ export const useAppStore = createWithEqualityFn<AppSlice>()(
}); });
}, },
}, },
albumArtistDetailFavoriteSongsSort: {
sortBy: SongListSort.ID,
sortOrder: SortOrder.ASC,
},
albumArtistDetailSort: { albumArtistDetailSort: {
groupingType: 'primary', groupingType: 'primary',
sortBy: AlbumListSort.RELEASE_DATE, sortBy: AlbumListSort.RELEASE_DATE,
+6 -6
View File
@@ -1472,6 +1472,12 @@ export type ImageArgs = BaseEndpointArgs & {
query: ImageQuery; query: ImageQuery;
}; };
export type ImageQuery = {
id: string;
itemType: LibraryItem;
size?: number;
};
export type ImageRequest = { export type ImageRequest = {
cacheKey: string; cacheKey: string;
credentials?: RequestCredentials; credentials?: RequestCredentials;
@@ -1479,12 +1485,6 @@ export type ImageRequest = {
url: string; url: string;
}; };
export type ImageQuery = {
id: string;
itemType: LibraryItem;
size?: number;
};
export type InternalControllerEndpoint = { export type InternalControllerEndpoint = {
addToPlaylist: ( addToPlaylist: (
args: ReplaceApiClientProps<AddToPlaylistArgs>, args: ReplaceApiClientProps<AddToPlaylistArgs>,