diff --git a/src/renderer/features/artists/components/album-artist-detail-content.tsx b/src/renderer/features/artists/components/album-artist-detail-content.tsx
index 613a5606..304dd33d 100644
--- a/src/renderer/features/artists/components/album-artist-detail-content.tsx
+++ b/src/renderer/features/artists/components/album-artist-detail-content.tsx
@@ -73,6 +73,13 @@ export const AlbumArtistDetailContent = () => {
artistName: detailQuery?.data?.name || '',
})}`;
+ const artistSongsLink = `${generatePath(AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_SONGS, {
+ albumArtistId,
+ })}?${createSearchParams({
+ artistId: albumArtistId,
+ artistName: detailQuery?.data?.name || '',
+ })}`;
+
const recentAlbumsQuery = useAlbumList({
jfParams: server?.type === ServerType.JELLYFIN ? { artistIds: albumArtistId } : undefined,
limit: itemsPerPage,
@@ -85,6 +92,19 @@ export const AlbumArtistDetailContent = () => {
startIndex: 0,
});
+ const compilationAlbumsQuery = useAlbumList({
+ jfParams:
+ server?.type === ServerType.JELLYFIN ? { contributingArtistIds: albumArtistId } : undefined,
+ limit: itemsPerPage,
+ ndParams:
+ server?.type === ServerType.NAVIDROME
+ ? { artist_id: albumArtistId, compilation: true }
+ : undefined,
+ sortBy: AlbumListSort.RELEASE_DATE,
+ sortOrder: SortOrder.DESC,
+ startIndex: 0,
+ });
+
const topSongsQuery = useTopSongsList(
{ artist: detailQuery?.data?.name || '' },
{ enabled: server?.type !== ServerType.JELLYFIN && !!detailQuery?.data?.name },
@@ -136,6 +156,7 @@ export const AlbumArtistDetailContent = () => {
const carousels = [
{
data: recentAlbumsQuery?.data?.items,
+ isHidden: !recentAlbumsQuery?.data?.items?.length,
itemType: LibraryItem.ALBUM,
loading: recentAlbumsQuery?.isLoading || recentAlbumsQuery.isFetching,
pagination: {
@@ -147,7 +168,7 @@ export const AlbumArtistDetailContent = () => {
fw="bold"
order={3}
>
- Recent albums
+ Recent releases
>
),
- uniqueId: 'recentAlbums',
+ uniqueId: 'recentReleases',
+ },
+ {
+ data: compilationAlbumsQuery?.data?.items,
+ isHidden: !compilationAlbumsQuery?.data?.items?.length,
+ itemType: LibraryItem.ALBUM,
+ loading: compilationAlbumsQuery?.isLoading || compilationAlbumsQuery.isFetching,
+ pagination: {
+ itemsPerPage,
+ },
+ title: (
+
+ Appears on
+
+ ),
+ uniqueId: 'compilationAlbums',
},
{
data: detailQuery?.data?.similarArtists?.slice(0, itemsPerPage),
@@ -232,12 +271,10 @@ export const AlbumArtistDetailContent = () => {
const showBiography =
detailQuery?.data?.biography !== undefined && detailQuery?.data?.biography !== null;
const showTopSongs = server?.type !== ServerType.JELLYFIN && topSongsQuery?.data?.items?.length;
- const showGenres = detailQuery?.data?.genres?.length !== 0;
+ const showGenres = detailQuery?.data?.genres ? detailQuery?.data?.genres.length !== 0 : false;
const isLoading =
- detailQuery?.isLoading ||
- recentAlbumsQuery?.isLoading ||
- (server?.type === ServerType.NAVIDROME && topSongsQuery?.isLoading);
+ detailQuery?.isLoading || (server?.type === ServerType.NAVIDROME && topSongsQuery?.isLoading);
if (isLoading) return ;
@@ -297,7 +334,7 @@ export const AlbumArtistDetailContent = () => {
compact
uppercase
component={Link}
- to={generatePath(AppRoute.LIBRARY_ALBUM_ARTISTS_DETAIL_SONGS, { albumArtistId })}
+ to={artistSongsLink}
variant="subtle"
>
View all songs
diff --git a/src/renderer/features/songs/components/jellyfin-song-filters.tsx b/src/renderer/features/songs/components/jellyfin-song-filters.tsx
index aa0e96e6..1bd845d2 100644
--- a/src/renderer/features/songs/components/jellyfin-song-filters.tsx
+++ b/src/renderer/features/songs/components/jellyfin-song-filters.tsx
@@ -96,38 +96,34 @@ export const JellyfinSongFilters = ({ handleFilterChange }: JellyfinSongFiltersP
))}
-
- Year range
-
-
-
-
+
+
+
-
-
- Genres
+
-
+
);
};
diff --git a/src/renderer/features/songs/components/navidrome-song-filters.tsx b/src/renderer/features/songs/components/navidrome-song-filters.tsx
index 89793db6..2736dbce 100644
--- a/src/renderer/features/songs/components/navidrome-song-filters.tsx
+++ b/src/renderer/features/songs/components/navidrome-song-filters.tsx
@@ -59,29 +59,6 @@ export const NavidromeSongFilters = ({ handleFilterChange }: NavidromeSongFilter
return (
-
- Year
-
-
-
-
- Genre
-
-
-
{toggleFilters.map((filter) => (
))}
+
+
+
+
+
);
};
diff --git a/src/renderer/features/songs/components/song-list-content.tsx b/src/renderer/features/songs/components/song-list-content.tsx
index 14fc1315..5e61d3b9 100644
--- a/src/renderer/features/songs/components/song-list-content.tsx
+++ b/src/renderer/features/songs/components/song-list-content.tsx
@@ -19,6 +19,7 @@ import {
VirtualTable,
} from '/@/renderer/components';
import {
+ SongListFilter,
useCurrentServer,
useSetSongTable,
useSetSongTablePagination,
@@ -31,15 +32,16 @@ import debounce from 'lodash/debounce';
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 { LibraryItem, QueueSong, SongListQuery } from '/@/renderer/api/types';
import { usePlayQueueAdd } from '/@/renderer/features/player';
interface SongListContentProps {
+ customFilters?: Partial;
itemCount?: number;
tableRef: MutableRefObject;
}
-export const SongListContent = ({ itemCount, tableRef }: SongListContentProps) => {
+export const SongListContent = ({ customFilters, itemCount, tableRef }: SongListContentProps) => {
const queryClient = useQueryClient();
const server = useCurrentServer();
const page = useSongListStore();
@@ -64,21 +66,20 @@ export const SongListContent = ({ itemCount, tableRef }: SongListContentProps) =
const limit = params.endRow - params.startRow;
const startIndex = params.startRow;
- const queryKey = queryKeys.songs.list(server?.id || '', {
+ const query: SongListQuery = {
limit,
startIndex,
...page.filter,
- });
+ ...customFilters,
+ };
+
+ const queryKey = queryKeys.songs.list(server?.id || '', query);
const songsRes = await queryClient.fetchQuery(
queryKey,
async ({ signal }) =>
api.controller.getSongList({
- query: {
- limit,
- startIndex,
- ...page.filter,
- },
+ query,
server,
signal,
}),
@@ -93,7 +94,7 @@ export const SongListContent = ({ itemCount, tableRef }: SongListContentProps) =
params.api.setDatasource(dataSource);
params.api.ensureIndexVisible(page.table.scrollOffset, 'top');
},
- [page.filter, page.table.scrollOffset, queryClient, server],
+ [customFilters, page.filter, page.table.scrollOffset, queryClient, server],
);
const onPaginationChanged = useCallback(
diff --git a/src/renderer/features/songs/components/song-list-header.tsx b/src/renderer/features/songs/components/song-list-header.tsx
index 5d8bf176..97da27a4 100644
--- a/src/renderer/features/songs/components/song-list-header.tsx
+++ b/src/renderer/features/songs/components/song-list-header.tsx
@@ -1,6 +1,7 @@
import type { 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 { openModal } from '@mantine/modals';
import debounce from 'lodash/debounce';
import { ChangeEvent, MouseEvent, MutableRefObject, useCallback } from 'react';
import {
@@ -89,11 +90,18 @@ const ORDER = [
];
interface SongListHeaderProps {
+ customFilters?: Partial;
itemCount?: number;
tableRef: MutableRefObject;
+ title?: string;
}
-export const SongListHeader = ({ itemCount, tableRef }: SongListHeaderProps) => {
+export const SongListHeader = ({
+ customFilters,
+ title,
+ itemCount,
+ tableRef,
+}: SongListHeaderProps) => {
const server = useCurrentServer();
const page = useSongListStore();
const setPage = useSetSongStore();
@@ -123,21 +131,20 @@ export const SongListHeader = ({ itemCount, tableRef }: SongListHeaderProps) =>
const pageFilters = filters || page.filter;
- const queryKey = queryKeys.songs.list(server?.id || '', {
+ const query: SongListQuery = {
limit,
startIndex,
...pageFilters,
- });
+ ...customFilters,
+ };
+
+ const queryKey = queryKeys.songs.list(server?.id || '', query);
const songsRes = await queryClient.fetchQuery(
queryKey,
async ({ signal }) =>
api.controller.getSongList({
- query: {
- limit,
- startIndex,
- ...pageFilters,
- },
+ query,
server,
signal,
}),
@@ -154,7 +161,7 @@ export const SongListHeader = ({ itemCount, tableRef }: SongListHeaderProps) =>
tableRef.current?.api.ensureIndexVisible(0, 'top');
setPagination({ currentPage: 0 });
},
- [page.filter, server, setPagination, tableRef],
+ [customFilters, page.filter, server, setPagination, tableRef],
);
const handleSetSortBy = useCallback(
@@ -273,6 +280,21 @@ export const SongListHeader = ({ itemCount, tableRef }: SongListHeaderProps) =>
});
};
+ const handleOpenFiltersModal = () => {
+ openModal({
+ children: (
+ <>
+ {server?.type === ServerType.NAVIDROME ? (
+
+ ) : (
+
+ )}
+ >
+ ),
+ title: 'Song Filters',
+ });
+ };
+
return (
- Tracks
+ {title || 'Tracks'}
)}
-
-
-
-
-
- {server?.type === ServerType.NAVIDROME ? (
-
- ) : (
-
- )}
-
-
+