mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-08 04:50:12 +02:00
add folder browsing support (#315)
This commit is contained in:
@@ -4,6 +4,7 @@ import { jfType } from '/@/shared/api/jellyfin/jellyfin-types';
|
||||
import {
|
||||
Album,
|
||||
AlbumArtist,
|
||||
Folder,
|
||||
Genre,
|
||||
LibraryItem,
|
||||
MusicFolder,
|
||||
@@ -496,17 +497,20 @@ const normalizeGenre = (
|
||||
};
|
||||
};
|
||||
|
||||
// const normalizeFolder = (item: any) => {
|
||||
// return {
|
||||
// created: item.DateCreated,
|
||||
// id: item.Id,
|
||||
// image: getCoverArtUrl(item, 150),
|
||||
// isDir: true,
|
||||
// title: item.Name,
|
||||
// type: Item.Folder,
|
||||
// uniqueId: nanoid(),
|
||||
// };
|
||||
// };
|
||||
const normalizeFolder = (
|
||||
item: z.infer<typeof jfType._response.folder>,
|
||||
server: null | ServerListItem,
|
||||
): Folder => {
|
||||
return {
|
||||
_itemType: LibraryItem.FOLDER,
|
||||
_serverId: server?.id || 'unknown',
|
||||
_serverType: ServerType.JELLYFIN,
|
||||
children: undefined,
|
||||
id: item.Id,
|
||||
name: item.Name || 'Unknown folder',
|
||||
parentId: item.ParentId,
|
||||
};
|
||||
};
|
||||
|
||||
// const normalizeScanStatus = () => {
|
||||
// return {
|
||||
@@ -518,6 +522,7 @@ const normalizeGenre = (
|
||||
export const jfNormalize = {
|
||||
album: normalizeAlbum,
|
||||
albumArtist: normalizeAlbumArtist,
|
||||
folder: normalizeFolder,
|
||||
genre: normalizeGenre,
|
||||
musicFolder: normalizeMusicFolder,
|
||||
playlist: normalizePlaylist,
|
||||
|
||||
@@ -487,6 +487,7 @@ const song = z.object({
|
||||
MediaType: z.string(),
|
||||
Name: z.string(),
|
||||
NormalizationGain: z.number().optional(),
|
||||
ParentId: z.string().optional(),
|
||||
ParentIndexNumber: z.number(),
|
||||
People: participant.array().optional(),
|
||||
PlaylistItemId: z.string().optional(),
|
||||
@@ -495,7 +496,7 @@ const song = z.object({
|
||||
ProviderIds: providerIds.optional(),
|
||||
RunTimeTicks: z.number(),
|
||||
ServerId: z.string(),
|
||||
SortName: z.string(),
|
||||
SortName: z.string().optional(),
|
||||
Tags: z.string().array().optional(),
|
||||
Type: z.string(),
|
||||
UserData: userData.optional(),
|
||||
@@ -772,6 +773,34 @@ const filters = z.object({
|
||||
Years: z.number().array().optional(),
|
||||
});
|
||||
|
||||
const folder = z.object({
|
||||
BackdropImageTags: z.array(z.string()),
|
||||
ChannelId: z.null(),
|
||||
CollectionType: z.string(),
|
||||
Id: z.string(),
|
||||
ImageBlurHashes: imageBlurHashes,
|
||||
ImageTags: imageTags,
|
||||
IsFolder: z.boolean(),
|
||||
LocationType: z.string(),
|
||||
MediaType: z.string(),
|
||||
Name: z.string(),
|
||||
ParentId: z.string().optional(),
|
||||
ServerId: z.string(),
|
||||
Type: z.string(),
|
||||
UserData: userData.optional(),
|
||||
});
|
||||
|
||||
const folderList = pagination.extend({
|
||||
Items: z.array(folder),
|
||||
});
|
||||
|
||||
const folderParameters = z.object({
|
||||
Fields: z.string().optional(),
|
||||
ParentId: z.string().optional(),
|
||||
SortBy: z.string().optional(),
|
||||
SortOrder: z.enum(sortOrderValues).optional(),
|
||||
});
|
||||
|
||||
export const jfType = {
|
||||
_enum: {
|
||||
albumArtistList: albumArtistListSort,
|
||||
@@ -794,6 +823,7 @@ export const jfType = {
|
||||
deletePlaylist: deletePlaylistParameters,
|
||||
favorite: favoriteParameters,
|
||||
filterList: filterListParameters,
|
||||
folder: folderParameters,
|
||||
genreList: genreListParameters,
|
||||
musicFolderList: musicFolderListParameters,
|
||||
playlistDetail: playlistDetailParameters,
|
||||
@@ -819,6 +849,8 @@ export const jfType = {
|
||||
error,
|
||||
favorite,
|
||||
filters,
|
||||
folder,
|
||||
folderList,
|
||||
genre,
|
||||
genreList,
|
||||
lyrics,
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
Album,
|
||||
AlbumArtist,
|
||||
ExplicitStatus,
|
||||
Folder,
|
||||
Genre,
|
||||
LibraryItem,
|
||||
Playlist,
|
||||
@@ -342,9 +343,48 @@ const normalizeGenre = (
|
||||
};
|
||||
};
|
||||
|
||||
const normalizeFolder = (
|
||||
item: z.infer<typeof ssType._response.directory>,
|
||||
server?: null | ServerListItemWithCredential,
|
||||
): Folder => {
|
||||
const results = item.child?.reduce(
|
||||
(acc: { folders: Folder[]; songs: Song[] }, item) => {
|
||||
const isDirectory = item.isDir === true;
|
||||
|
||||
if (isDirectory) {
|
||||
const folder = normalizeFolder(item, server);
|
||||
acc.folders.push(folder);
|
||||
} else {
|
||||
const song = normalizeSong(item, server);
|
||||
acc.songs.push(song);
|
||||
}
|
||||
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
folders: [],
|
||||
songs: [],
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
_itemType: LibraryItem.FOLDER,
|
||||
_serverId: server?.id || 'unknown',
|
||||
_serverType: ServerType.SUBSONIC,
|
||||
children: {
|
||||
folders: results?.folders || [],
|
||||
songs: results?.songs || [],
|
||||
},
|
||||
id: item.id.toString(),
|
||||
name: item.title,
|
||||
parentId: item.parent,
|
||||
};
|
||||
};
|
||||
|
||||
export const ssNormalize = {
|
||||
album: normalizeAlbum,
|
||||
albumArtist: normalizeAlbumArtist,
|
||||
folder: normalizeFolder,
|
||||
genre: normalizeGenre,
|
||||
playlist: normalizePlaylist,
|
||||
song: normalizeSong,
|
||||
|
||||
@@ -548,6 +548,50 @@ const albumInfo = z.object({
|
||||
}),
|
||||
});
|
||||
|
||||
const getMusicDirectoryParameters = z.object({
|
||||
id: z.string(),
|
||||
});
|
||||
|
||||
const directory = z.object({
|
||||
artist: z.string().optional(),
|
||||
child: z.array(song).optional(),
|
||||
coverArt: z.string().optional(),
|
||||
id,
|
||||
isDir: z.boolean(),
|
||||
parent: z.string().optional(),
|
||||
title: z.string(),
|
||||
});
|
||||
|
||||
const getMusicDirectory = z.object({
|
||||
directory,
|
||||
});
|
||||
|
||||
const getIndexes = z.object({
|
||||
indexes: z.object({
|
||||
child: z.array(song),
|
||||
index: z
|
||||
.object({
|
||||
artist: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
})
|
||||
.array(),
|
||||
})
|
||||
.array(),
|
||||
shortcut: z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
})
|
||||
.array(),
|
||||
}),
|
||||
});
|
||||
|
||||
const getIndexesParameters = z.object({
|
||||
musicFolderId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const ssType = {
|
||||
_parameters: {
|
||||
albumInfo: albumInfoParameters,
|
||||
@@ -563,6 +607,8 @@ export const ssType = {
|
||||
getArtists: getArtistsParameters,
|
||||
getGenre: getGenresParameters,
|
||||
getGenres: getGenresParameters,
|
||||
getIndexes: getIndexesParameters,
|
||||
getMusicDirectory: getMusicDirectoryParameters,
|
||||
getPlaylist: getPlaylistParameters,
|
||||
getPlaylists: getPlaylistsParameters,
|
||||
getSong: getSongParameters,
|
||||
@@ -591,12 +637,15 @@ export const ssType = {
|
||||
baseResponse,
|
||||
createFavorite,
|
||||
createPlaylist,
|
||||
directory,
|
||||
genre,
|
||||
getAlbum,
|
||||
getAlbumList2,
|
||||
getArtist,
|
||||
getArtists,
|
||||
getGenres,
|
||||
getIndexes,
|
||||
getMusicDirectory,
|
||||
getPlaylist,
|
||||
getPlaylists,
|
||||
getSong,
|
||||
|
||||
@@ -245,6 +245,11 @@ export const sortSongsByFetchedOrder = (
|
||||
fetchedIds: string[],
|
||||
itemType: LibraryItem,
|
||||
): Song[] => {
|
||||
// For folders, songs are already in the correct order
|
||||
if (itemType === LibraryItem.FOLDER) {
|
||||
return songs;
|
||||
}
|
||||
|
||||
// Group songs by the fetched ID they belong to
|
||||
const songsByFetchedId = new Map<string, Song[]>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user