Show collection bars + Top Tracks for source artists, upgrade source clicks to library when possible
Three issues from screenshots: 1. .collection-overview was hidden for source artists (CSS rule too aggressive). It actually renders fine — just shows 0/N "missing" for each release type, which is useful info. Removed from the hide rules. 2. #artist-hero-sidebar (Top Tracks "Popular on Last.fm") was also hidden. The renderer (_loadArtistTopTracks in library.js) already fetches by artist name via /api/artist/0/lastfm-top-tracks, so it works for source artists too. Removed from the hide rules. 3. Clicking a source-artist result for someone you ALREADY have in the library was loading the bare source view instead of the library view (bug). Backend now does a "library upgrade" lookup in get_artist_detail: when the direct ID lookup misses but a source param is provided, search the artists table by the source- specific ID column (deezer_id / spotify_artist_id / etc.). If a match exists, use that library PK and the rest of the library path runs normally — owned releases, enrichment, completion bars, all the goodies you'd see if you'd clicked from Library. Falls back to a name match within the active server, then to the source-only response if nothing matches. The remaining library-only items (artist-enrichment-coverage, Radio button, Enhance Quality button) stay hidden for source artists since they all require owned tracks.
This commit is contained in:
parent
5c94b87aea
commit
9106617538
2 changed files with 70 additions and 10 deletions
|
|
@ -11331,6 +11331,51 @@ _SOURCE_ID_FIELD = {
|
|||
}
|
||||
|
||||
|
||||
def _find_library_artist_for_source(database, source, source_artist_id, artist_name):
|
||||
"""Try to upgrade a source-artist click to a library lookup.
|
||||
|
||||
Returns the library PK of an artist that matches either the source-specific
|
||||
ID column (e.g. WHERE deezer_id = source_artist_id) or, as a fallback, the
|
||||
artist name in the active server. Returns None if no match.
|
||||
"""
|
||||
column = _SOURCE_ID_FIELD.get(source)
|
||||
if not column:
|
||||
return None
|
||||
try:
|
||||
with database._get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
# Match by source-specific ID column. Server-source-agnostic: any
|
||||
# library record (Plex/Jellyfin/Navidrome/SoulSync) that has the
|
||||
# right external ID is a hit.
|
||||
cursor.execute(
|
||||
f"SELECT id, name FROM artists WHERE {column} = ? LIMIT 1",
|
||||
(str(source_artist_id),)
|
||||
)
|
||||
row = cursor.fetchone()
|
||||
if row:
|
||||
return row[0]
|
||||
|
||||
# Fallback: case-insensitive name match within the active server only,
|
||||
# to avoid jumping the user across server contexts unintentionally.
|
||||
if artist_name:
|
||||
try:
|
||||
active_server = config_manager.get_active_media_server()
|
||||
except Exception:
|
||||
active_server = None
|
||||
if active_server:
|
||||
cursor.execute(
|
||||
"SELECT id FROM artists "
|
||||
"WHERE LOWER(name) = LOWER(?) AND server_source = ? LIMIT 1",
|
||||
(artist_name, active_server)
|
||||
)
|
||||
row = cursor.fetchone()
|
||||
if row:
|
||||
return row[0]
|
||||
except Exception as e:
|
||||
logger.debug(f"Library upgrade lookup failed for {source}:{source_artist_id}: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def _build_source_only_artist_detail(artist_id, artist_name, source):
|
||||
"""Synthesize an artist-detail response from a single metadata source for an
|
||||
artist that isn't in the local library. Used when `/api/artist-detail/<id>`
|
||||
|
|
@ -11514,9 +11559,26 @@ def get_artist_detail(artist_id):
|
|||
# Get artist discography from database
|
||||
db_result = database.get_artist_discography(artist_id)
|
||||
|
||||
# Library upgrade: if direct ID lookup missed AND we have a source hint,
|
||||
# check whether the user already owns this artist in the library under
|
||||
# a different ID (e.g. clicking a Deezer search result for an artist
|
||||
# they have indexed in Plex). Prefer the library record so they get
|
||||
# all their owned releases + enrichment instead of a bare source view.
|
||||
if not db_result.get('success') and source_param in _SOURCE_ONLY_ARTIST_SOURCES:
|
||||
library_pk = _find_library_artist_for_source(
|
||||
database, source_param, artist_id, artist_name_arg
|
||||
)
|
||||
if library_pk:
|
||||
logger.info(
|
||||
f"Source-id {source_param}:{artist_id} matched library artist "
|
||||
f"PK={library_pk} — upgrading to library response"
|
||||
)
|
||||
db_result = database.get_artist_discography(library_pk)
|
||||
|
||||
if not db_result.get('success'):
|
||||
# Library lookup failed. If a metadata source was specified, fall back
|
||||
# to a source-only response so the page can render a non-library artist.
|
||||
# Library lookup still failed. If a metadata source was specified,
|
||||
# fall back to a source-only response so the page can render a
|
||||
# non-library artist.
|
||||
if source_param in _SOURCE_ONLY_ARTIST_SOURCES:
|
||||
return _build_source_only_artist_detail(
|
||||
artist_id, artist_name_arg, source_param
|
||||
|
|
|
|||
|
|
@ -59400,20 +59400,18 @@ body[data-artist-source="source"] #artist-detail-page #enhanced-view-container {
|
|||
display: none !important;
|
||||
}
|
||||
|
||||
/* Library-only: completion bars, enrichment coverage, Top Tracks sidebar, Radio / Enhance Quality buttons */
|
||||
body[data-artist-source="source"] #artist-detail-page .collection-overview,
|
||||
/* Library-only buttons: Radio + Enhance Quality both require owned tracks.
|
||||
Enrichment coverage is a per-track DB enrichment percentage that doesn't
|
||||
apply to artists you don't own.
|
||||
.collection-overview and #artist-hero-sidebar both render usefully for
|
||||
source artists (collection shows 0/N missing, Top Tracks pulls from
|
||||
Last.fm by name) so they stay visible. */
|
||||
body[data-artist-source="source"] #artist-detail-page .artist-enrichment-coverage,
|
||||
body[data-artist-source="source"] #artist-detail-page #artist-hero-sidebar,
|
||||
body[data-artist-source="source"] #artist-detail-page #library-artist-radio-btn,
|
||||
body[data-artist-source="source"] #artist-detail-page #library-artist-enhance-btn {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Library-only: section-stats "0 owned / 0 missing" counts don't apply */
|
||||
body[data-artist-source="source"] #artist-detail-page .section-stats {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
/* =========================================================================
|
||||
Standalone /artist-detail page hero — blurred-background treatment
|
||||
|
|
|
|||
Loading…
Reference in a new issue