mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-08 13:00:13 +02:00
support navidrome playlist image upload
This commit is contained in:
@@ -490,6 +490,8 @@ const normalizePlaylist = (
|
||||
item: z.infer<typeof ndType._response.playlist>,
|
||||
server?: null | ServerListItem,
|
||||
): Playlist => {
|
||||
const imageId = !item.uploadedImage ? item.id : `pl-${item.id}&square=true&_=${item.updatedAt}`;
|
||||
|
||||
return {
|
||||
_itemType: LibraryItem.PLAYLIST,
|
||||
_serverId: server?.id || 'unknown',
|
||||
@@ -498,7 +500,7 @@ const normalizePlaylist = (
|
||||
duration: item.duration * 1000,
|
||||
genres: [],
|
||||
id: item.id,
|
||||
imageId: item.id,
|
||||
imageId,
|
||||
imageUrl: null,
|
||||
name: item.name,
|
||||
owner: item.ownerName,
|
||||
@@ -508,6 +510,7 @@ const normalizePlaylist = (
|
||||
size: item.size,
|
||||
songCount: item.songCount,
|
||||
sync: item.sync,
|
||||
uploadedImage: item.uploadedImage,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -624,6 +624,7 @@ const playlist = z.object({
|
||||
songCount: z.number(),
|
||||
sync: z.boolean(),
|
||||
updatedAt: z.string(),
|
||||
uploadedImage: z.string().optional(),
|
||||
});
|
||||
|
||||
const playlistList = z.array(playlist);
|
||||
@@ -659,6 +660,18 @@ const updatePlaylist = playlist;
|
||||
|
||||
const updatePlaylistParameters = createPlaylistParameters.partial();
|
||||
|
||||
const uploadPlaylistImage = z.object({
|
||||
status: z.string(),
|
||||
});
|
||||
|
||||
const uploadPlaylistImageParameters = z.object({
|
||||
image: z.instanceof(Uint8Array),
|
||||
});
|
||||
|
||||
const deletePlaylistImage = z.object({
|
||||
status: z.string(),
|
||||
});
|
||||
|
||||
const deletePlaylist = z.null();
|
||||
|
||||
const addToPlaylist = z.object({
|
||||
@@ -760,6 +773,7 @@ export const ndType = {
|
||||
songList: songListParameters,
|
||||
tagList: tagListParameters,
|
||||
updatePlaylist: updatePlaylistParameters,
|
||||
uploadPlaylistImage: uploadPlaylistImageParameters,
|
||||
userList: userListParameters,
|
||||
},
|
||||
_response: {
|
||||
@@ -771,6 +785,7 @@ export const ndType = {
|
||||
authenticate,
|
||||
createPlaylist,
|
||||
deletePlaylist,
|
||||
deletePlaylistImage,
|
||||
error,
|
||||
genre,
|
||||
genreList,
|
||||
@@ -787,6 +802,7 @@ export const ndType = {
|
||||
songList,
|
||||
tagList,
|
||||
updatePlaylist,
|
||||
uploadPlaylistImage,
|
||||
user,
|
||||
userList,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import {
|
||||
FileButton as MantineFileButton,
|
||||
FileButtonProps as MantineFileButtonProps,
|
||||
} from '@mantine/core';
|
||||
import { CSSProperties } from 'react';
|
||||
|
||||
export interface FileButtonProps extends MantineFileButtonProps {
|
||||
maxWidth?: CSSProperties['maxWidth'];
|
||||
width?: CSSProperties['width'];
|
||||
}
|
||||
|
||||
export const FileButton = MantineFileButton;
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
LuArrowUpToLine,
|
||||
LuBookOpen,
|
||||
LuBraces,
|
||||
LuCamera,
|
||||
LuCheck,
|
||||
LuChevronDown,
|
||||
LuChevronLast,
|
||||
@@ -41,7 +42,6 @@ import {
|
||||
LuCloudDownload,
|
||||
LuCornerDownRight,
|
||||
LuCornerUpRight,
|
||||
LuDelete,
|
||||
LuDisc,
|
||||
LuDisc3,
|
||||
LuDownload,
|
||||
@@ -117,6 +117,7 @@ import {
|
||||
LuTable,
|
||||
LuTimer,
|
||||
LuTimerOff,
|
||||
LuTrash,
|
||||
LuTriangleAlert,
|
||||
LuUpload,
|
||||
LuUser,
|
||||
@@ -248,7 +249,7 @@ export const AppIcon = {
|
||||
check: LuCheck,
|
||||
clipboardCopy: LuClipboardCopy,
|
||||
collection: LuPackage2,
|
||||
delete: LuDelete,
|
||||
delete: LuTrash,
|
||||
disc: LuDisc,
|
||||
download: LuDownload,
|
||||
dragHorizontal: LuGripHorizontal,
|
||||
@@ -351,6 +352,7 @@ export const AppIcon = {
|
||||
unfavorite: LuHeartCrack,
|
||||
unpin: LuPinOff,
|
||||
upload: LuUpload,
|
||||
uploadImage: LuCamera,
|
||||
user: LuUser,
|
||||
userManage: LuUserRoundCog,
|
||||
visibility: MdOutlineVisibility,
|
||||
|
||||
@@ -344,6 +344,7 @@ export type Playlist = {
|
||||
size: null | number;
|
||||
songCount: null | number;
|
||||
sync?: boolean | null;
|
||||
uploadedImage?: string;
|
||||
};
|
||||
|
||||
export type RelatedAlbumArtist = {
|
||||
@@ -968,6 +969,16 @@ export type DeletePlaylistArgs = BaseEndpointArgs & {
|
||||
query: DeletePlaylistQuery;
|
||||
};
|
||||
|
||||
export type DeletePlaylistImageArgs = BaseEndpointArgs & {
|
||||
query: DeletePlaylistImageQuery;
|
||||
};
|
||||
|
||||
export type DeletePlaylistImageQuery = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type DeletePlaylistImageResponse = boolean;
|
||||
|
||||
export type DeletePlaylistQuery = { id: string };
|
||||
|
||||
// Delete Playlist
|
||||
@@ -1106,6 +1117,21 @@ export type UpdatePlaylistQuery = {
|
||||
// Update Playlist
|
||||
export type UpdatePlaylistResponse = null | undefined;
|
||||
|
||||
export type UploadPlaylistImageArgs = BaseEndpointArgs & {
|
||||
body: UploadPlaylistImageBody;
|
||||
query: UploadPlaylistImageQuery;
|
||||
};
|
||||
|
||||
export type UploadPlaylistImageBody = {
|
||||
image: Uint8Array;
|
||||
};
|
||||
|
||||
export type UploadPlaylistImageQuery = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type UploadPlaylistImageResponse = boolean;
|
||||
|
||||
type PlaylistListSortMap = {
|
||||
jellyfin: Record<PlaylistListSort, JFPlaylistListSort | undefined>;
|
||||
navidrome: Record<PlaylistListSort, NDPlaylistListSort | undefined>;
|
||||
@@ -1390,6 +1416,7 @@ export type ControllerEndpoint = {
|
||||
args: DeleteInternetRadioStationArgs,
|
||||
) => Promise<DeleteInternetRadioStationResponse>;
|
||||
deletePlaylist: (args: DeletePlaylistArgs) => Promise<DeletePlaylistResponse>;
|
||||
deletePlaylistImage?: (args: DeletePlaylistImageArgs) => Promise<DeletePlaylistImageResponse>;
|
||||
getAlbumArtistDetail: (args: AlbumArtistDetailArgs) => Promise<AlbumArtistDetailResponse>;
|
||||
getAlbumArtistInfo?: (args: AlbumArtistInfoArgs) => Promise<AlbumArtistInfoResponse | null>;
|
||||
getAlbumArtistList: (args: AlbumArtistListArgs) => Promise<AlbumArtistListResponse>;
|
||||
@@ -1443,6 +1470,7 @@ export type ControllerEndpoint = {
|
||||
args: UpdateInternetRadioStationArgs,
|
||||
) => Promise<UpdateInternetRadioStationResponse>;
|
||||
updatePlaylist: (args: UpdatePlaylistArgs) => Promise<UpdatePlaylistResponse>;
|
||||
uploadPlaylistImage?: (args: UploadPlaylistImageArgs) => Promise<UploadPlaylistImageResponse>;
|
||||
};
|
||||
|
||||
export type DownloadArgs = BaseEndpointArgs & {
|
||||
@@ -1515,6 +1543,9 @@ export type InternalControllerEndpoint = {
|
||||
deletePlaylist: (
|
||||
args: ReplaceApiClientProps<DeletePlaylistArgs>,
|
||||
) => Promise<DeletePlaylistResponse>;
|
||||
deletePlaylistImage?: (
|
||||
args: ReplaceApiClientProps<DeletePlaylistImageArgs>,
|
||||
) => Promise<DeletePlaylistImageResponse>;
|
||||
getAlbumArtistDetail: (
|
||||
args: ReplaceApiClientProps<AlbumArtistDetailArgs>,
|
||||
) => Promise<AlbumArtistDetailResponse>;
|
||||
@@ -1599,6 +1630,9 @@ export type InternalControllerEndpoint = {
|
||||
updatePlaylist: (
|
||||
args: ReplaceApiClientProps<UpdatePlaylistArgs>,
|
||||
) => Promise<UpdatePlaylistResponse>;
|
||||
uploadPlaylistImage?: (
|
||||
args: ReplaceApiClientProps<UploadPlaylistImageArgs>,
|
||||
) => Promise<UploadPlaylistImageResponse>;
|
||||
};
|
||||
|
||||
export type LyricGetQuery = {
|
||||
|
||||
@@ -8,6 +8,7 @@ export enum ServerFeature {
|
||||
MUSIC_FOLDER_MULTISELECT = 'musicFolderMultiselect',
|
||||
OS_FORM_POST = 'osFormPost',
|
||||
OS_TRANSCODE_DECISION = 'osTranscodeDecision',
|
||||
PLAYLIST_IMAGE_UPLOAD = 'playlistImageUpload',
|
||||
PLAYLISTS_SMART = 'playlistsSmart',
|
||||
PUBLIC_PLAYLIST = 'publicPlaylist',
|
||||
SERVER_PLAY_QUEUE = 'serverPlayQueue',
|
||||
|
||||
Reference in New Issue
Block a user