diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ac99738..7acd06e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -289,6 +289,12 @@ Foundational work: faster reviews, narrower diffs, and a safety net under the pa * **Add Station** / **Edit** now mount **`RadioEditModal`** with **`createPortal(..., document.body)`** (same layering approach as **Search Directory**). Previously the overlay lived under nested **`.content-body`** with **`contain: paint`**, so on an **empty** station list the fixed overlay was **painted inside a short box** and looked cropped; after the first station the layout was tall enough that the bug was easy to miss. +### Now Playing — stable list keys on dashboard cards (duplicate React `key` warnings) + +**By [@cucadmuh](https://github.com/cucadmuh), PR [#703](https://github.com/Psychotoxical/psysonic/pull/703)** + +* **Similar artists**, the **track list inside the in-player album card**, and **Top songs** can all include **more than one row with the same Subsonic `id`** (server payloads are not always strictly deduped). Those lists used **`key={id}`**, which triggered **duplicate `key`** warnings in React devtools and made reconciliation depend on row order. Keys now combine **`id` with the list index** — rendering only; **no queue or playback change**. + ### Search — hide duplicate artist hits with zero albums **By [@cucadmuh](https://github.com/cucadmuh), thanks to zunoz for the report on the Psysonic Discord, PR [#697](https://github.com/Psychotoxical/psysonic/pull/697)** diff --git a/src/components/nowPlaying/AlbumCard.tsx b/src/components/nowPlaying/AlbumCard.tsx index 57144abe..544397ce 100644 --- a/src/components/nowPlaying/AlbumCard.tsx +++ b/src/components/nowPlaying/AlbumCard.tsx @@ -69,10 +69,10 @@ const AlbumCard = memo(function AlbumCard({ album, songs, currentTrackId, albumN
- {visibleSongs.map(track => { + {visibleSongs.map((track, idx) => { const isActive = track.id === currentTrackId; return ( -
{isActive diff --git a/src/components/nowPlaying/ArtistCard.tsx b/src/components/nowPlaying/ArtistCard.tsx index 59c5a6ec..21725706 100644 --- a/src/components/nowPlaying/ArtistCard.tsx +++ b/src/components/nowPlaying/ArtistCard.tsx @@ -81,8 +81,8 @@ const ArtistCard = memo(function ArtistCard({ artistName, artistId, artistInfo, {similar.length > 0 && (
- {similar.slice(0, 12).map(a => ( - ( + a.id && onNavigate(`/artist/${a.id}`)} data-tooltip={t('nowPlaying.goToArtist')}> {a.name} diff --git a/src/components/nowPlaying/TopSongsCard.tsx b/src/components/nowPlaying/TopSongsCard.tsx index 239c781a..6975af3f 100644 --- a/src/components/nowPlaying/TopSongsCard.tsx +++ b/src/components/nowPlaying/TopSongsCard.tsx @@ -35,7 +35,7 @@ const TopSongsCard = memo(function TopSongsCard({ artistName, artistId, songs, c {top.map((s, idx) => { const isActive = s.id === currentTrackId; return ( -
onPlay(s)} data-tooltip={t('contextMenu.playNow')}> diff --git a/src/config/settingsCredits.ts b/src/config/settingsCredits.ts index 89f052f9..0b338ad1 100644 --- a/src/config/settingsCredits.ts +++ b/src/config/settingsCredits.ts @@ -110,6 +110,7 @@ const CONTRIBUTOR_ENTRIES = [ 'OpenSubsonic albumArtists in album header; track artists in player bar, mobile, mini + songToTrack (#552) (PR #696)', 'Search: filter search3 artist rows with zero albums (report: zunoz on Psysonic Discord) (PR #697)', 'Internet Radio: portal add/edit station modal to document.body — fixes clipped modal on empty library (report: voidboywannabe on Psysonic Discord) (PR #699)', + 'Now Playing: composite list keys on similar artists, album-card tracklist, and top songs — avoids duplicate React keys when Subsonic repeats ids (PR #703)', ], }, {