Added playlist search
This commit is contained in:
parent
7850e0be46
commit
f5f789bfb1
6 changed files with 91 additions and 99 deletions
|
@ -13,10 +13,13 @@ import code.name.monkey.retromusic.glide.ArtistGlideRequest
|
||||||
import code.name.monkey.retromusic.glide.SongGlideRequest
|
import code.name.monkey.retromusic.glide.SongGlideRequest
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.helper.menu.SongMenuHelper
|
import code.name.monkey.retromusic.helper.menu.SongMenuHelper
|
||||||
|
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
|
||||||
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
|
||||||
import code.name.monkey.retromusic.model.Genre
|
import code.name.monkey.retromusic.model.Genre
|
||||||
|
import code.name.monkey.retromusic.model.Playlist
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
|
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist
|
||||||
import code.name.monkey.retromusic.util.MusicUtil
|
import code.name.monkey.retromusic.util.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.NavigationUtil
|
import code.name.monkey.retromusic.util.NavigationUtil
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
|
@ -36,6 +39,7 @@ class SearchAdapter(
|
||||||
if (dataSet!![position] is Album) return ALBUM
|
if (dataSet!![position] is Album) return ALBUM
|
||||||
if (dataSet!![position] is Artist) return ARTIST
|
if (dataSet!![position] is Artist) return ARTIST
|
||||||
if (dataSet!![position] is Genre) return GENRE
|
if (dataSet!![position] is Genre) return GENRE
|
||||||
|
if (dataSet!![position] is Playlist) return PLAYLIST
|
||||||
return if (dataSet!![position] is Song) SONG else HEADER
|
return if (dataSet!![position] is Song) SONG else HEADER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +80,11 @@ class SearchAdapter(
|
||||||
val genre = dataSet?.get(position) as Genre
|
val genre = dataSet?.get(position) as Genre
|
||||||
holder.title?.text = genre.name
|
holder.title?.text = genre.name
|
||||||
}
|
}
|
||||||
|
PLAYLIST -> {
|
||||||
|
val playlist = dataSet?.get(position) as Playlist
|
||||||
|
holder.title?.text = playlist.name
|
||||||
|
holder.text?.text = MusicUtil.getPlaylistInfoString(activity, getSongs(playlist))
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
holder.title?.text = dataSet?.get(position).toString()
|
holder.title?.text = dataSet?.get(position).toString()
|
||||||
holder.title?.setTextColor(ThemeStore.accentColor(activity))
|
holder.title?.setTextColor(ThemeStore.accentColor(activity))
|
||||||
|
@ -83,6 +92,16 @@ class SearchAdapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getSongs(playlist: Playlist): java.util.ArrayList<Song> {
|
||||||
|
val songs = java.util.ArrayList<Song>()
|
||||||
|
if (playlist is AbsSmartPlaylist) {
|
||||||
|
songs.addAll(playlist.getSongs(activity))
|
||||||
|
} else {
|
||||||
|
songs.addAll(PlaylistSongsLoader.getPlaylistSongList(activity, playlist.id))
|
||||||
|
}
|
||||||
|
return songs
|
||||||
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
return dataSet!!.size
|
return dataSet!!.size
|
||||||
}
|
}
|
||||||
|
@ -131,6 +150,9 @@ class SearchAdapter(
|
||||||
GENRE -> {
|
GENRE -> {
|
||||||
NavigationUtil.goToGenre(activity, item as Genre)
|
NavigationUtil.goToGenre(activity, item as Genre)
|
||||||
}
|
}
|
||||||
|
PLAYLIST -> {
|
||||||
|
NavigationUtil.goToPlaylistNew(activity, item as Playlist)
|
||||||
|
}
|
||||||
SONG -> {
|
SONG -> {
|
||||||
val playList = ArrayList<Song>()
|
val playList = ArrayList<Song>()
|
||||||
playList.add(item as Song)
|
playList.add(item as Song)
|
||||||
|
@ -146,5 +168,6 @@ class SearchAdapter(
|
||||||
private const val ARTIST = 2
|
private const val ARTIST = 2
|
||||||
private const val SONG = 3
|
private const val SONG = 3
|
||||||
private const val GENRE = 4
|
private const val GENRE = 4
|
||||||
|
private const val PLAYLIST = 5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ object GenreLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun searchGenres(context: Context): ArrayList<Genre> {
|
fun searchGenres(context: Context): ArrayList<Genre> {
|
||||||
return getGenresFromCursorForSearch(context, makeGenreCursor(context));
|
return getGenresFromCursorForSearch(context, makeGenreCursor(context))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSongs(context: Context, genreId: Int): ArrayList<Song> {
|
fun getSongs(context: Context, genreId: Int): ArrayList<Song> {
|
||||||
|
|
|
@ -20,9 +20,7 @@ import android.provider.BaseColumns
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.provider.MediaStore.Audio.PlaylistsColumns
|
import android.provider.MediaStore.Audio.PlaylistsColumns
|
||||||
import code.name.monkey.retromusic.model.Playlist
|
import code.name.monkey.retromusic.model.Playlist
|
||||||
import io.reactivex.Observable
|
import java.util.ArrayList
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by hemanths on 16/08/17.
|
* Created by hemanths on 16/08/17.
|
||||||
|
@ -30,24 +28,8 @@ import java.util.*
|
||||||
|
|
||||||
object PlaylistLoader {
|
object PlaylistLoader {
|
||||||
|
|
||||||
private fun getPlaylistFlowable(
|
private fun getPlaylist(
|
||||||
cursor: Cursor?
|
cursor: Cursor?
|
||||||
): Observable<Playlist> {
|
|
||||||
return Observable.create { e ->
|
|
||||||
var playlist = Playlist()
|
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
playlist = getPlaylistFromCursorImpl(cursor)
|
|
||||||
}
|
|
||||||
cursor?.close()
|
|
||||||
|
|
||||||
e.onNext(playlist)
|
|
||||||
e.onComplete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPlaylist(
|
|
||||||
cursor: Cursor?
|
|
||||||
): Playlist {
|
): Playlist {
|
||||||
var playlist = Playlist()
|
var playlist = Playlist()
|
||||||
|
|
||||||
|
@ -58,66 +40,25 @@ object PlaylistLoader {
|
||||||
return playlist
|
return playlist
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPlaylistFlowable(
|
fun searchPlaylist(context: Context, searchString: String): List<Playlist> {
|
||||||
context: Context,
|
return getAllPlaylists(
|
||||||
playlistName: String
|
makePlaylistCursor(
|
||||||
): Observable<Playlist> {
|
context, PlaylistsColumns.NAME + "=?", arrayOf(searchString)
|
||||||
return getPlaylistFlowable(makePlaylistCursor(
|
)
|
||||||
context,
|
)
|
||||||
PlaylistsColumns.NAME + "=?",
|
|
||||||
arrayOf(playlistName)
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPlaylist(
|
fun getPlaylist(
|
||||||
context: Context,
|
context: Context,
|
||||||
playlistName: String
|
playlistName: String
|
||||||
): Playlist {
|
): Playlist {
|
||||||
return getPlaylist(makePlaylistCursor(
|
return getPlaylist(
|
||||||
|
makePlaylistCursor(
|
||||||
context,
|
context,
|
||||||
PlaylistsColumns.NAME + "=?",
|
PlaylistsColumns.NAME + "=?",
|
||||||
arrayOf(playlistName)
|
arrayOf(playlistName)
|
||||||
))
|
)
|
||||||
}
|
)
|
||||||
|
|
||||||
fun getPlaylistFlowable(
|
|
||||||
context: Context,
|
|
||||||
playlistId: Int
|
|
||||||
): Observable<Playlist> {
|
|
||||||
return getPlaylistFlowable(makePlaylistCursor(
|
|
||||||
context,
|
|
||||||
BaseColumns._ID + "=?",
|
|
||||||
arrayOf(playlistId.toString())
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getAllPlaylistsFlowoable(
|
|
||||||
context: Context
|
|
||||||
): Observable<ArrayList<Playlist>> {
|
|
||||||
return getAllPlaylistsFlowable(makePlaylistCursor(context, null, null))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFavoritePlaylistFlowable(context: Context): Observable<ArrayList<Playlist>> {
|
|
||||||
return getAllPlaylistsFlowable(makePlaylistCursor(
|
|
||||||
context,
|
|
||||||
PlaylistsColumns.NAME + "=?",
|
|
||||||
arrayOf(context.getString(code.name.monkey.retromusic.R.string.favorites))))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getAllPlaylistsFlowable(cursor: Cursor?): Observable<ArrayList<Playlist>> {
|
|
||||||
return Observable.create { e ->
|
|
||||||
val playlists = ArrayList<Playlist>()
|
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
|
||||||
do {
|
|
||||||
playlists.add(getPlaylistFromCursorImpl(cursor))
|
|
||||||
} while (cursor.moveToNext())
|
|
||||||
}
|
|
||||||
cursor?.close()
|
|
||||||
|
|
||||||
e.onNext(playlists)
|
|
||||||
e.onComplete()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllPlaylists(context: Context): ArrayList<Playlist> {
|
fun getAllPlaylists(context: Context): ArrayList<Playlist> {
|
||||||
|
@ -125,10 +66,13 @@ object PlaylistLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFavoritePlaylist(context: Context): ArrayList<Playlist> {
|
fun getFavoritePlaylist(context: Context): ArrayList<Playlist> {
|
||||||
return getAllPlaylists(makePlaylistCursor(
|
return getAllPlaylists(
|
||||||
|
makePlaylistCursor(
|
||||||
context,
|
context,
|
||||||
PlaylistsColumns.NAME + "=?",
|
PlaylistsColumns.NAME + "=?",
|
||||||
arrayOf(context.getString(code.name.monkey.retromusic.R.string.favorites))))
|
arrayOf(context.getString(code.name.monkey.retromusic.R.string.favorites))
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllPlaylists(cursor: Cursor?): ArrayList<Playlist> {
|
fun getAllPlaylists(cursor: Cursor?): ArrayList<Playlist> {
|
||||||
|
@ -153,40 +97,44 @@ object PlaylistLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makePlaylistCursor(
|
private fun makePlaylistCursor(
|
||||||
context: Context,
|
context: Context,
|
||||||
selection: String?,
|
selection: String?,
|
||||||
values: Array<String>?
|
values: Array<String>?
|
||||||
): Cursor? {
|
): Cursor? {
|
||||||
try {
|
try {
|
||||||
return context.contentResolver.query(
|
return context.contentResolver.query(
|
||||||
MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||||
arrayOf(BaseColumns._ID, /* 0 */
|
arrayOf(
|
||||||
PlaylistsColumns.NAME), /* 1 */
|
BaseColumns._ID, /* 0 */
|
||||||
selection,
|
PlaylistsColumns.NAME
|
||||||
values,
|
), /* 1 */
|
||||||
MediaStore.Audio.Playlists.DEFAULT_SORT_ORDER)
|
selection,
|
||||||
|
values,
|
||||||
|
MediaStore.Audio.Playlists.DEFAULT_SORT_ORDER
|
||||||
|
)
|
||||||
} catch (e: SecurityException) {
|
} catch (e: SecurityException) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPlaylist(
|
fun getPlaylist(
|
||||||
context: Context,
|
context: Context,
|
||||||
playlistId: Int
|
playlistId: Int
|
||||||
): Playlist {
|
): Playlist {
|
||||||
return getPlaylist(makePlaylistCursor(
|
return getPlaylist(
|
||||||
|
makePlaylistCursor(
|
||||||
context,
|
context,
|
||||||
BaseColumns._ID + "=?",
|
BaseColumns._ID + "=?",
|
||||||
arrayOf(playlistId.toString())
|
arrayOf(playlistId.toString())
|
||||||
))
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPlaylistFromCursorImpl(
|
private fun getPlaylistFromCursorImpl(
|
||||||
cursor: Cursor
|
cursor: Cursor
|
||||||
): Playlist {
|
): Playlist {
|
||||||
val id = cursor.getInt(0)
|
val id = cursor.getInt(0)
|
||||||
val name = cursor.getString(1)
|
val name = cursor.getString(1)
|
||||||
return Playlist(id, name)
|
return Playlist(id, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,7 @@ package code.name.monkey.retromusic.loaders
|
||||||
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.model.Genre
|
import code.name.monkey.retromusic.model.Genre
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
|
|
||||||
|
|
||||||
object SearchLoader {
|
object SearchLoader {
|
||||||
fun searchAll(context: Context, query: String?): MutableList<Any> {
|
fun searchAll(context: Context, query: String?): MutableList<Any> {
|
||||||
|
@ -41,11 +40,24 @@ object SearchLoader {
|
||||||
results.add(context.resources.getString(R.string.albums))
|
results.add(context.resources.getString(R.string.albums))
|
||||||
results.addAll(albums)
|
results.addAll(albums)
|
||||||
}
|
}
|
||||||
val genres: List<Genre> = GenreLoader.searchGenres(context).filter { genre -> genre.name.toLowerCase(Locale.getDefault()).contains(searchString.toLowerCase(Locale.getDefault())) }
|
val genres: List<Genre> = GenreLoader.searchGenres(context)
|
||||||
|
.filter { genre ->
|
||||||
|
genre.name.toLowerCase(Locale.getDefault())
|
||||||
|
.contains(searchString.toLowerCase(Locale.getDefault()))
|
||||||
|
}
|
||||||
if (genres.isNotEmpty()) {
|
if (genres.isNotEmpty()) {
|
||||||
results.add(context.resources.getString(R.string.genres))
|
results.add(context.resources.getString(R.string.genres))
|
||||||
results.addAll(genres)
|
results.addAll(genres)
|
||||||
}
|
}
|
||||||
|
val playlist = PlaylistLoader.getAllPlaylists(context)
|
||||||
|
.filter { playlist ->
|
||||||
|
playlist.name.toLowerCase(Locale.getDefault())
|
||||||
|
.contains(searchString.toLowerCase(Locale.getDefault()))
|
||||||
|
}
|
||||||
|
if (playlist.isNotEmpty()) {
|
||||||
|
results.add(context.getString(R.string.playlists))
|
||||||
|
results.addAll(playlist)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,11 @@ import code.name.monkey.retromusic.mvp.BaseView
|
||||||
import code.name.monkey.retromusic.mvp.Presenter
|
import code.name.monkey.retromusic.mvp.Presenter
|
||||||
import code.name.monkey.retromusic.mvp.PresenterImpl
|
import code.name.monkey.retromusic.mvp.PresenterImpl
|
||||||
import code.name.monkey.retromusic.providers.interfaces.Repository
|
import code.name.monkey.retromusic.providers.interfaces.Repository
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
|
@ -29,6 +33,7 @@ import kotlin.coroutines.CoroutineContext
|
||||||
*/
|
*/
|
||||||
|
|
||||||
interface SearchView : BaseView {
|
interface SearchView : BaseView {
|
||||||
|
|
||||||
fun showData(data: MutableList<Any>)
|
fun showData(data: MutableList<Any>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +42,7 @@ interface SearchPresenter : Presenter<SearchView> {
|
||||||
fun search(query: String?)
|
fun search(query: String?)
|
||||||
|
|
||||||
class SearchPresenterImpl @Inject constructor(
|
class SearchPresenterImpl @Inject constructor(
|
||||||
private val repository: Repository
|
private val repository: Repository
|
||||||
) : PresenterImpl<SearchView>(), SearchPresenter, CoroutineScope {
|
) : PresenterImpl<SearchView>(), SearchPresenter, CoroutineScope {
|
||||||
|
|
||||||
override val coroutineContext: CoroutineContext
|
override val coroutineContext: CoroutineContext
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
<com.google.android.material.textview.MaterialTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.google.android.material.textview.MaterialTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
style="@style/SubTitleTextAppearance"
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="start"
|
android:layout_gravity="start"
|
||||||
android:gravity="start"
|
android:gravity="start"
|
||||||
tools:text="Songs" />
|
android:padding="16dp"
|
||||||
|
android:textAppearance="@style/TextViewHeadline5"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="@tools:sample/lorem" />
|
Loading…
Reference in a new issue