From a07e8e9593eb5e90f0a5e92dcaa85961adcde6fd Mon Sep 17 00:00:00 2001 From: cucadmuh <49571317+cucadmuh@users.noreply.github.com> Date: Wed, 3 Jun 2026 22:23:11 +0300 Subject: [PATCH] fix(composers): keep role-split names in page-local search (#961) * fix(composers): keep role-split names in page-local search Composers browse already loads the Navidrome role-scoped catalog; scoped search now filters that list instead of replacing it with generic artist index/search3 hits that merge split credits into one joined name. Reported by zunoz on the Psysonic Discord (v1.47.0-rc.3). * docs: note Composers scoped-search fix in CHANGELOG (PR #961) --- CHANGELOG.md | 7 +++++++ src/pages/Composers.tsx | 31 +++++++++++++++---------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad53d8bc..b48d8a14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -429,6 +429,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * About the Artist loads bio for each performer; when multiple artist ids are present, tabs switch between their bios, images, and similar artists instead of showing one joined name with a single profile. +### Composers — page search keeps role-split credits + +**By [@cucadmuh](https://github.com/cucadmuh), reported by zunoz on the Psysonic Discord, PR [#961](https://github.com/Psychotoxical/psysonic/pull/961)** + +* Scoped search on Composers no longer replaces the Navidrome role-scoped catalog with generic artist index/search3 hits that merge split composer credits into one joined name and id — results stay split like the scroll overview. + + ### In-page browse — virtual scroll and cover-art priority **By [@cucadmuh](https://github.com/cucadmuh), PR [#783](https://github.com/Psychotoxical/psysonic/pull/783)** diff --git a/src/pages/Composers.tsx b/src/pages/Composers.tsx index 1ff75e91..619c3862 100644 --- a/src/pages/Composers.tsx +++ b/src/pages/Composers.tsx @@ -16,7 +16,6 @@ import { useComposersBrowseFilters, type ComposerBrowseScrollSnapshot } from '.. import { useComposersBrowseScrollRestore } from '../hooks/useComposersBrowseScrollRestore'; import { useArtistsBrowseScrollReset } from '../hooks/useArtistsBrowseScrollReset'; import { useNavigateToComposer } from '../hooks/useNavigateToComposer'; -import { useLibraryIndexStore } from '../store/libraryIndexStore'; import { peekComposerBrowseScrollRestore } from '../store/composerBrowseSessionStore'; import { useScopedBrowseSearchQuery } from '../store/liveSearchScopeStore'; import { readComposerBrowseRestore } from '../utils/navigation/albumDetailNavigation'; @@ -102,6 +101,21 @@ export default function Composers() { const composersSearchQuery = useScopedBrowseSearchQuery('composers'); + // Full composer catalog is loaded via ndListArtistsByRole (Navidrome role stats, + // correctly split multi-name credits). Generic artist index/search3 returns joined + // performer strings — do not race that path on this page (report: zunoz, v1.47 RC3). + const { textSearchLoading, effectiveFilter } = useBrowseArtistTextSearch( + composersSearchQuery, + false, + serverId, + 'composers_browse', + ); + const composerSource = composers; + const textSearchActive = composersSearchQuery.trim().length > 0; + const composerBrowsePlainLayout = + perfFlags.disableMainstageVirtualLists + || textSearchActive; + // Compact tiles + initial-letter only → 200 per page is comfortable. const PAGE_SIZE = 200; const { @@ -114,19 +128,6 @@ export default function Composers() { const navigate = useNavigate(); const navigateToComposer = useNavigateToComposer(); const openContextMenu = usePlayerStore(state => state.openContextMenu); - const indexEnabled = useLibraryIndexStore(s => s.isIndexEnabled(serverId)); - const { textSearchArtists, textSearchLoading, effectiveFilter } = useBrowseArtistTextSearch( - composersSearchQuery, - indexEnabled, - serverId, - 'composers_browse', - ); - const composerSource = textSearchArtists ?? composers; - const textSearchActive = textSearchArtists != null; - const composerBrowsePlainLayout = - perfFlags.disableMainstageVirtualLists - || textSearchActive - || composersSearchQuery.trim().length > 0; const { visibleCount, @@ -300,8 +301,6 @@ export default function Composers() { viewMode, serverId, musicLibraryFilterVersion, - textSearchArtists?.length ?? '', - textSearchArtists?.[0]?.id ?? '', ].join('\0'); useArtistsBrowseScrollReset({