From 4761772b9adb740d2c5f943944ad0980f00562fa Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Sun, 18 Oct 2026 05:38:41 +0000 Subject: [PATCH] library: keep display-only artists out of the artist lists Filter the paged, search and home artist lists to artists referenced by the plural credits, falling back to the full list while the relation tables are still empty. Display names keep using the singular tag and navigation keeps using the plural refs. --- .../com/subtracks/data/db/LibraryDao.kt | 25 +++++++++++--- .../com/subtracks/data/db/LibraryPaging.kt | 1 + .../subtracks/data/sync/SyncServiceTest.kt | 34 ++++++++++++++++++- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/app/src/main/kotlin/com/subtracks/data/db/LibraryDao.kt b/app/src/main/kotlin/com/subtracks/data/db/LibraryDao.kt index 326df3b0..2980ae50 100644 --- a/app/src/main/kotlin/com/subtracks/data/db/LibraryDao.kt +++ b/app/src/main/kotlin/com/subtracks/data/db/LibraryDao.kt @@ -93,9 +93,18 @@ private const val DOWNLOADED_ARTIST_ALBUMS = "WHERE song_artists.sourceId = :sourceId AND song_artists.artistId = artists.id " + "AND sd.status = 'Completed' AND songs.albumId IS NOT NULL" +internal const val ARTIST_CREDITED = + "((NOT EXISTS (SELECT 1 FROM album_artists WHERE sourceId = artists.sourceId) " + + "AND NOT EXISTS (SELECT 1 FROM song_artists WHERE sourceId = artists.sourceId)) " + + "OR EXISTS (SELECT 1 FROM album_artists aa " + + "WHERE aa.sourceId = artists.sourceId AND aa.artistId = artists.id) " + + "OR EXISTS (SELECT 1 FROM song_artists sa " + + "WHERE sa.sourceId = artists.sourceId AND sa.artistId = artists.id))" + internal const val ARTISTS_FILTER = "FROM artists WHERE sourceId = :sourceId " + "AND (:starredFilter = 0 OR (:starredFilter = 1 AND starred IS NOT NULL) OR (:starredFilter = 2 AND starred IS NULL)) " + + "AND $ARTIST_CREDITED " + "AND (:downloadedFilter = 0 OR EXISTS (" + "SELECT 1 FROM ($ARTIST_DOWNLOAD_ROWS) dl " + "WHERE dl.id = artists.id AND dl.status = 'Completed')) " + @@ -325,7 +334,7 @@ interface LibraryDao { ): Flow> @Query( - "SELECT * FROM artists WHERE sourceId = :sourceId AND played IS NOT NULL " + + "SELECT * FROM artists WHERE sourceId = :sourceId AND played IS NOT NULL AND $ARTIST_CREDITED " + "ORDER BY played DESC, sortName COLLATE NOCASE, id LIMIT :limit", ) fun recentlyPlayedArtists( @@ -343,7 +352,7 @@ interface LibraryDao { ): Flow> @Query( - "SELECT * FROM artists WHERE sourceId = :sourceId AND playCount > 0 " + + "SELECT * FROM artists WHERE sourceId = :sourceId AND playCount > 0 AND $ARTIST_CREDITED " + "ORDER BY playCount DESC, sortName COLLATE NOCASE, id LIMIT :limit", ) fun mostPlayedArtists( @@ -392,7 +401,7 @@ interface LibraryDao { ): Flow> @Query( - "SELECT * FROM artists WHERE sourceId = :sourceId AND $ARTIST_SEARCH_FILTER " + + "SELECT * FROM artists WHERE sourceId = :sourceId AND $ARTIST_SEARCH_FILTER AND $ARTIST_CREDITED " + "ORDER BY sortName COLLATE NOCASE, id LIMIT :limit", ) fun searchArtists( @@ -803,10 +812,16 @@ interface LibraryDao { @Query("SELECT * FROM albums WHERE sourceId = :sourceId ORDER BY created DESC, sortName COLLATE NOCASE, id") fun homeRecentlyAddedAlbums(sourceId: Long): PagingSource - @Query("SELECT * FROM artists WHERE sourceId = :sourceId AND played IS NOT NULL ORDER BY played DESC, sortName COLLATE NOCASE, id") + @Query( + "SELECT * FROM artists WHERE sourceId = :sourceId AND played IS NOT NULL AND $ARTIST_CREDITED " + + "ORDER BY played DESC, sortName COLLATE NOCASE, id", + ) fun homeRecentlyPlayedArtists(sourceId: Long): PagingSource - @Query("SELECT * FROM artists WHERE sourceId = :sourceId AND playCount > 0 ORDER BY playCount DESC, sortName COLLATE NOCASE, id") + @Query( + "SELECT * FROM artists WHERE sourceId = :sourceId AND playCount > 0 AND $ARTIST_CREDITED " + + "ORDER BY playCount DESC, sortName COLLATE NOCASE, id", + ) fun homeMostPlayedArtists(sourceId: Long): PagingSource @Query( diff --git a/app/src/main/kotlin/com/subtracks/data/db/LibraryPaging.kt b/app/src/main/kotlin/com/subtracks/data/db/LibraryPaging.kt index 6bfb79f2..935d0b45 100644 --- a/app/src/main/kotlin/com/subtracks/data/db/LibraryPaging.kt +++ b/app/src/main/kotlin/com/subtracks/data/db/LibraryPaging.kt @@ -22,6 +22,7 @@ internal const val ALBUMS_FILTER_BASE = internal const val ARTISTS_FILTER_BASE = "FROM artists WHERE sourceId = ? " + "AND (? = 0 OR (? = 1 AND starred IS NOT NULL) OR (? = 2 AND starred IS NULL)) " + + "AND $ARTIST_CREDITED " + "AND (? = '' " + "OR (length(?) >= 3 AND rowid IN (SELECT rowid FROM artist_search " + "WHERE artist_search MATCH '\"' || replace(?, '\"', '\"\"') || '\"')) " + diff --git a/app/src/test/kotlin/com/subtracks/data/sync/SyncServiceTest.kt b/app/src/test/kotlin/com/subtracks/data/sync/SyncServiceTest.kt index cbe28871..d2bb0577 100644 --- a/app/src/test/kotlin/com/subtracks/data/sync/SyncServiceTest.kt +++ b/app/src/test/kotlin/com/subtracks/data/sync/SyncServiceTest.kt @@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.test.runTest import org.junit.After import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -58,7 +59,7 @@ class SyncServiceTest { FakeMusicSource( artists = listOf(artist("a1"), artist("a2")), albums = listOf(album("al1")), - songs = listOf(song("s1"), song("s2")), + songs = listOf(song("s1"), song("s2").copy(artistId = "a2")), playlists = listOf(playlist("p1")), playlistSongs = listOf(PlaylistSong(1, "p1", "s1", 0)), ) @@ -1064,6 +1065,37 @@ class SyncServiceTest { assertEquals("Zulu", db.libraryDao().songOnce(1, "s1")!!.artistSort) } + @Test + fun theArtistsListHidesNamesThatAreOnlyDisplayStrings() = + runTest { + insertSource() + val source = + FakeMusicSource( + artists = listOf(artist("a1", "Alpha"), artist("combo", "Alpha & Beta")), + albums = listOf(album("al1")), + songs = listOf(song("s1")), + ) + + SyncService(db, source).sync() + + assertEquals( + listOf("a1"), + db + .libraryDao() + .artistsByName(1, 0, "") + .allRows() + .map { it.id }, + ) + assertEquals( + listOf("a1"), + db + .libraryDao() + .searchArtists(1, "alpha", 10) + .first() + .map { it.id }, + ) + } + @Test fun everyAlbumArtistAndTrackArtistReachesTheSharedAlbum() = runTest {