mirror of
https://github.com/jeffvli/feishin.git
synced 2024-11-20 14:37:06 +01:00
Add album detail api
This commit is contained in:
parent
dc6936b22c
commit
f4ba82531c
@ -543,41 +543,6 @@ const getSongCoverArtUrl = (args: { baseUrl: string; item: JFSong; size: number
|
||||
);
|
||||
};
|
||||
|
||||
const normalizeAlbum = (item: JFAlbum, server: ServerListItem, imageSize?: number): Album => {
|
||||
return {
|
||||
albumArtists:
|
||||
item.AlbumArtists?.map((entry) => ({
|
||||
id: entry.Id,
|
||||
name: entry.Name,
|
||||
})) || [],
|
||||
artists: item.ArtistItems?.map((entry) => ({ id: entry.Id, name: entry.Name })),
|
||||
backdropImageUrl: null,
|
||||
createdAt: item.DateCreated,
|
||||
duration: item.RunTimeTicks / 10000000,
|
||||
genres: item.GenreItems?.map((entry) => ({ id: entry.Id, name: entry.Name })),
|
||||
id: item.Id,
|
||||
imagePlaceholderUrl: null,
|
||||
imageUrl: getAlbumCoverArtUrl({
|
||||
baseUrl: server.url,
|
||||
item,
|
||||
size: imageSize || 300,
|
||||
}),
|
||||
isCompilation: null,
|
||||
isFavorite: item.UserData?.IsFavorite || false,
|
||||
lastPlayedAt: null,
|
||||
name: item.Name,
|
||||
playCount: item.UserData?.PlayCount || 0,
|
||||
rating: null,
|
||||
releaseDate: item.PremiereDate?.split('T')[0] || null,
|
||||
releaseYear: item.ProductionYear,
|
||||
serverType: ServerType.JELLYFIN,
|
||||
size: null,
|
||||
songCount: item?.ChildCount || null,
|
||||
uniqueId: nanoid(),
|
||||
updatedAt: item?.DateLastMediaAdded || item.DateCreated,
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeSong = (
|
||||
item: JFSong,
|
||||
server: ServerListItem,
|
||||
@ -627,6 +592,42 @@ const normalizeSong = (
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeAlbum = (item: JFAlbum, server: ServerListItem, imageSize?: number): Album => {
|
||||
return {
|
||||
albumArtists:
|
||||
item.AlbumArtists.map((entry) => ({
|
||||
id: entry.Id,
|
||||
name: entry.Name,
|
||||
})) || [],
|
||||
artists: item.ArtistItems?.map((entry) => ({ id: entry.Id, name: entry.Name })),
|
||||
backdropImageUrl: null,
|
||||
createdAt: item.DateCreated,
|
||||
duration: item.RunTimeTicks / 10000000,
|
||||
genres: item.GenreItems?.map((entry) => ({ id: entry.Id, name: entry.Name })),
|
||||
id: item.Id,
|
||||
imagePlaceholderUrl: null,
|
||||
imageUrl: getAlbumCoverArtUrl({
|
||||
baseUrl: server.url,
|
||||
item,
|
||||
size: imageSize || 300,
|
||||
}),
|
||||
isCompilation: null,
|
||||
isFavorite: item.UserData?.IsFavorite || false,
|
||||
lastPlayedAt: null,
|
||||
name: item.Name,
|
||||
playCount: item.UserData?.PlayCount || 0,
|
||||
rating: null,
|
||||
releaseDate: item.PremiereDate?.split('T')[0] || null,
|
||||
releaseYear: item.ProductionYear,
|
||||
serverType: ServerType.JELLYFIN,
|
||||
size: null,
|
||||
songCount: item?.ChildCount || null,
|
||||
songs: item.songs?.map((song) => normalizeSong(song, server, '', imageSize)),
|
||||
uniqueId: nanoid(),
|
||||
updatedAt: item?.DateLastMediaAdded || item.DateCreated,
|
||||
};
|
||||
};
|
||||
|
||||
// const normalizeArtist = (item: any) => {
|
||||
// return {
|
||||
// album: (item.album || []).map((entry: any) => normalizeAlbum(entry)),
|
||||
|
@ -401,42 +401,6 @@ const getCoverArtUrl = (args: {
|
||||
);
|
||||
};
|
||||
|
||||
const normalizeAlbum = (item: NDAlbum, server: ServerListItem, imageSize?: number): Album => {
|
||||
const imageUrl = getCoverArtUrl({
|
||||
baseUrl: server.url,
|
||||
coverArtId: item.coverArtId,
|
||||
credential: server.credential,
|
||||
size: imageSize || 300,
|
||||
});
|
||||
|
||||
const imagePlaceholderUrl = imageUrl?.replace(/size=\d+/, 'size=50') || null;
|
||||
|
||||
return {
|
||||
albumArtists: [{ id: item.albumArtistId, name: item.albumArtist }],
|
||||
artists: [{ id: item.artistId, name: item.artist }],
|
||||
backdropImageUrl: null,
|
||||
createdAt: item.createdAt.split('T')[0],
|
||||
duration: item.duration || null,
|
||||
genres: item.genres,
|
||||
id: item.id,
|
||||
imagePlaceholderUrl,
|
||||
imageUrl,
|
||||
isCompilation: item.compilation,
|
||||
isFavorite: item.starred,
|
||||
lastPlayedAt: item.playDate ? item.playDate.split('T')[0] : null,
|
||||
name: item.name,
|
||||
playCount: item.playCount,
|
||||
rating: item.rating,
|
||||
releaseDate: new Date(item.minYear, 0, 1).toISOString(),
|
||||
releaseYear: item.minYear,
|
||||
serverType: ServerType.NAVIDROME,
|
||||
size: item.size,
|
||||
songCount: item.songCount,
|
||||
uniqueId: nanoid(),
|
||||
updatedAt: item.updatedAt,
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeSong = (
|
||||
item: NDSong,
|
||||
server: ServerListItem,
|
||||
@ -485,6 +449,44 @@ const normalizeSong = (
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeAlbum = (item: NDAlbum, server: ServerListItem, imageSize?: number): Album => {
|
||||
const imageUrl = getCoverArtUrl({
|
||||
baseUrl: server.url,
|
||||
coverArtId: item.coverArtId,
|
||||
credential: server.credential,
|
||||
size: imageSize || 300,
|
||||
});
|
||||
|
||||
const imagePlaceholderUrl = imageUrl?.replace(/size=\d+/, 'size=50') || null;
|
||||
const imageBackdropUrl = imageUrl?.replace(/size=\d+/, 'size=1000') || null;
|
||||
|
||||
return {
|
||||
albumArtists: [{ id: item.albumArtistId, name: item.albumArtist }],
|
||||
artists: [{ id: item.artistId, name: item.artist }],
|
||||
backdropImageUrl: imageBackdropUrl,
|
||||
createdAt: item.createdAt.split('T')[0],
|
||||
duration: item.duration || null,
|
||||
genres: item.genres,
|
||||
id: item.id,
|
||||
imagePlaceholderUrl,
|
||||
imageUrl,
|
||||
isCompilation: item.compilation,
|
||||
isFavorite: item.starred,
|
||||
lastPlayedAt: item.playDate ? item.playDate.split('T')[0] : null,
|
||||
name: item.name,
|
||||
playCount: item.playCount,
|
||||
rating: item.rating,
|
||||
releaseDate: new Date(item.minYear, 0, 1).toISOString(),
|
||||
releaseYear: item.minYear,
|
||||
serverType: ServerType.NAVIDROME,
|
||||
size: item.size,
|
||||
songCount: item.songCount,
|
||||
songs: item.songs ? item.songs.map((song) => normalizeSong(song, server, '')) : undefined,
|
||||
uniqueId: nanoid(),
|
||||
updatedAt: item.updatedAt,
|
||||
};
|
||||
};
|
||||
|
||||
export const navidromeApi = {
|
||||
authenticate,
|
||||
createPlaylist,
|
||||
|
@ -45,7 +45,7 @@ export type NDAlbum = {
|
||||
starred: boolean;
|
||||
starredAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
} & { songs?: NDSong[] };
|
||||
|
||||
export type NDSong = {
|
||||
album: string;
|
||||
|
@ -9,6 +9,8 @@ import { ndNormalize } from '/@/renderer/api/navidrome.api';
|
||||
import type { NDAlbum, NDGenreList, NDSong } from '/@/renderer/api/navidrome.types';
|
||||
import { SSGenreList, SSMusicFolderList } from '/@/renderer/api/subsonic.types';
|
||||
import type {
|
||||
Album,
|
||||
RawAlbumDetailResponse,
|
||||
RawAlbumListResponse,
|
||||
RawGenreListResponse,
|
||||
RawMusicFolderListResponse,
|
||||
@ -36,6 +38,25 @@ const albumList = (data: RawAlbumListResponse | undefined, server: ServerListIte
|
||||
};
|
||||
};
|
||||
|
||||
const albumDetail = (
|
||||
data: RawAlbumDetailResponse | undefined,
|
||||
server: ServerListItem | null,
|
||||
): Album | undefined => {
|
||||
let album: Album | undefined;
|
||||
switch (server?.type) {
|
||||
case 'jellyfin':
|
||||
album = jfNormalize.album(data as JFAlbum, server);
|
||||
break;
|
||||
case 'navidrome':
|
||||
album = ndNormalize.album(data as NDAlbum, server);
|
||||
break;
|
||||
case 'subsonic':
|
||||
break;
|
||||
}
|
||||
|
||||
return album;
|
||||
};
|
||||
|
||||
const songList = (data: RawSongListResponse | undefined, server: ServerListItem | null) => {
|
||||
let songs;
|
||||
switch (server?.type) {
|
||||
@ -116,6 +137,7 @@ const genreList = (data: RawGenreListResponse | undefined, server: ServerListIte
|
||||
};
|
||||
|
||||
export const normalize = {
|
||||
albumDetail,
|
||||
albumList,
|
||||
genreList,
|
||||
musicFolderList,
|
||||
|
@ -165,7 +165,7 @@ export type Album = {
|
||||
songs?: Song[];
|
||||
uniqueId: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
} & { songs?: Song[] };
|
||||
|
||||
export type Song = {
|
||||
album: string;
|
||||
|
@ -2,15 +2,21 @@ import { useQuery } from '@tanstack/react-query';
|
||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||
import type { QueryOptions } from '/@/renderer/lib/react-query';
|
||||
import { useCurrentServer } from '../../../store/auth.store';
|
||||
import type { AlbumDetailQuery } from '/@/renderer/api/types';
|
||||
import type { AlbumDetailQuery, RawAlbumDetailResponse } from '/@/renderer/api/types';
|
||||
import { controller } from '/@/renderer/api/controller';
|
||||
import { useCallback } from 'react';
|
||||
import { api } from '/@/renderer/api';
|
||||
|
||||
export const useAlbumDetail = (query: AlbumDetailQuery, options: QueryOptions) => {
|
||||
export const useAlbumDetail = (query: AlbumDetailQuery, options?: QueryOptions) => {
|
||||
const server = useCurrentServer();
|
||||
|
||||
return useQuery({
|
||||
queryFn: ({ signal }) => controller.getAlbumDetail({ query, server, signal }),
|
||||
queryKey: queryKeys.albums.detail(server?.id || '', query),
|
||||
select: useCallback(
|
||||
(data: RawAlbumDetailResponse | undefined) => api.normalize.albumDetail(data, server),
|
||||
[server],
|
||||
),
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user