music: update search results when library changes

This commit is contained in:
Alexander Capehart 2024-04-14 12:59:31 -06:00
parent c8571a4df3
commit a3e74cbd1e
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
2 changed files with 67 additions and 14 deletions

View file

@ -57,7 +57,9 @@ constructor(
private var invalidator: Invalidator? = null private var invalidator: Invalidator? = null
interface Invalidator { interface Invalidator {
fun invalidate(ids: List<String>) data class ParentId(val id: String, val itemCount: Int)
fun invalidate(ids: Map<String, Int>)
fun invalidate(controller: ControllerInfo, query: String, itemCount: Int) fun invalidate(controller: ControllerInfo, query: String, itemCount: Int)
} }
@ -76,23 +78,43 @@ constructor(
override fun onMusicChanges(changes: MusicRepository.Changes) { override fun onMusicChanges(changes: MusicRepository.Changes) {
val deviceLibrary = musicRepository.deviceLibrary val deviceLibrary = musicRepository.deviceLibrary
var invalidateSearch = false var invalidateSearch = false
val invalidate = mutableListOf<MediaSessionUID>() val invalidate = mutableMapOf<String, Int>()
if (changes.deviceLibrary && deviceLibrary != null) { if (changes.deviceLibrary && deviceLibrary != null) {
invalidate.addAll(MediaSessionUID.Category.DEVICE_MUSIC) MediaSessionUID.Category.DEVICE_MUSIC.forEach {
deviceLibrary.albums.mapTo(invalidate) { MediaSessionUID.Single(it.uid) } invalidate[it.toString()] = getCategorySize(it, musicRepository)
deviceLibrary.artists.mapTo(invalidate) { MediaSessionUID.Single(it.uid) } }
deviceLibrary.genres.mapTo(invalidate) { MediaSessionUID.Single(it.uid) }
deviceLibrary.albums.forEach {
val id = MediaSessionUID.Single(it.uid).toString()
invalidate[id] = it.songs.size
}
deviceLibrary.artists.forEach {
val id = MediaSessionUID.Single(it.uid).toString()
invalidate[id] = it.songs.size + it.explicitAlbums.size + it.implicitAlbums.size
}
deviceLibrary.genres.forEach {
val id = MediaSessionUID.Single(it.uid).toString()
invalidate[id] = it.songs.size + it.artists.size
}
invalidateSearch = true invalidateSearch = true
} }
val userLibrary = musicRepository.userLibrary val userLibrary = musicRepository.userLibrary
if (changes.userLibrary && userLibrary != null) { if (changes.userLibrary && userLibrary != null) {
invalidate.addAll(MediaSessionUID.Category.USER_MUSIC) MediaSessionUID.Category.USER_MUSIC.forEach {
userLibrary.playlists.mapTo(invalidate) { MediaSessionUID.Single(it.uid) } invalidate[it.toString()] = getCategorySize(it, musicRepository)
}
userLibrary.playlists.forEach {
val id = MediaSessionUID.Single(it.uid).toString()
invalidate[id] = it.songs.size
}
invalidateSearch = true invalidateSearch = true
} }
if (invalidate.isNotEmpty()) { if (invalidate.isNotEmpty()) {
invalidator?.invalidate(invalidate.map { it.toString() }) invalidator?.invalidate(invalidate)
} }
if (invalidateSearch) { if (invalidateSearch) {
@ -119,8 +141,10 @@ constructor(
is MediaSessionUID.Category -> return uid.toMediaItem(context) is MediaSessionUID.Category -> return uid.toMediaItem(context)
is MediaSessionUID.Single -> is MediaSessionUID.Single ->
musicRepository.find(uid.uid)?.let { musicRepository.find(it.uid) } musicRepository.find(uid.uid)?.let { musicRepository.find(it.uid) }
is MediaSessionUID.Joined -> is MediaSessionUID.Joined ->
musicRepository.find(uid.childUid)?.let { musicRepository.find(it.uid) } musicRepository.find(uid.childUid)?.let { musicRepository.find(it.uid) }
null -> null null -> null
} }
?: return null ?: return null
@ -155,32 +179,40 @@ constructor(
when (mediaSessionUID) { when (mediaSessionUID) {
MediaSessionUID.Category.ROOT -> MediaSessionUID.Category.ROOT ->
MediaSessionUID.Category.IMPORTANT.map { it.toMediaItem(context) } MediaSessionUID.Category.IMPORTANT.map { it.toMediaItem(context) }
MediaSessionUID.Category.SONGS -> MediaSessionUID.Category.SONGS ->
listSettings.songSort.songs(deviceLibrary.songs).map { listSettings.songSort.songs(deviceLibrary.songs).map {
it.toMediaItem(context, null) it.toMediaItem(context, null)
} }
MediaSessionUID.Category.ALBUMS -> MediaSessionUID.Category.ALBUMS ->
listSettings.albumSort.albums(deviceLibrary.albums).map { listSettings.albumSort.albums(deviceLibrary.albums).map {
it.toMediaItem(context) it.toMediaItem(context)
} }
MediaSessionUID.Category.ARTISTS -> MediaSessionUID.Category.ARTISTS ->
listSettings.artistSort.artists(deviceLibrary.artists).map { listSettings.artistSort.artists(deviceLibrary.artists).map {
it.toMediaItem(context) it.toMediaItem(context)
} }
MediaSessionUID.Category.GENRES -> MediaSessionUID.Category.GENRES ->
listSettings.genreSort.genres(deviceLibrary.genres).map { listSettings.genreSort.genres(deviceLibrary.genres).map {
it.toMediaItem(context) it.toMediaItem(context)
} }
MediaSessionUID.Category.PLAYLISTS -> MediaSessionUID.Category.PLAYLISTS ->
userLibrary.playlists.map { it.toMediaItem(context) } userLibrary.playlists.map { it.toMediaItem(context) }
} }
} }
is MediaSessionUID.Single -> { is MediaSessionUID.Single -> {
getChildMediaItems(mediaSessionUID.uid) getChildMediaItems(mediaSessionUID.uid)
} }
is MediaSessionUID.Joined -> { is MediaSessionUID.Joined -> {
getChildMediaItems(mediaSessionUID.childUid) getChildMediaItems(mediaSessionUID.childUid)
} }
null -> { null -> {
return null return null
} }
@ -193,25 +225,45 @@ constructor(
val songs = listSettings.albumSongSort.songs(item.songs) val songs = listSettings.albumSongSort.songs(item.songs)
songs.map { it.toMediaItem(context, item) } songs.map { it.toMediaItem(context, item) }
} }
is Artist -> { is Artist -> {
val albums = ARTIST_ALBUMS_SORT.albums(item.explicitAlbums + item.implicitAlbums) val albums = ARTIST_ALBUMS_SORT.albums(item.explicitAlbums + item.implicitAlbums)
val songs = listSettings.artistSongSort.songs(item.songs) val songs = listSettings.artistSongSort.songs(item.songs)
albums.map { it.toMediaItem(context) } + songs.map { it.toMediaItem(context, item) } albums.map { it.toMediaItem(context) } + songs.map { it.toMediaItem(context, item) }
} }
is Genre -> { is Genre -> {
val artists = GENRE_ARTISTS_SORT.artists(item.artists) val artists = GENRE_ARTISTS_SORT.artists(item.artists)
val songs = listSettings.genreSongSort.songs(item.songs) val songs = listSettings.genreSongSort.songs(item.songs)
artists.map { it.toMediaItem(context) } + artists.map { it.toMediaItem(context) } +
songs.map { it.toMediaItem(context, null) } songs.map { it.toMediaItem(context, null) }
} }
is Playlist -> { is Playlist -> {
item.songs.map { it.toMediaItem(context, item) } item.songs.map { it.toMediaItem(context, item) }
} }
is Song, is Song,
null -> return null null -> return null
} }
} }
private fun getCategorySize(
category: MediaSessionUID.Category,
musicRepository: MusicRepository
): Int {
val deviceLibrary = musicRepository.deviceLibrary ?: return 0
val userLibrary = musicRepository.userLibrary ?: return 0
return when (category) {
MediaSessionUID.Category.ROOT -> MediaSessionUID.Category.IMPORTANT.size
MediaSessionUID.Category.SONGS -> deviceLibrary.songs.size
MediaSessionUID.Category.ALBUMS -> deviceLibrary.albums.size
MediaSessionUID.Category.ARTISTS -> deviceLibrary.artists.size
MediaSessionUID.Category.GENRES -> deviceLibrary.genres.size
MediaSessionUID.Category.PLAYLISTS -> userLibrary.playlists.size
}
}
suspend fun prepareSearch(query: String, controller: ControllerInfo) { suspend fun prepareSearch(query: String, controller: ControllerInfo) {
searchSubscribers[controller] = query searchSubscribers[controller] = query
val existing = searchResults[query] val existing = searchResults[query]
@ -287,7 +339,8 @@ constructor(
deviceLibrary.albums, deviceLibrary.albums,
deviceLibrary.artists, deviceLibrary.artists,
deviceLibrary.genres, deviceLibrary.genres,
userLibrary.playlists) userLibrary.playlists
)
val results = searchEngine.search(items, query) val results = searchEngine.search(items, query)
for (entry in searchSubscribers.entries) { for (entry in searchSubscribers.entries) {
if (entry.value == query) { if (entry.value == query) {

View file

@ -255,9 +255,9 @@ constructor(
mediaSession.setCustomLayout(layout) mediaSession.setCustomLayout(layout)
} }
override fun invalidate(ids: List<String>) { override fun invalidate(ids: Map<String, Int>){
for (id in ids) { for (id in ids) {
mediaSession.notifyChildrenChanged(id, Int.MAX_VALUE, null) mediaSession.notifyChildrenChanged(id.key, id.value, null)
} }
} }