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

@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.auxio.music.service
import android.content.Context
@ -57,7 +57,9 @@ constructor(
private var invalidator: Invalidator? = null
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)
}
@ -76,23 +78,43 @@ constructor(
override fun onMusicChanges(changes: MusicRepository.Changes) {
val deviceLibrary = musicRepository.deviceLibrary
var invalidateSearch = false
val invalidate = mutableListOf<MediaSessionUID>()
val invalidate = mutableMapOf<String, Int>()
if (changes.deviceLibrary && deviceLibrary != null) {
invalidate.addAll(MediaSessionUID.Category.DEVICE_MUSIC)
deviceLibrary.albums.mapTo(invalidate) { MediaSessionUID.Single(it.uid) }
deviceLibrary.artists.mapTo(invalidate) { MediaSessionUID.Single(it.uid) }
deviceLibrary.genres.mapTo(invalidate) { MediaSessionUID.Single(it.uid) }
MediaSessionUID.Category.DEVICE_MUSIC.forEach {
invalidate[it.toString()] = getCategorySize(it, musicRepository)
}
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
}
val userLibrary = musicRepository.userLibrary
if (changes.userLibrary && userLibrary != null) {
invalidate.addAll(MediaSessionUID.Category.USER_MUSIC)
userLibrary.playlists.mapTo(invalidate) { MediaSessionUID.Single(it.uid) }
MediaSessionUID.Category.USER_MUSIC.forEach {
invalidate[it.toString()] = getCategorySize(it, musicRepository)
}
userLibrary.playlists.forEach {
val id = MediaSessionUID.Single(it.uid).toString()
invalidate[id] = it.songs.size
}
invalidateSearch = true
}
if (invalidate.isNotEmpty()) {
invalidator?.invalidate(invalidate.map { it.toString() })
invalidator?.invalidate(invalidate)
}
if (invalidateSearch) {
@ -119,8 +141,10 @@ constructor(
is MediaSessionUID.Category -> return uid.toMediaItem(context)
is MediaSessionUID.Single ->
musicRepository.find(uid.uid)?.let { musicRepository.find(it.uid) }
is MediaSessionUID.Joined ->
musicRepository.find(uid.childUid)?.let { musicRepository.find(it.uid) }
null -> null
}
?: return null
@ -155,32 +179,40 @@ constructor(
when (mediaSessionUID) {
MediaSessionUID.Category.ROOT ->
MediaSessionUID.Category.IMPORTANT.map { it.toMediaItem(context) }
MediaSessionUID.Category.SONGS ->
listSettings.songSort.songs(deviceLibrary.songs).map {
it.toMediaItem(context, null)
}
MediaSessionUID.Category.ALBUMS ->
listSettings.albumSort.albums(deviceLibrary.albums).map {
it.toMediaItem(context)
}
MediaSessionUID.Category.ARTISTS ->
listSettings.artistSort.artists(deviceLibrary.artists).map {
it.toMediaItem(context)
}
MediaSessionUID.Category.GENRES ->
listSettings.genreSort.genres(deviceLibrary.genres).map {
it.toMediaItem(context)
}
MediaSessionUID.Category.PLAYLISTS ->
userLibrary.playlists.map { it.toMediaItem(context) }
}
}
is MediaSessionUID.Single -> {
getChildMediaItems(mediaSessionUID.uid)
}
is MediaSessionUID.Joined -> {
getChildMediaItems(mediaSessionUID.childUid)
}
null -> {
return null
}
@ -193,25 +225,45 @@ constructor(
val songs = listSettings.albumSongSort.songs(item.songs)
songs.map { it.toMediaItem(context, item) }
}
is Artist -> {
val albums = ARTIST_ALBUMS_SORT.albums(item.explicitAlbums + item.implicitAlbums)
val songs = listSettings.artistSongSort.songs(item.songs)
albums.map { it.toMediaItem(context) } + songs.map { it.toMediaItem(context, item) }
}
is Genre -> {
val artists = GENRE_ARTISTS_SORT.artists(item.artists)
val songs = listSettings.genreSongSort.songs(item.songs)
artists.map { it.toMediaItem(context) } +
songs.map { it.toMediaItem(context, null) }
songs.map { it.toMediaItem(context, null) }
}
is Playlist -> {
item.songs.map { it.toMediaItem(context, item) }
}
is Song,
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) {
searchSubscribers[controller] = query
val existing = searchResults[query]
@ -287,7 +339,8 @@ constructor(
deviceLibrary.albums,
deviceLibrary.artists,
deviceLibrary.genres,
userLibrary.playlists)
userLibrary.playlists
)
val results = searchEngine.search(items, query)
for (entry in searchSubscribers.entries) {
if (entry.value == query) {

View file

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