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 = (
|
const normalizeSong = (
|
||||||
item: JFSong,
|
item: JFSong,
|
||||||
server: ServerListItem,
|
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) => {
|
// const normalizeArtist = (item: any) => {
|
||||||
// return {
|
// return {
|
||||||
// album: (item.album || []).map((entry: any) => normalizeAlbum(entry)),
|
// 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 = (
|
const normalizeSong = (
|
||||||
item: NDSong,
|
item: NDSong,
|
||||||
server: ServerListItem,
|
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 = {
|
export const navidromeApi = {
|
||||||
authenticate,
|
authenticate,
|
||||||
createPlaylist,
|
createPlaylist,
|
||||||
|
@ -45,7 +45,7 @@ export type NDAlbum = {
|
|||||||
starred: boolean;
|
starred: boolean;
|
||||||
starredAt: string;
|
starredAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
} & { songs?: NDSong[] };
|
||||||
|
|
||||||
export type NDSong = {
|
export type NDSong = {
|
||||||
album: string;
|
album: string;
|
||||||
|
@ -9,6 +9,8 @@ import { ndNormalize } from '/@/renderer/api/navidrome.api';
|
|||||||
import type { NDAlbum, NDGenreList, NDSong } from '/@/renderer/api/navidrome.types';
|
import type { NDAlbum, NDGenreList, NDSong } from '/@/renderer/api/navidrome.types';
|
||||||
import { SSGenreList, SSMusicFolderList } from '/@/renderer/api/subsonic.types';
|
import { SSGenreList, SSMusicFolderList } from '/@/renderer/api/subsonic.types';
|
||||||
import type {
|
import type {
|
||||||
|
Album,
|
||||||
|
RawAlbumDetailResponse,
|
||||||
RawAlbumListResponse,
|
RawAlbumListResponse,
|
||||||
RawGenreListResponse,
|
RawGenreListResponse,
|
||||||
RawMusicFolderListResponse,
|
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) => {
|
const songList = (data: RawSongListResponse | undefined, server: ServerListItem | null) => {
|
||||||
let songs;
|
let songs;
|
||||||
switch (server?.type) {
|
switch (server?.type) {
|
||||||
@ -116,6 +137,7 @@ const genreList = (data: RawGenreListResponse | undefined, server: ServerListIte
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const normalize = {
|
export const normalize = {
|
||||||
|
albumDetail,
|
||||||
albumList,
|
albumList,
|
||||||
genreList,
|
genreList,
|
||||||
musicFolderList,
|
musicFolderList,
|
||||||
|
@ -165,7 +165,7 @@ export type Album = {
|
|||||||
songs?: Song[];
|
songs?: Song[];
|
||||||
uniqueId: string;
|
uniqueId: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
};
|
} & { songs?: Song[] };
|
||||||
|
|
||||||
export type Song = {
|
export type Song = {
|
||||||
album: string;
|
album: string;
|
||||||
|
@ -2,15 +2,21 @@ import { useQuery } from '@tanstack/react-query';
|
|||||||
import { queryKeys } from '/@/renderer/api/query-keys';
|
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||||
import type { QueryOptions } from '/@/renderer/lib/react-query';
|
import type { QueryOptions } from '/@/renderer/lib/react-query';
|
||||||
import { useCurrentServer } from '../../../store/auth.store';
|
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 { 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();
|
const server = useCurrentServer();
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryFn: ({ signal }) => controller.getAlbumDetail({ query, server, signal }),
|
queryFn: ({ signal }) => controller.getAlbumDetail({ query, server, signal }),
|
||||||
queryKey: queryKeys.albums.detail(server?.id || '', query),
|
queryKey: queryKeys.albums.detail(server?.id || '', query),
|
||||||
|
select: useCallback(
|
||||||
|
(data: RawAlbumDetailResponse | undefined) => api.normalize.albumDetail(data, server),
|
||||||
|
[server],
|
||||||
|
),
|
||||||
...options,
|
...options,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user