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)
This commit is contained in:
cucadmuh
2026-06-03 22:23:11 +03:00
committed by GitHub
parent 4c70408bd6
commit a07e8e9593
2 changed files with 22 additions and 16 deletions
+7
View File
@@ -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)**
+15 -16
View File
@@ -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({