diff --git a/src/renderer/features/context-menu/context-menu-items.tsx b/src/renderer/features/context-menu/context-menu-items.tsx index 9adfbd0a..8b5a622d 100644 --- a/src/renderer/features/context-menu/context-menu-items.tsx +++ b/src/renderer/features/context-menu/context-menu-items.tsx @@ -109,5 +109,6 @@ export const PLAYLIST_CONTEXT_MENU_ITEMS: SetContextMenuItems = [ { id: 'playNext' }, { divider: true, id: 'playShuffled' }, { divider: true, id: 'shareItem' }, - { id: 'deletePlaylist' }, + { divider: true, id: 'deletePlaylist' }, + { divider: true, id: 'showDetails' }, ]; diff --git a/src/renderer/features/item-details/components/item-details-modal.tsx b/src/renderer/features/item-details/components/item-details-modal.tsx index 7d8b95a6..f54ccf7f 100644 --- a/src/renderer/features/item-details/components/item-details-modal.tsx +++ b/src/renderer/features/item-details/components/item-details-modal.tsx @@ -20,12 +20,13 @@ import { AlbumArtist, AnyLibraryItem, LibraryItem, + Playlist, RelatedArtist, Song, } from '/@/shared/types/domain-types'; export type ItemDetailsModalProps = { - item: Album | AlbumArtist | Song; + item: Album | AlbumArtist | Playlist | Song; }; type ItemDetailRow = { @@ -90,9 +91,13 @@ const formatArtists = (artists: null | RelatedArtist[] | undefined) => const formatComment = (item: Album | Song) => item.comment ? {replaceURLWithHTMLLinks(item.comment)} : null; -const FormatGenre = (item: Album | AlbumArtist | Song) => { +const FormatGenre = (item: Album | AlbumArtist | Playlist | Song) => { const genreRoute = useGenreRoute(); + if (!item.genres?.length) { + return null; + } + return item.genres?.map((genre, index) => ( {index > 0 && } @@ -158,6 +163,7 @@ const AlbumPropertyMapping: ItemDetailRow[] = [ ) : null, }, + { key: 'id', label: 'filter.id' }, ]; const AlbumArtistPropertyMapping: ItemDetailRow[] = [ @@ -202,6 +208,30 @@ const AlbumArtistPropertyMapping: ItemDetailRow[] = [ /> ) : null, }, + { key: 'id', label: 'filter.id' }, +]; + +const PlaylistPropertyMapping: ItemDetailRow[] = [ + { key: 'name', label: 'common.title' }, + { key: 'description', label: 'common.description' }, + { label: 'entity.genre_other', render: FormatGenre }, + { + label: 'common.duration', + render: (playlist) => playlist.duration && formatDurationString(playlist.duration), + }, + { key: 'songCount', label: 'filter.songCount' }, + { + key: 'size', + label: 'common.size', + render: (playlist) => playlist.size && formatSizeString(playlist.size), + }, + { key: 'owner', label: 'common.owner' }, + { key: 'public', label: 'form.createPlaylist.input_public' }, + { + label: 'entity.smartPlaylist', + render: (playlist) => (playlist.rules ? BoolField(true) : null), + }, + { key: 'id', label: 'filter.id' }, ]; const SongPropertyMapping: ItemDetailRow[] = [ @@ -277,6 +307,7 @@ const SongPropertyMapping: ItemDetailRow[] = [ render: (song) => (song.peak?.track !== undefined ? `${song.peak.track}` : null), }, { label: 'filter.comment', render: formatComment }, + { key: 'id', label: 'filter.id' }, ]; const handleTags = (item: Album | Song, t: TFunction) => { @@ -358,6 +389,9 @@ export const ItemDetailsModal = ({ item }: ItemDetailsModalProps) => { case LibraryItem.ALBUM_ARTIST: body = AlbumArtistPropertyMapping.map((rule) => handleRow(t, item, rule)); break; + case LibraryItem.PLAYLIST: + body = PlaylistPropertyMapping.map((rule) => handleRow(t, item, rule)); + break; case LibraryItem.SONG: body = SongPropertyMapping.map((rule) => handleRow(t, item, rule)); body.push(...handleParticipants(item, t)); @@ -372,7 +406,7 @@ export const ItemDetailsModal = ({ item }: ItemDetailsModalProps) => { {body} diff --git a/src/shared/api/subsonic/subsonic-normalize.ts b/src/shared/api/subsonic/subsonic-normalize.ts index 111f0193..5a400eb1 100644 --- a/src/shared/api/subsonic/subsonic-normalize.ts +++ b/src/shared/api/subsonic/subsonic-normalize.ts @@ -285,7 +285,7 @@ const normalizePlaylist = ( ): Playlist => { return { description: item.comment || null, - duration: item.duration, + duration: item.duration * 1000, genres: [], id: item.id.toString(), imagePlaceholderUrl: null,