feat: Library Only mode — toggle, search, artist page, similar artists
Backend: - Migration 17: similar_artist_map table stores per-artist similar artist relationships (source_mbid → similar_mbid + name + score) - Tier 4 index build now persists similar artists to this table - GetLibrarySimilarArtists(mbid) queries similar artists filtered by JOIN with the artists table (library-only, no API calls) - Added db field to explore.Service for direct queries Frontend: - ExploreSettingsStore with libraryOnly toggle, persisted to localStorage - Top bar toggle button with active/inactive styling - Explore search: skips full MB/LB pipeline when library-only, uses only searchLibraryCache (pure JS, instant) - Artist detail page: in library-only mode, skips all API calls (no top tracks, no top releases, no LB play count, no MB artist lookup). Uses library store for discography, calls GetLibrarySimilarArtists for similar artists. - Similar artists section: changed from horizontal scroll to wrapping flex layout with collapsible toggle (Show all N) - Removed debug artist ranking log
This commit is contained in:
@@ -1060,6 +1060,9 @@ func (si *SearchIndex) buildTier4Similar(
|
||||
|
||||
similar := si.fetchSimilarArtists(ctx, artistMBID)
|
||||
|
||||
// Persist the similar artist relationships.
|
||||
si.storeSimilarArtists(artistMBID, similar)
|
||||
|
||||
mu.Lock()
|
||||
|
||||
for _, s := range similar {
|
||||
@@ -1637,6 +1640,37 @@ func (si *SearchIndex) markInLibrary(artists []lbSitewideArtist) {
|
||||
}
|
||||
}
|
||||
|
||||
// storeSimilarArtists persists the similar artist relationships
|
||||
// for a source artist into the similar_artist_map table.
|
||||
func (si *SearchIndex) storeSimilarArtists(sourceMBID string, similar []lbSimilarArtistWire) {
|
||||
if len(similar) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
tx, err := si.db.BeginTx()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() { _ = tx.Rollback() }()
|
||||
|
||||
// Clear existing entries for this source to avoid stale data.
|
||||
_, _ = tx.Exec(
|
||||
"DELETE FROM similar_artist_map WHERE source_artist_mbid = ?",
|
||||
sourceMBID,
|
||||
)
|
||||
|
||||
for _, s := range similar {
|
||||
_, _ = tx.Exec(`
|
||||
INSERT OR IGNORE INTO similar_artist_map
|
||||
(source_artist_mbid, similar_artist_mbid, similar_artist_name, score)
|
||||
VALUES (?, ?, ?, ?)
|
||||
`, sourceMBID, s.ArtistMBID, s.Name, s.Score)
|
||||
}
|
||||
|
||||
_ = tx.Commit()
|
||||
}
|
||||
|
||||
// markSimilar sets is_similar=1 for all index entries whose
|
||||
// artist_mbid matches one of the given artists.
|
||||
func (si *SearchIndex) markSimilar(artists []lbSitewideArtist) {
|
||||
|
||||
Reference in New Issue
Block a user