Fixed slow search because of Genres, and also added Playlists to Search results, Don't worry that won't slow the search.
This commit is contained in:
parent
5c1a88b32b
commit
010b771373
5 changed files with 73 additions and 73 deletions
|
@ -96,11 +96,11 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
|
||||||
view.doOnPreDraw {
|
view.doOnPreDraw {
|
||||||
startPostponedEnterTransition()
|
startPostponedEnterTransition()
|
||||||
}
|
}
|
||||||
libraryViewModel.getFabMargin().observe(viewLifecycleOwner, {
|
libraryViewModel.getFabMargin().observe(viewLifecycleOwner) {
|
||||||
binding.keyboardPopup.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
binding.keyboardPopup.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
bottomMargin = it
|
bottomMargin = it
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
KeyboardVisibilityEvent.setEventListener(requireActivity(), viewLifecycleOwner) {
|
KeyboardVisibilityEvent.setEventListener(requireActivity(), viewLifecycleOwner) {
|
||||||
if (it) {
|
if (it) {
|
||||||
binding.keyboardPopup.isGone = true
|
binding.keyboardPopup.isGone = true
|
||||||
|
@ -192,6 +192,7 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
|
||||||
R.id.chip_albums -> Filter.ALBUMS
|
R.id.chip_albums -> Filter.ALBUMS
|
||||||
R.id.chip_album_artists -> Filter.ALBUM_ARTISTS
|
R.id.chip_album_artists -> Filter.ALBUM_ARTISTS
|
||||||
R.id.chip_genres -> Filter.GENRES
|
R.id.chip_genres -> Filter.GENRES
|
||||||
|
R.id.chip_playlists -> Filter.PLAYLISTS
|
||||||
else -> Filter.NO_FILTER
|
else -> Filter.NO_FILTER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,6 +246,7 @@ enum class Filter {
|
||||||
ALBUMS,
|
ALBUMS,
|
||||||
ALBUM_ARTISTS,
|
ALBUM_ARTISTS,
|
||||||
GENRES,
|
GENRES,
|
||||||
|
PLAYLISTS,
|
||||||
NO_FILTER
|
NO_FILTER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,19 +16,19 @@ package code.name.monkey.retromusic.repository
|
||||||
|
|
||||||
import android.content.ContentResolver
|
import android.content.ContentResolver
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.net.Uri
|
|
||||||
import android.provider.BaseColumns
|
import android.provider.BaseColumns
|
||||||
import android.provider.MediaStore.Audio.Genres
|
import android.provider.MediaStore.Audio.Genres
|
||||||
import code.name.monkey.retromusic.Constants.IS_MUSIC
|
import code.name.monkey.retromusic.Constants.IS_MUSIC
|
||||||
import code.name.monkey.retromusic.Constants.baseProjection
|
import code.name.monkey.retromusic.Constants.baseProjection
|
||||||
import code.name.monkey.retromusic.extensions.getLong
|
import code.name.monkey.retromusic.extensions.getLong
|
||||||
import code.name.monkey.retromusic.extensions.getString
|
|
||||||
import code.name.monkey.retromusic.extensions.getStringOrNull
|
import code.name.monkey.retromusic.extensions.getStringOrNull
|
||||||
import code.name.monkey.retromusic.model.Genre
|
import code.name.monkey.retromusic.model.Genre
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
|
|
||||||
interface GenreRepository {
|
interface GenreRepository {
|
||||||
|
fun genres(query: String): List<Genre>
|
||||||
|
|
||||||
fun genres(): List<Genre>
|
fun genres(): List<Genre>
|
||||||
|
|
||||||
fun songs(genreId: Long): List<Song>
|
fun songs(genreId: Long): List<Song>
|
||||||
|
@ -41,6 +41,10 @@ class RealGenreRepository(
|
||||||
private val songRepository: RealSongRepository
|
private val songRepository: RealSongRepository
|
||||||
) : GenreRepository {
|
) : GenreRepository {
|
||||||
|
|
||||||
|
override fun genres(query: String): List<Genre> {
|
||||||
|
return getGenresFromCursor(makeGenreCursor(query))
|
||||||
|
}
|
||||||
|
|
||||||
override fun genres(): List<Genre> {
|
override fun genres(): List<Genre> {
|
||||||
return getGenresFromCursor(makeGenreCursor())
|
return getGenresFromCursor(makeGenreCursor())
|
||||||
}
|
}
|
||||||
|
@ -57,18 +61,23 @@ class RealGenreRepository(
|
||||||
return songRepository.song(makeGenreSongCursor(genreId))
|
return songRepository.song(makeGenreSongCursor(genreId))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getSongCount(genreId: Long): Int {
|
||||||
|
contentResolver.query(
|
||||||
|
Genres.Members.getContentUri("external", genreId),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
).use {
|
||||||
|
return it?.count ?: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getGenreFromCursor(cursor: Cursor): Genre {
|
private fun getGenreFromCursor(cursor: Cursor): Genre {
|
||||||
val id = cursor.getLong(Genres._ID)
|
val id = cursor.getLong(Genres._ID)
|
||||||
val name = cursor.getStringOrNull(Genres.NAME)
|
val name = cursor.getStringOrNull(Genres.NAME)
|
||||||
val songCount = songs(id).size
|
val songCount = getSongCount(id)
|
||||||
return Genre(id, name ?: "", songCount)
|
return Genre(id, name ?: "", songCount)
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getGenreFromCursorWithOutSongs(cursor: Cursor): Genre {
|
|
||||||
val id = cursor.getLong(Genres._ID)
|
|
||||||
val name = cursor.getString(Genres.NAME)
|
|
||||||
return Genre(id, name, -1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSongsWithNoGenre(): List<Song> {
|
private fun getSongsWithNoGenre(): List<Song> {
|
||||||
|
@ -77,28 +86,6 @@ class RealGenreRepository(
|
||||||
return songRepository.songs(songRepository.makeSongCursor(selection, null))
|
return songRepository.songs(songRepository.makeSongCursor(selection, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasSongsWithNoGenre(): Boolean {
|
|
||||||
val allSongsCursor = songRepository.makeSongCursor(null, null)
|
|
||||||
val allSongsWithGenreCursor = makeAllSongsWithGenreCursor()
|
|
||||||
|
|
||||||
if (allSongsCursor == null || allSongsWithGenreCursor == null) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val hasSongsWithNoGenre = allSongsCursor.count > allSongsWithGenreCursor.count
|
|
||||||
allSongsCursor.close()
|
|
||||||
allSongsWithGenreCursor.close()
|
|
||||||
return hasSongsWithNoGenre
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun makeAllSongsWithGenreCursor(): Cursor? {
|
|
||||||
println(Genres.EXTERNAL_CONTENT_URI.toString())
|
|
||||||
return contentResolver.query(
|
|
||||||
Uri.parse("content://media/external/audio/genres/all/members"),
|
|
||||||
arrayOf(Genres.Members.AUDIO_ID), null, null, null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun makeGenreSongCursor(genreId: Long): Cursor? {
|
private fun makeGenreSongCursor(genreId: Long): Cursor? {
|
||||||
return try {
|
return try {
|
||||||
contentResolver.query(
|
contentResolver.query(
|
||||||
|
@ -121,37 +108,13 @@ class RealGenreRepository(
|
||||||
val genre = getGenreFromCursor(cursor)
|
val genre = getGenreFromCursor(cursor)
|
||||||
if (genre.songCount > 0) {
|
if (genre.songCount > 0) {
|
||||||
genres.add(genre)
|
genres.add(genre)
|
||||||
} else {
|
|
||||||
// try to remove the empty genre from the media store
|
|
||||||
try {
|
|
||||||
contentResolver.delete(
|
|
||||||
Genres.EXTERNAL_CONTENT_URI,
|
|
||||||
Genres._ID + " == " + genre.id,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} while (cursor.moveToNext())
|
} while (cursor.moveToNext())
|
||||||
}
|
}
|
||||||
cursor.close()
|
|
||||||
}
|
}
|
||||||
return genres
|
return genres
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getGenresFromCursorForSearch(cursor: Cursor?): List<Genre> {
|
|
||||||
val genres = mutableListOf<Genre>()
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
do {
|
|
||||||
genres.add(getGenreFromCursorWithOutSongs(cursor))
|
|
||||||
} while (cursor.moveToNext())
|
|
||||||
}
|
|
||||||
cursor?.close()
|
|
||||||
return genres
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun makeGenreCursor(): Cursor? {
|
private fun makeGenreCursor(): Cursor? {
|
||||||
val projection = arrayOf(Genres._ID, Genres.NAME)
|
val projection = arrayOf(Genres._ID, Genres.NAME)
|
||||||
return try {
|
return try {
|
||||||
|
@ -166,4 +129,19 @@ class RealGenreRepository(
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun makeGenreCursor(query: String): Cursor? {
|
||||||
|
val projection = arrayOf(Genres._ID, Genres.NAME)
|
||||||
|
return try {
|
||||||
|
contentResolver.query(
|
||||||
|
Genres.EXTERNAL_CONTENT_URI,
|
||||||
|
projection,
|
||||||
|
Genres.NAME + " = ?",
|
||||||
|
arrayOf(query),
|
||||||
|
PreferenceUtil.genreSortOrder
|
||||||
|
)
|
||||||
|
} catch (e: SecurityException) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ package code.name.monkey.retromusic.repository
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
|
import code.name.monkey.retromusic.db.PlaylistEntity
|
||||||
import code.name.monkey.retromusic.fragments.search.Filter
|
import code.name.monkey.retromusic.fragments.search.Filter
|
||||||
import code.name.monkey.retromusic.model.Album
|
import code.name.monkey.retromusic.model.Album
|
||||||
import code.name.monkey.retromusic.model.Artist
|
import code.name.monkey.retromusic.model.Artist
|
||||||
|
@ -29,20 +30,23 @@ class RealSearchRepository(
|
||||||
private val roomRepository: RoomRepository,
|
private val roomRepository: RoomRepository,
|
||||||
private val genreRepository: GenreRepository,
|
private val genreRepository: GenreRepository,
|
||||||
) {
|
) {
|
||||||
fun searchAll(context: Context, query: String?, filter: Filter): MutableList<Any> {
|
suspend fun searchAll(context: Context, query: String?, filter: Filter): MutableList<Any> {
|
||||||
val results = mutableListOf<Any>()
|
val results = mutableListOf<Any>()
|
||||||
if (query.isNullOrEmpty()) return results
|
if (query.isNullOrEmpty()) return results
|
||||||
query.let { searchString ->
|
query.let { searchString ->
|
||||||
|
|
||||||
|
/** Songs **/
|
||||||
val songs: List<Song> = if (filter == Filter.SONGS || filter == Filter.NO_FILTER) {
|
val songs: List<Song> = if (filter == Filter.SONGS || filter == Filter.NO_FILTER) {
|
||||||
songRepository.songs(searchString)
|
songRepository.songs(searchString)
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (songs.isNotEmpty()) {
|
if (songs.isNotEmpty()) {
|
||||||
results.add(context.resources.getString(R.string.songs))
|
results.add(context.resources.getString(R.string.songs))
|
||||||
results.addAll(songs)
|
results.addAll(songs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Artists **/
|
||||||
val artists: List<Artist> =
|
val artists: List<Artist> =
|
||||||
if (filter == Filter.ARTISTS || filter == Filter.NO_FILTER) {
|
if (filter == Filter.ARTISTS || filter == Filter.NO_FILTER) {
|
||||||
artistRepository.artists(searchString)
|
artistRepository.artists(searchString)
|
||||||
|
@ -53,6 +57,8 @@ class RealSearchRepository(
|
||||||
results.add(context.resources.getString(R.string.artists))
|
results.add(context.resources.getString(R.string.artists))
|
||||||
results.addAll(artists)
|
results.addAll(artists)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Albums **/
|
||||||
val albums: List<Album> = if (filter == Filter.ALBUMS || filter == Filter.NO_FILTER) {
|
val albums: List<Album> = if (filter == Filter.ALBUMS || filter == Filter.NO_FILTER) {
|
||||||
albumRepository.albums(searchString)
|
albumRepository.albums(searchString)
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,6 +68,8 @@ class RealSearchRepository(
|
||||||
results.add(context.resources.getString(R.string.albums))
|
results.add(context.resources.getString(R.string.albums))
|
||||||
results.addAll(albums)
|
results.addAll(albums)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Album-Artists **/
|
||||||
val albumArtists: List<Artist> =
|
val albumArtists: List<Artist> =
|
||||||
if (filter == Filter.ALBUM_ARTISTS || filter == Filter.NO_FILTER) {
|
if (filter == Filter.ALBUM_ARTISTS || filter == Filter.NO_FILTER) {
|
||||||
artistRepository.albumArtists(searchString)
|
artistRepository.albumArtists(searchString)
|
||||||
|
@ -72,11 +80,10 @@ class RealSearchRepository(
|
||||||
results.add(context.resources.getString(R.string.album_artist))
|
results.add(context.resources.getString(R.string.album_artist))
|
||||||
results.addAll(albumArtists)
|
results.addAll(albumArtists)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Genres **/
|
||||||
val genres: List<Genre> = if (filter == Filter.GENRES || filter == Filter.NO_FILTER) {
|
val genres: List<Genre> = if (filter == Filter.GENRES || filter == Filter.NO_FILTER) {
|
||||||
genreRepository.genres().filter { genre ->
|
genreRepository.genres(query)
|
||||||
genre.name.lowercase()
|
|
||||||
.contains(searchString.lowercase())
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
|
@ -84,14 +91,21 @@ class RealSearchRepository(
|
||||||
results.add(context.resources.getString(R.string.genres))
|
results.add(context.resources.getString(R.string.genres))
|
||||||
results.addAll(genres)
|
results.addAll(genres)
|
||||||
}
|
}
|
||||||
/* val playlist = roomRepository.playlists().filter { playlist ->
|
|
||||||
playlist.playlistName.toLowerCase(Locale.getDefault())
|
/** Playlists **/
|
||||||
.contains(searchString.toLowerCase(Locale.getDefault()))
|
val playlist: List<PlaylistEntity> =
|
||||||
}
|
if (filter == Filter.PLAYLISTS || filter == Filter.NO_FILTER) {
|
||||||
if (playlist.isNotEmpty()) {
|
roomRepository.playlists().filter { playlist ->
|
||||||
results.add(context.getString(R.string.playlists))
|
playlist.playlistName.lowercase().contains(searchString.lowercase())
|
||||||
results.addAll(playlist)
|
}
|
||||||
}*/
|
} else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playlist.isNotEmpty()) {
|
||||||
|
results.add(context.getString(R.string.playlists))
|
||||||
|
results.addAll(playlist)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,13 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/genres" />
|
android:text="@string/genres" />
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/chip_playlists"
|
||||||
|
style="@style/SearchChipStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/playlists" />
|
||||||
</com.google.android.material.chip.ChipGroup>
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
|
||||||
</HorizontalScrollView>
|
</HorizontalScrollView>
|
||||||
|
|
|
@ -207,7 +207,6 @@
|
||||||
<item name="android:textSize">16sp</item>
|
<item name="android:textSize">16sp</item>
|
||||||
<item name="checkedIconEnabled">true</item>
|
<item name="checkedIconEnabled">true</item>
|
||||||
<item name="chipEndPadding">10dp</item>
|
<item name="chipEndPadding">10dp</item>
|
||||||
<item name="chipIconEnabled">true</item>
|
|
||||||
<item name="chipMinHeight">40dp</item>
|
<item name="chipMinHeight">40dp</item>
|
||||||
<item name="chipStartPadding">10dp</item>
|
<item name="chipStartPadding">10dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue