Add top song list for jellyfin

This commit is contained in:
jeffvli 2023-02-27 12:17:22 -08:00
parent f08538cbfb
commit c0a703be7a
7 changed files with 48 additions and 12 deletions

View file

@ -115,7 +115,7 @@ const endpoints: ApiController = {
getPlaylistSongList: jellyfinApi.getPlaylistSongList,
getSongDetail: undefined,
getSongList: jellyfinApi.getSongList,
getTopSongs: undefined,
getTopSongs: jellyfinApi.getTopSongList,
getUserList: undefined,
removeFromPlaylist: jellyfinApi.removeFromPlaylist,
scrobble: jellyfinApi.scrobble,

View file

@ -1,6 +1,6 @@
import ky from 'ky';
import { nanoid } from 'nanoid/non-secure';
import type {
import {
JFAddToPlaylist,
JFAddToPlaylistParams,
JFAlbum,
@ -35,8 +35,9 @@ import type {
JFSongList,
JFSongListParams,
JFSongListResponse,
JFSongListSort,
JFCollectionType,
} from '/@/renderer/api/jellyfin.types';
import { JFCollectionType } from '/@/renderer/api/jellyfin.types';
import {
Album,
AlbumArtist,
@ -72,6 +73,8 @@ import {
AddToPlaylistArgs,
ScrobbleArgs,
RawScrobbleResponse,
TopSongListArgs,
SortOrder,
} from '/@/renderer/api/types';
import { useAuthStore } from '/@/renderer/store';
import { ServerListItem, ServerType } from '/@/renderer/types';
@ -326,6 +329,36 @@ const getAlbumList = async (args: AlbumListArgs): Promise<JFAlbumList> => {
};
};
const getTopSongList = async (args: TopSongListArgs): Promise<any> => {
const { signal, server, query } = args;
const searchParams: any = {
artistIds: query.artistId,
fields: 'Genres, DateCreated, MediaSources, ParentId',
includeItemTypes: 'Audio',
limit: query.limit,
recursive: true,
sortBy: JFSongListSort.COMMUNITY_RATING,
sortOrder: SortOrder.DESC,
userId: server?.userId || '',
};
const data = await api
.get(`users/${server?.userId}/items`, {
headers: { 'X-MediaBrowser-Token': server?.credential },
prefixUrl: server?.url,
searchParams: parseSearchParams(searchParams),
signal,
})
.json<any>();
return {
items: data.Items,
startIndex: 0,
totalRecordCount: data.TotalRecordCount,
};
};
const getSongList = async (args: SongListArgs): Promise<JFSongList> => {
const { query, server, signal } = args;
@ -1007,6 +1040,7 @@ export const jellyfinApi = {
getPlaylistList,
getPlaylistSongList,
getSongList,
getTopSongList,
removeFromPlaylist,
scrobble,
updatePlaylist,

View file

@ -567,6 +567,7 @@ export enum JFSongListSort {
ALBUM = 'Album,SortName',
ALBUM_ARTIST = 'AlbumArtist,Album,SortName',
ARTIST = 'Artist,Album,SortName',
COMMUNITY_RATING = 'CommunityRating,SortName',
DURATION = 'Runtime,AlbumArtist,Album,SortName',
NAME = 'Name,SortName',
PLAY_COUNT = 'PlayCount,SortName',

View file

@ -99,6 +99,7 @@ const topSongList = (data: RawTopSongListResponse | undefined, server: ServerLis
switch (server?.type) {
case 'jellyfin':
songs = data?.items.map((item) => jfNormalize.song(item as JFSong, server, ''));
break;
case 'navidrome':
songs = data?.items?.map((item) => ssNormalize.song(item as SSSong, server, ''));

View file

@ -1009,12 +1009,13 @@ export const userListSortMap: UserListSortMap = {
};
// Top Songs List
export type RawTopSongListResponse = SSTopSongList | undefined;
export type RawTopSongListResponse = SSTopSongList | JFSongList | undefined;
export type TopSongListResponse = BasePaginatedResponse<Song[]>;
export type TopSongListQuery = {
artist: string;
artistId: string;
limit?: number;
};

View file

@ -105,8 +105,8 @@ export const AlbumArtistDetailContent = () => {
});
const topSongsQuery = useTopSongsList(
{ artist: detailQuery?.data?.name || '' },
{ enabled: server?.type !== ServerType.JELLYFIN && !!detailQuery?.data?.name },
{ artist: detailQuery?.data?.name || '', artistId: albumArtistId },
{ enabled: !!detailQuery?.data?.name },
);
const topSongsColumnDefs: ColDef[] = useMemo(
@ -270,11 +270,13 @@ export const AlbumArtistDetailContent = () => {
ARTIST_CONTEXT_MENU_ITEMS,
);
console.log('topSongsQuery?.data :>> ', topSongsQuery?.data);
const topSongs = topSongsQuery?.data?.items?.slice(0, 10);
const showBiography =
detailQuery?.data?.biography !== undefined && detailQuery?.data?.biography !== null;
const showTopSongs = server?.type !== ServerType.JELLYFIN && topSongsQuery?.data?.items?.length;
const showTopSongs = topSongsQuery?.data?.items?.length;
const showGenres = detailQuery?.data?.genres ? detailQuery?.data?.genres.length !== 0 : false;
const isLoading =

View file

@ -6,19 +6,16 @@ import { AlbumArtistDetailTopSongsListHeader } from '/@/renderer/features/artist
import { useAlbumArtistDetail } from '/@/renderer/features/artists/queries/album-artist-detail-query';
import { useTopSongsList } from '/@/renderer/features/artists/queries/top-songs-list-query';
import { AnimatedPage } from '/@/renderer/features/shared';
import { useCurrentServer } from '/@/renderer/store';
import { ServerType } from '/@/renderer/types';
const AlbumArtistDetailTopSongsListRoute = () => {
const tableRef = useRef<AgGridReactType | null>(null);
const { albumArtistId } = useParams() as { albumArtistId: string };
const server = useCurrentServer();
const detailQuery = useAlbumArtistDetail({ id: albumArtistId });
const topSongsQuery = useTopSongsList(
{ artist: detailQuery?.data?.name || '' },
{ enabled: server?.type !== ServerType.JELLYFIN && !!detailQuery?.data?.name },
{ artist: detailQuery?.data?.name || '', artistId: albumArtistId },
{ enabled: !!detailQuery?.data?.name },
);
const itemCount = topSongsQuery?.data?.items?.length || 0;