diff --git a/src/renderer/api/navidrome/navidrome-normalize.ts b/src/renderer/api/navidrome/navidrome-normalize.ts index c60f1a7f..9e55f3ba 100644 --- a/src/renderer/api/navidrome/navidrome-normalize.ts +++ b/src/renderer/api/navidrome/navidrome-normalize.ts @@ -278,11 +278,25 @@ const normalizeAlbumArtist = ( }); } + let albumCount: number; + let songCount: number; + + if (item.stats) { + albumCount = Math.max( + item.stats.albumartist?.albumCount ?? 0, + item.stats.artist?.albumCount ?? 0, + ); + songCount = Math.max( + item.stats.albumartist?.songCount ?? 0, + item.stats.artist?.songCount ?? 0, + ); + } else { + albumCount = item.albumCount; + songCount = item.songCount; + } + return { - albumCount: Math.max( - item.stats?.albumartist?.albumCount || item.albumCount, - item.stats?.artist?.albumCount || 0, - ), + albumCount, backgroundImageUrl: null, biography: item.biography || null, duration: null, @@ -307,7 +321,7 @@ const normalizeAlbumArtist = ( imageUrl: artist?.artistImageUrl || null, name: artist.name, })) || null, - songCount: item.stats?.albumartist?.songCount || item.songCount, + songCount, userFavorite: item.starred, userRating: item.rating, }; diff --git a/src/renderer/api/subsonic/subsonic-controller.ts b/src/renderer/api/subsonic/subsonic-controller.ts index d987eafd..e84d7775 100644 --- a/src/renderer/api/subsonic/subsonic-controller.ts +++ b/src/renderer/api/subsonic/subsonic-controller.ts @@ -190,7 +190,7 @@ export const SubsonicController: ControllerEndpoint = { return { ...ssNormalize.albumArtist(artist, apiClientProps.server, 300), - albums: artist.album.map((album) => ssNormalize.album(album, apiClientProps.server)), + albums: artist.album?.map((album) => ssNormalize.album(album, apiClientProps.server)), similarArtists: artistInfo?.similarArtist?.map((artist) => ssNormalize.albumArtist(artist, apiClientProps.server, 300), @@ -305,7 +305,7 @@ export const SubsonicController: ControllerEndpoint = { return []; } - return artist.body.artist.album; + return artist.body.artist.album ?? []; }); return { @@ -966,7 +966,7 @@ export const SubsonicController: ControllerEndpoint = { return []; } - return artist.body.artist.album; + return artist.body.artist.album ?? []; }); const albumIds = albums.map((album) => album.id); diff --git a/src/renderer/api/subsonic/subsonic-types.ts b/src/renderer/api/subsonic/subsonic-types.ts index 8ce91cc7..35fae9f4 100644 --- a/src/renderer/api/subsonic/subsonic-types.ts +++ b/src/renderer/api/subsonic/subsonic-types.ts @@ -156,7 +156,7 @@ const albumListParameters = z.object({ const albumList = z.array(album.omit({ song: true })); const albumArtist = z.object({ - album: z.array(album), + album: z.array(album).optional(), albumCount: z.string(), artistImageUrl: z.string().optional(), coverArt: z.string().optional(), diff --git a/src/renderer/features/artists/components/album-artist-detail-header.tsx b/src/renderer/features/artists/components/album-artist-detail-header.tsx index 647eb800..b273e9c5 100644 --- a/src/renderer/features/artists/components/album-artist-detail-header.tsx +++ b/src/renderer/features/artists/components/album-artist-detail-header.tsx @@ -28,25 +28,29 @@ export const AlbumArtistDetailHeader = forwardRef( serverId: server?.id, }); + const albumCount = detailQuery?.data?.albumCount; + const songCount = detailQuery?.data?.songCount; + const duration = detailQuery?.data?.duration; + const durationEnabled = duration !== null && duration !== undefined; + const metadataItems = [ { - enabled: detailQuery?.data?.albumCount, + enabled: albumCount !== null && albumCount !== undefined, id: 'albumCount', secondary: false, - value: t('entity.albumWithCount', { count: detailQuery?.data?.albumCount || 0 }), + value: t('entity.albumWithCount', { count: albumCount || 0 }), }, { - enabled: detailQuery?.data?.songCount, + enabled: songCount !== null && songCount !== undefined, id: 'songCount', secondary: false, - value: t('entity.trackWithCount', { count: detailQuery?.data?.songCount || 0 }), + value: t('entity.trackWithCount', { count: songCount || 0 }), }, { - enabled: detailQuery.data?.duration, + enabled: durationEnabled, id: 'duration', secondary: true, - value: - detailQuery?.data?.duration && formatDurationString(detailQuery.data.duration), + value: durationEnabled && formatDurationString(duration), }, ]; diff --git a/src/renderer/features/search/components/command-palette.tsx b/src/renderer/features/search/components/command-palette.tsx index 64ff8510..d239f1bf 100644 --- a/src/renderer/features/search/components/command-palette.tsx +++ b/src/renderer/features/search/components/command-palette.tsx @@ -2,6 +2,7 @@ import { useCallback, useState, Fragment, useRef } from 'react'; import { ActionIcon, Group, Kbd, ScrollArea } from '@mantine/core'; import { useDisclosure, useDebouncedValue } from '@mantine/hooks'; +import { useTranslation } from 'react-i18next'; import { RiSearchLine, RiCloseFill } from 'react-icons/ri'; import { generatePath, useNavigate } from 'react-router'; import styled from 'styled-components'; @@ -37,6 +38,7 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => { const activePage = pages[pages.length - 1]; const isHome = activePage === CommandPalettePages.HOME; const searchInputRef = useRef(null); + const { t } = useTranslation(); const popPage = useCallback(() => { setPages((pages) => { @@ -187,13 +189,17 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => { }} > 0 - ? `${artist.albumCount} albums` + artist?.albumCount !== undefined && + artist?.albumCount !== null + ? t('entity.albumWithCount', { + count: artist.albumCount, + }) : undefined } title={artist.name} diff --git a/src/renderer/features/search/components/library-command-item.tsx b/src/renderer/features/search/components/library-command-item.tsx index 380cc09b..0cac83ec 100644 --- a/src/renderer/features/search/components/library-command-item.tsx +++ b/src/renderer/features/search/components/library-command-item.tsx @@ -53,6 +53,7 @@ const StyledImage = styled.img` const ActionsContainer = styled(Flex)``; interface LibraryCommandItemProps { + disabled?: boolean; handlePlayQueueAdd?: (options: PlayQueueAddOptions) => void; id: string; imageUrl: string | null; @@ -62,6 +63,7 @@ interface LibraryCommandItemProps { } export const LibraryCommandItem = ({ + disabled, id, imageUrl, subtitle, @@ -154,6 +156,7 @@ export const LibraryCommandItem = ({ >