search: add playlist results

Add playlist results to the search view.
This commit is contained in:
Alexander Capehart 2023-05-17 17:11:35 -06:00
parent 06885ba264
commit b2e899a211
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
4 changed files with 43 additions and 19 deletions

View file

@ -43,6 +43,7 @@ class SearchAdapter(private val listener: SelectableListListener<Music>) :
is Album -> AlbumViewHolder.VIEW_TYPE
is Artist -> ArtistViewHolder.VIEW_TYPE
is Genre -> GenreViewHolder.VIEW_TYPE
is Playlist -> PlaylistViewHolder.VIEW_TYPE
is BasicHeader -> BasicHeaderViewHolder.VIEW_TYPE
else -> super.getItemViewType(position)
}
@ -53,6 +54,7 @@ class SearchAdapter(private val listener: SelectableListListener<Music>) :
AlbumViewHolder.VIEW_TYPE -> AlbumViewHolder.from(parent)
ArtistViewHolder.VIEW_TYPE -> ArtistViewHolder.from(parent)
GenreViewHolder.VIEW_TYPE -> GenreViewHolder.from(parent)
PlaylistViewHolder.VIEW_TYPE -> PlaylistViewHolder.from(parent)
BasicHeaderViewHolder.VIEW_TYPE -> BasicHeaderViewHolder.from(parent)
else -> error("Invalid item type $viewType")
}
@ -64,6 +66,7 @@ class SearchAdapter(private val listener: SelectableListListener<Music>) :
is Album -> (holder as AlbumViewHolder).bind(item, listener)
is Artist -> (holder as ArtistViewHolder).bind(item, listener)
is Genre -> (holder as GenreViewHolder).bind(item, listener)
is Playlist -> (holder as PlaylistViewHolder).bind(item, listener)
is BasicHeader -> (holder as BasicHeaderViewHolder).bind(item)
}
}

View file

@ -26,6 +26,7 @@ import org.oxycblt.auxio.music.Album
import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.music.Genre
import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.info.Name
@ -33,8 +34,6 @@ import org.oxycblt.auxio.music.info.Name
* Implements the fuzzy-ish searching algorithm used in the search view.
*
* @author Alexander Capehart
*
* TODO: Add playlists
*/
interface SearchEngine {
/**
@ -53,12 +52,14 @@ interface SearchEngine {
* @param albums A list of [Album]s, null if empty.
* @param artists A list of [Artist]s, null if empty.
* @param genres A list of [Genre]s, null if empty.
* @param playlists A list of [Playlist], null if empty.
*/
data class Items(
val songs: List<Song>?,
val albums: List<Album>?,
val artists: List<Artist>?,
val genres: List<Genre>?
val genres: List<Genre>?,
val playlists: List<Playlist>?
)
}
@ -72,7 +73,8 @@ class SearchEngineImpl @Inject constructor(@ApplicationContext private val conte
},
albums = items.albums?.searchListImpl(query),
artists = items.artists?.searchListImpl(query),
genres = items.genres?.searchListImpl(query))
genres = items.genres?.searchListImpl(query),
playlists = items.playlists?.searchListImpl(query))
/**
* Search a given [Music] list.

View file

@ -34,6 +34,7 @@ import org.oxycblt.auxio.list.Item
import org.oxycblt.auxio.list.Sort
import org.oxycblt.auxio.music.*
import org.oxycblt.auxio.music.device.DeviceLibrary
import org.oxycblt.auxio.music.user.UserLibrary
import org.oxycblt.auxio.playback.PlaybackSettings
import org.oxycblt.auxio.util.logD
@ -73,7 +74,7 @@ constructor(
}
override fun onMusicChanges(changes: MusicRepository.Changes) {
if (changes.deviceLibrary && musicRepository.deviceLibrary != null) {
if (changes.deviceLibrary || changes.userLibrary) {
search(lastQuery)
}
}
@ -90,7 +91,8 @@ constructor(
lastQuery = query
val deviceLibrary = musicRepository.deviceLibrary
if (query.isNullOrEmpty() || deviceLibrary == null) {
val userLibrary = musicRepository.userLibrary
if (query.isNullOrEmpty() || deviceLibrary == null || userLibrary == null) {
logD("Search query is not applicable.")
_searchResults.value = listOf()
return
@ -101,11 +103,16 @@ constructor(
// Searching is time-consuming, so do it in the background.
currentSearchJob =
viewModelScope.launch {
_searchResults.value = searchImpl(deviceLibrary, query).also { yield() }
_searchResults.value =
searchImpl(deviceLibrary, userLibrary, query).also { yield() }
}
}
private suspend fun searchImpl(deviceLibrary: DeviceLibrary, query: String): List<Item> {
private suspend fun searchImpl(
deviceLibrary: DeviceLibrary,
userLibrary: UserLibrary,
query: String
): List<Item> {
val filterMode = searchSettings.searchFilterMode
val items =
@ -115,33 +122,40 @@ constructor(
deviceLibrary.songs,
deviceLibrary.albums,
deviceLibrary.artists,
deviceLibrary.genres)
deviceLibrary.genres,
userLibrary.playlists)
} else {
SearchEngine.Items(
songs = if (filterMode == MusicMode.SONGS) deviceLibrary.songs else null,
albums = if (filterMode == MusicMode.ALBUMS) deviceLibrary.albums else null,
artists = if (filterMode == MusicMode.ARTISTS) deviceLibrary.artists else null,
genres = if (filterMode == MusicMode.GENRES) deviceLibrary.genres else null)
genres = if (filterMode == MusicMode.GENRES) deviceLibrary.genres else null,
playlists =
if (filterMode == MusicMode.PLAYLISTS) userLibrary.playlists else null)
}
val results = searchEngine.search(items, query)
return buildList {
results.artists?.let { artists ->
results.artists?.let {
add(BasicHeader(R.string.lbl_artists))
addAll(SORT.artists(artists))
addAll(SORT.artists(it))
}
results.albums?.let { albums ->
results.albums?.let {
add(BasicHeader(R.string.lbl_albums))
addAll(SORT.albums(albums))
addAll(SORT.albums(it))
}
results.genres?.let { genres ->
results.playlists?.let {
add(BasicHeader(R.string.lbl_playlists))
addAll(SORT.playlists(it))
}
results.genres?.let {
add(BasicHeader(R.string.lbl_genres))
addAll(SORT.genres(genres))
addAll(SORT.genres(it))
}
results.songs?.let { songs ->
results.songs?.let {
add(BasicHeader(R.string.lbl_songs))
addAll(SORT.songs(songs))
addAll(SORT.songs(it))
}
}
}
@ -158,7 +172,7 @@ constructor(
MusicMode.ALBUMS -> R.id.option_filter_albums
MusicMode.ARTISTS -> R.id.option_filter_artists
MusicMode.GENRES -> R.id.option_filter_genres
MusicMode.PLAYLISTS -> R.id.option_filter_all // TODO: Handle
MusicMode.PLAYLISTS -> R.id.option_filter_playlists
// Null maps to filtering nothing.
null -> R.id.option_filter_all
}
@ -175,6 +189,7 @@ constructor(
R.id.option_filter_albums -> MusicMode.ALBUMS
R.id.option_filter_artists -> MusicMode.ARTISTS
R.id.option_filter_genres -> MusicMode.GENRES
R.id.option_filter_playlists -> MusicMode.PLAYLISTS
// Null maps to filtering nothing.
R.id.option_filter_all -> null
else -> error("Invalid option ID provided")

View file

@ -28,6 +28,10 @@
android:id="@+id/option_filter_genres"
android:title="@string/lbl_genres"
app:showAsAction="never" />
<item
android:id="@+id/option_filter_playlists"
android:title="@string/lbl_playlists"
app:showAsAction="never" />
</group>
</menu>
</item>