Fix search slow, last added slow

main
h4h13 2019-10-25 01:38:09 +05:30
parent 27190d5b74
commit e75246ff46
36 changed files with 732 additions and 501 deletions

61
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,61 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 60
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 7
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- pinned
- security
- "[Status] Maybe Later"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: false
# Label to use when marking as stale
staleLabel: wontfix
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Comment to post when closing a stale Issue or Pull Request.
# closeComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed

View File

@ -83,6 +83,7 @@ android {
kapt {
generateStubs = true
}
}
def getProperties(String fileName) {
@ -107,9 +108,9 @@ dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation project(':appthemehelper')
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.fragment:fragment:1.2.0-alpha04'
implementation 'androidx.fragment:fragment:1.2.0-beta02'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta04'
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta05'
implementation "androidx.gridlayout:gridlayout:1.0.0"
implementation "androidx.cardview:cardview:1.0.0"
implementation "androidx.palette:palette:1.0.0"
@ -118,12 +119,12 @@ dependencies {
implementation 'androidx.palette:palette-ktx:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0-beta01'
implementation 'com.google.android.material:material:1.2.0-alpha01'
implementation 'com.google.android.play:core:1.6.3'
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.1'
implementation 'com.squareup.retrofit2:retrofit:2.6.2'
implementation 'com.squareup.retrofit2:converter-gson:2.6.2'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.2'
implementation 'com.afollestad.material-dialogs:core:3.1.1'
implementation 'com.afollestad.material-dialogs:input:3.1.1'
@ -147,6 +148,10 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"
implementation 'org.eclipse.mylyn.github:org.eclipse.egit.github.core:3.4.0.201406110918-r'
implementation 'com.github.ksoichiro:android-observablescrollview:1.6.0'
@ -162,5 +167,4 @@ dependencies {
kapt 'com.google.dagger:dagger-compiler:2.23.1'
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic
import kotlinx.coroutines.Dispatchers
import kotlin.coroutines.CoroutineContext
/**
* Created by hemanths on 2019-10-23.
*/
class AppExecutors constructor(
val ioContext: CoroutineContext = Dispatchers.IO,
val uiContext: CoroutineContext = Dispatchers.Main
)

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic
/**
* Created by hemanths on 2019-10-23.
*/
sealed class Result<out T : Any> {
class Success<out T : Any>(val data: T) : Result<T>()
class Error(val exception: Throwable) : Result<Nothing>()
}

View File

@ -129,7 +129,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
val uri = intent.data
val mimeType = intent.type
var handled = false
println("uri -> $uri")
if (intent.action != null && intent.action == MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH) {
val songs = SearchQueryHelper.getSongs(this, intent.extras!!)
if (MusicPlayerRemote.shuffleMode == MusicService.SHUFFLE_MODE_SHUFFLE) {

View File

@ -25,6 +25,7 @@ import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsPresenter
import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsView
import code.name.monkey.retromusic.util.DensityUtil
import code.name.monkey.retromusic.util.PlaylistsUtil
import code.name.monkey.retromusic.util.RetroColorUtil
import code.name.monkey.retromusic.util.ViewUtil
@ -50,6 +51,9 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
override fun onCreate(savedInstanceState: Bundle?) {
setDrawUnderStatusBar()
super.onCreate(savedInstanceState)
App.musicComponent.inject(this)
playlistSongsPresenter.attachView(this)
setStatusbarColor(Color.TRANSPARENT)
setNavigationbarColorAuto()
@ -65,10 +69,6 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
finish()
}
App.musicComponent.inject(this)
playlistSongsPresenter.attachView(this)
setUpToolBar()
setUpRecyclerView()
}
@ -160,14 +160,12 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
override fun onMediaStoreChanged() {
super.onMediaStoreChanged()
if (playlist !is AbsCustomPlaylist) {
// Playlist deleted
if (!PlaylistsUtil.doesPlaylistExist(this, playlist.id)) {
finish()
return
}
// Playlist renamed
val playlistName = PlaylistsUtil.getNameForPlaylist(this, playlist.id.toLong())
if (playlistName != playlist.name) {
@ -182,8 +180,13 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
supportActionBar!!.title = title
}
private fun checkIsEmpty() {
private fun checkForPadding() {
val height = DensityUtil.dip2px(this, 52f)
recyclerView.setPadding(0, 0, 0, (height ))
}
private fun checkIsEmpty() {
checkForPadding()
empty.visibility = if (adapter.itemCount == 0) View.VISIBLE else View.GONE
emptyText.visibility = if (adapter.itemCount == 0) View.VISIBLE else View.GONE
}

View File

@ -1,10 +1,8 @@
package code.name.monkey.retromusic.activities
import android.app.Activity
import android.app.SearchManager
import android.app.Service
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.res.ColorStateList
import android.os.Bundle
@ -77,6 +75,10 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
keyboardPopup.setTextColor(this)
keyboardPopup.iconTint = this
}
if (savedInstanceState != null) {
query = savedInstanceState.getString(QUERY);
}
}
private fun setupRecyclerView() {
@ -104,15 +106,9 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
}
private fun setupSearchView() {
getSystemService(Context.SEARCH_SERVICE) as SearchManager
searchView.addTextChangedListener(this)
}
override fun onResume() {
super.onResume()
searchPresenter.search(query)
}
override fun onDestroy() {
super.onDestroy()
searchPresenter.detachView()
@ -123,11 +119,6 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
outState.putString(QUERY, query)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
searchPresenter.search(savedInstanceState.getString(QUERY, ""))
}
private fun setUpToolBar() {
title = null
appBarLayout.setBackgroundColor(ATHUtil.resolveColor(this, R.attr.colorPrimary))
@ -135,14 +126,14 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
private fun search(query: String) {
this.query = query.trim { it <= ' ' }
this.query = query
voiceSearch.visibility = if (query.isNotEmpty()) View.GONE else View.VISIBLE
searchPresenter.search(query)
}
override fun onMediaStoreChanged() {
super.onMediaStoreChanged()
searchPresenter.search(query!!)
query?.let { search(it) }
}
override fun onQueryTextSubmit(query: String): Boolean {

View File

@ -16,27 +16,21 @@ import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Home
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.providers.interfaces.Repository
import code.name.monkey.retromusic.util.PreferenceUtil
import com.google.android.material.textview.MaterialTextView
class HomeAdapter(
private val activity: AppCompatActivity,
private val displayMetrics: DisplayMetrics,
private val repository: Repository
private val displayMetrics: DisplayMetrics
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var list = ArrayList<Home>()
override fun getItemViewType(position: Int): Int {
return when (position) {
0 -> TOP_ARTISTS
1 -> TOP_ALBUMS
2 -> RECENT_ARTISTS
3 -> RECENT_ALBUMS
4 -> PLAYLISTS
else -> -1
}
return list[position].homeSection
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
@ -51,35 +45,39 @@ class HomeAdapter(
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
println(getItemViewType(position))
println("ViewType ${getItemViewType(position)}")
when (getItemViewType(position)) {
RECENT_ALBUMS -> {
val viewHolder = holder as AlbumViewHolder
viewHolder.bindView(repository.recentAlbums(), R.string.recent_albums, R.string.recent_added_albums)
viewHolder.bindView(list[position].arrayList.toAlbums(), R.string.recent_albums, R.string.recent_added_albums)
}
TOP_ALBUMS -> {
val viewHolder = holder as AlbumViewHolder
viewHolder.bindView(repository.topAlbums(), R.string.top_albums, R.string.most_played_albums)
viewHolder.bindView(list[position].arrayList.toAlbums(), R.string.top_albums, R.string.most_played_albums)
}
RECENT_ARTISTS -> {
val viewHolder = holder as ArtistViewHolder
viewHolder.bindView(repository.recentArtists(), R.string.recent_artists, R.string.recent_added_artists)
viewHolder.bindView(list[position].arrayList.toArtists(), R.string.recent_artists, R.string.recent_added_artists)
}
TOP_ARTISTS -> {
val viewHolder = holder as ArtistViewHolder
viewHolder.bindView(repository.recentArtists(), R.string.top_artists, R.string.most_played_artists)
viewHolder.bindView(list[position].arrayList.toArtists(), R.string.top_artists, R.string.most_played_artists)
}
PLAYLISTS -> {
val viewHolder = holder as PlaylistViewHolder
viewHolder.bindView(repository.favoritePlaylist, R.string.favorites, R.string.favorites_songs)
viewHolder.bindView(list[position].arrayList as ArrayList<Playlist>, R.string.favorites, R.string.favorites_songs)
}
}
}
override fun getItemCount(): Int {
return 5
return list.size
}
fun swapData(sections: ArrayList<Home>) {
list = sections
notifyDataSetChanged()
}
companion object {
@ -103,11 +101,13 @@ class HomeAdapter(
show()
adapter = AlbumFullWidthAdapter(activity, list, displayMetrics)
}
titleContainer . show ()
titleContainer.show()
title.text = activity.getString(titleRes)
text.text = activity.getString(subtitleRes)
}
}
}
inner class ArtistViewHolder(view: View) : AbsHomeViewItem(view) {
@ -153,4 +153,21 @@ class HomeAdapter(
val title: MaterialTextView = itemView.findViewById(R.id.title)
val text: MaterialTextView = itemView.findViewById(R.id.text)
}
}
}
private fun <E> ArrayList<E>.toAlbums(): ArrayList<Album> {
val arrayList = ArrayList<Album>()
for (x in this) {
arrayList.add(x as Album)
}
return arrayList;
}
private fun <E> ArrayList<E>.toArtists(): ArrayList<Artist> {
val arrayList = ArrayList<Artist>()
for (x in this) {
arrayList.add(x as Artist)
}
return arrayList;
}

View File

@ -19,7 +19,6 @@ import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.MusicUtil
import code.name.monkey.retromusic.util.NavigationUtil
import com.bumptech.glide.Glide
import java.util.*
import android.util.Pair as UtilPair
class SearchAdapter(
@ -57,7 +56,7 @@ class SearchAdapter(
holder.title?.text = artist.name
holder.text?.text = MusicUtil.getArtistInfoString(activity, artist)
ArtistGlideRequest.Builder.from(Glide.with(activity), artist)
.build().into(holder.image);
.build().into(holder.image)
}
SONG -> {
val song = dataSet?.get(position) as Song
@ -79,16 +78,14 @@ class SearchAdapter(
init {
itemView.setOnLongClickListener(null)
if (menu != null) {
if (itemViewType == SONG) {
menu!!.visibility = View.VISIBLE
menu!!.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
override val song: Song
get() = dataSet!![adapterPosition] as Song
})
} else {
menu!!.visibility = View.GONE
}
if (itemViewType == SONG) {
menu?.visibility = View.VISIBLE
menu?.setOnClickListener(object : SongMenuHelper.OnClickSongMenu(activity) {
override val song: Song
get() = dataSet!![adapterPosition] as Song
})
} else {
menu?.visibility = View.GONE
}
when (itemViewType) {
@ -126,7 +123,6 @@ class SearchAdapter(
}
companion object {
private const val HEADER = 0
private const val ALBUM = 1
private const val ARTIST = 2

View File

@ -215,9 +215,7 @@ class PlaylistAdapter(protected val activity: AppCompatActivity, dataSet: ArrayL
}
companion object {
val TAG: String = PlaylistAdapter::class.java.simpleName
private const val SMART_PLAYLIST = 0
private const val DEFAULT_PLAYLIST = 1
}

View File

@ -44,7 +44,7 @@ abstract class AbsLibraryPagerRecyclerViewFragment<A : RecyclerView.Adapter<*>,
private fun initAdapter() {
adapter = createAdapter()
adapter!!.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
adapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
super.onChanged()
checkIsEmpty()

View File

@ -2,7 +2,6 @@ package code.name.monkey.retromusic.fragments.mainactivity.home
import android.app.ActivityOptions
import android.graphics.Bitmap
import android.graphics.Color
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.*
@ -18,7 +17,6 @@ import code.name.monkey.retromusic.Constants.USER_BANNER
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.HomeAdapter
import code.name.monkey.retromusic.dialogs.OptionsSheetDialogFragment
import code.name.monkey.retromusic.extensions.hide
import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.helper.MusicPlayerRemote
@ -28,8 +26,8 @@ import code.name.monkey.retromusic.model.Home
import code.name.monkey.retromusic.model.smartplaylist.HistoryPlaylist
import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist
import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist
import code.name.monkey.retromusic.mvp.presenter.HomePresenter
import code.name.monkey.retromusic.mvp.presenter.HomeView
import code.name.monkey.retromusic.providers.interfaces.Repository
import code.name.monkey.retromusic.util.Compressor
import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.util.PreferenceUtil
@ -49,19 +47,14 @@ import javax.inject.Inject
class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallbacks, HomeView {
private lateinit var homeAdapter: HomeAdapter
@Inject
lateinit var repository: Repository
lateinit var homePresenter: HomePresenter
private var disposable: CompositeDisposable = CompositeDisposable()
private lateinit var toolbar: Toolbar
override fun sections(sections: ArrayList<Home>) {
val finalList = sections.sortedWith(compareBy { it.priority })
if (sections.isEmpty()) {
showEmptyView()
} else {
emptyContainer.hide()
}
println(sections.size)
homeAdapter.swapData(sections)
}
override fun onCreateView(inflater: LayoutInflater, viewGroup: ViewGroup?, savedInstanceState: Bundle?): View? {
@ -133,17 +126,18 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
titleWelcome.text = String.format("%s", PreferenceUtil.getInstance(requireContext()).userName)
App.musicComponent.inject(this)
homeAdapter = HomeAdapter(mainActivity, displayMetrics, repository)
homeAdapter = HomeAdapter(mainActivity, displayMetrics)
recyclerView.apply {
layoutManager = LinearLayoutManager(mainActivity)
adapter = homeAdapter
}
homePresenter.attachView(this)
homePresenter.loadSections()
}
private fun toolbarColor(): Int {
return if (PreferenceUtil.getInstance(requireContext()).isHomeBanner) {
toolbarContainer.setBackgroundColor(Color.TRANSPARENT)
ColorUtil.withAlpha(RetroColorUtil.toolbarColor(mainActivity), 0.85f)
} else {
RetroColorUtil.toolbarColor(mainActivity)
@ -176,6 +170,7 @@ class BannerHomeFragment : AbsMainActivityFragment(), MainActivityFragmentCallba
override fun onDestroyView() {
super.onDestroyView()
disposable.dispose()
homePresenter.detachView()
}
override fun showEmptyView() {

View File

@ -16,7 +16,6 @@ package code.name.monkey.retromusic.loaders
import android.content.Context
import code.name.monkey.retromusic.R
import io.reactivex.Observable
object SearchLoader {

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.misc
import android.content.Context
import android.text.TextUtils
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.loaders.AlbumLoader
import code.name.monkey.retromusic.loaders.ArtistLoader
import code.name.monkey.retromusic.loaders.SongLoader
import java.util.*
internal class AsyncSearchResultLoader(context: Context, private val query: String) : WrappedAsyncTaskLoader<List<Any>>(context) {
override fun loadInBackground(): List<Any>? {
val results = ArrayList<Any>()
if (!TextUtils.isEmpty(query)) {
val songs = SongLoader.getSongs(context, query.trim { it <= ' ' })
if (!songs.isEmpty()) {
results.add(context.resources.getString(R.string.songs))
results.addAll(songs)
}
val artists = ArtistLoader.getArtists(context, query.trim { it <= ' ' })
if (!artists.isEmpty()) {
results.add(context.resources.getString(R.string.artists))
results.addAll(artists)
}
val albums = AlbumLoader.getAlbums(context, query.trim { it <= ' ' })
if (!albums.isEmpty()) {
results.add(context.resources.getString(R.string.albums))
results.addAll(albums)
}
}
return results
}
}

View File

@ -14,13 +14,17 @@
package code.name.monkey.retromusic.mvp
import androidx.annotation.CallSuper
/**
* Created by hemanths on 16/08/17.
*/
interface Presenter<T> {
@CallSuper
fun attachView(view: T)
@CallSuper
fun detachView()
}

View File

@ -14,14 +14,16 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.mvp.BaseView
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.PresenterImpl
import code.name.monkey.retromusic.providers.interfaces.Repository
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.*
import java.util.*
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
/**
@ -37,22 +39,30 @@ interface AlbumsPresenter : Presenter<AlbumsView> {
class AlbumsPresenterImpl @Inject constructor(
private val repository: Repository
) : PresenterImpl<AlbumsView>(), AlbumsPresenter {
) : PresenterImpl<AlbumsView>(), AlbumsPresenter, CoroutineScope {
private val job = Job()
private var disposable: Disposable? = null
private fun showList(albums: ArrayList<Album>) {
view?.albums(albums)
}
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO + job
override fun detachView() {
super.detachView()
disposable?.dispose()
job.cancel()
}
override fun loadAlbums() {
disposable = repository.allAlbumsFlowable
.subscribe({ view?.albums(it) }, { t -> println(t) })
launch {
when (val result = repository.allAlbums()) {
is Result.Success -> {
withContext(Dispatchers.Main) {
view?.albums(result.data)
}
}
is Result.Error -> {
view?.showEmptyView()
}
}
}
}
}
}

View File

@ -14,13 +14,15 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.mvp.BaseView
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.PresenterImpl
import code.name.monkey.retromusic.providers.interfaces.Repository
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.*
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
interface ArtistsView : BaseView {
fun artists(artists: ArrayList<Artist>)
@ -32,18 +34,26 @@ interface ArtistsPresenter : Presenter<ArtistsView> {
class ArtistsPresenterImpl @Inject constructor(
private val repository: Repository
) : PresenterImpl<ArtistsView>(), ArtistsPresenter {
) : PresenterImpl<ArtistsView>(), ArtistsPresenter, CoroutineScope {
private val job = Job()
private var disposable: Disposable? = null
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO + job
override fun detachView() {
super.detachView()
disposable?.dispose()
job.cancel()
}
override fun loadArtists() {
disposable = repository.allArtistsFlowable
.subscribe({ view?.artists(it) }, { t -> println(t) })
launch {
when (val result = repository.allArtists()) {
is Result.Success -> withContext(Dispatchers.Main) {
view?.artists(result.data)
}
is Result.Error -> withContext(Dispatchers.Main) { view?.showEmptyView() }
}
}
}
}
}

View File

@ -14,14 +14,16 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.BaseView
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.PresenterImpl
import code.name.monkey.retromusic.providers.interfaces.Repository
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.*
import java.util.*
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
/**
@ -37,18 +39,29 @@ interface GenreDetailsPresenter : Presenter<GenreDetailsView> {
class GenreDetailsPresenterImpl @Inject constructor(
private val repository: Repository
) : PresenterImpl<GenreDetailsView>(), GenreDetailsPresenter {
) : PresenterImpl<GenreDetailsView>(), GenreDetailsPresenter, CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO + job
override fun detachView() {
super.detachView()
disposable?.dispose()
job.cancel()
}
private var disposable: Disposable? = null
override fun loadGenreSongs(genreId: Int) {
disposable = repository.getGenreFlowable(genreId)
.subscribe({ view?.songs(it) }, { t -> println(t) })
launch {
when (val result = repository.getGenre(genreId)) {
is Result.Success -> withContext(Dispatchers.Main) {
view?.songs(result.data)
}
is Result.Error -> withContext(Dispatchers.Main) {
view?.showEmptyView()
}
}
}
}
}
}

View File

@ -14,14 +14,16 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.mvp.BaseView
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.PresenterImpl
import code.name.monkey.retromusic.providers.interfaces.Repository
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.*
import java.util.*
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
/**
* @author Hemanth S (h4h13).
@ -35,13 +37,26 @@ interface GenresPresenter : Presenter<GenresView> {
class GenresPresenterImpl @Inject constructor(
private val repository: Repository
) : PresenterImpl<GenresView>(), GenresPresenter {
) : PresenterImpl<GenresView>(), GenresPresenter, CoroutineScope {
private val job = Job()
private var disposable: Disposable? = null
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO + job
override fun detachView() {
super.detachView()
job.cancel()
}
override fun loadGenres() {
disposable = repository.allGenresFlowable
.subscribe({ view.genres(it) }, { t -> println(t) })
launch {
when (val result = repository.allGenres()) {
is Result.Success -> withContext(Dispatchers.Main) {
view?.genres(result.data)
}
is Result.Error -> withContext(Dispatchers.Main) { view?.showEmptyView() }
}
}
}
}
}

View File

@ -14,12 +14,7 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.HomeAdapter.Companion.PLAYLISTS
import code.name.monkey.retromusic.adapter.HomeAdapter.Companion.RECENT_ALBUMS
import code.name.monkey.retromusic.adapter.HomeAdapter.Companion.RECENT_ARTISTS
import code.name.monkey.retromusic.adapter.HomeAdapter.Companion.TOP_ALBUMS
import code.name.monkey.retromusic.adapter.HomeAdapter.Companion.TOP_ARTISTS
import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.model.Home
import code.name.monkey.retromusic.mvp.BaseView
import code.name.monkey.retromusic.mvp.Presenter
@ -27,7 +22,9 @@ import code.name.monkey.retromusic.mvp.PresenterImpl
import code.name.monkey.retromusic.providers.interfaces.Repository
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.*
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
add(disposable)
@ -40,238 +37,38 @@ interface HomeView : BaseView {
interface HomePresenter : Presenter<HomeView> {
fun loadSections()
class HomePresenterImpl @Inject constructor(
private val repository: Repository
) : PresenterImpl<HomeView>(), HomePresenter {
) : PresenterImpl<HomeView>(), HomePresenter, CoroutineScope {
private val job = Job()
private val hashSet: HashSet<Home> = HashSet()
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO + job
override fun detachView() {
super.detachView()
job.cancel()
}
override fun loadSections() {
loadRecentArtists()
loadRecentAlbums()
loadTopArtists()
loadATopAlbums()
loadFavorite()
//loadHomeSection()
}
private var disposable: CompositeDisposable = CompositeDisposable()
private fun showData(sections: ArrayList<Home>) {
if (sections.isEmpty()) {
view.showEmptyView()
} else {
view.sections(sections)
launch {
val list = ArrayList<Home>()
val recentArtistResult = listOf(
repository.topArtists(),
repository.topAlbums(),
repository.recentArtists(),
repository.recentAlbums(),
repository.favoritePlaylist()
)
for (r in recentArtistResult) {
when (r) {
is Result.Success -> list.add(r.data)
}
}
withContext(Dispatchers.Main) {
if (list.isNotEmpty()) view?.sections(list) else view?.showEmptyView()
}
}
}
private fun loadRecentArtists() {
disposable += repository.recentArtistsFlowable
.subscribe {
if (it.isNotEmpty()) hashSet.add(
Home(0,
R.string.recent_artists,
R.string.recent_added_artists,
it,
RECENT_ARTISTS,
R.drawable.ic_artist_white_24dp
))
showData(ArrayList(hashSet))
}
}
private fun loadRecentAlbums() {
disposable += repository.recentAlbumsFlowable
.subscribe {
if (it.isNotEmpty()) hashSet.add(
Home(1,
R.string.recent_albums,
R.string.recent_added_albums,
it,
RECENT_ALBUMS,
R.drawable.ic_album_white_24dp
))
showData(ArrayList(hashSet))
}
}
private fun loadTopArtists() {
disposable += repository.topArtistsFlowable
.subscribe {
if (it.isNotEmpty()) hashSet.add(
Home(2,
R.string.top_artists,
R.string.most_played_artists,
it,
TOP_ARTISTS,
R.drawable.ic_artist_white_24dp
))
showData(ArrayList(hashSet))
}
}
private fun loadATopAlbums() {
disposable += repository.topAlbumsFlowable
.subscribe {
if (it.isNotEmpty()) hashSet.add(
Home(3,
R.string.top_albums,
R.string.most_played_albums,
it,
TOP_ALBUMS,
R.drawable.ic_album_white_24dp
))
showData(ArrayList(hashSet))
}
}
private fun loadFavorite() {
disposable += repository.favoritePlaylistFlowable
.subscribe {
if (it.isNotEmpty()) hashSet.add(
Home(4,
R.string.favorites,
R.string.favorites_songs,
it,
PLAYLISTS,
R.drawable.ic_favorite_white_24dp
))
showData(ArrayList(hashSet))
}
}
/*private fun loadHomeSection() {
val ob = listOf(repository.recentArtistsFlowable,
repository.recentAlbumsFlowable,
repository.topArtistsFlowable,
repository.topAlbumsFlowable,
repository.favoritePlaylistFlowable)
disposable += Observable.combineLatest(ob) {
val hashSet: HashSet<Home> = HashSet()
val recentArtist = it[0] as ArrayList<Artist>
if (recentArtist.isNotEmpty()) hashSet.add(
Home(0,
R.string.recent_artists,
0,
recentArtist,
RECENT_ARTISTS,
R.drawable.ic_artist_white_24dp
))
val recentAlbums = it[1] as ArrayList<Album>
if (recentAlbums.isNotEmpty()) hashSet.add(
Home(1,
R.string.recent_albums,
0,
recentAlbums,
RECENT_ALBUMS,
R.drawable.ic_album_white_24dp
))
val topArtists = it[2] as ArrayList<Artist>
if (topArtists.isNotEmpty()) hashSet.add(
Home(2,
R.string.top_artists,
0,
topArtists,
TOP_ARTISTS,
R.drawable.ic_artist_white_24dp
))
val topAlbums = it[3] as ArrayList<Album>
if (topAlbums.isNotEmpty()) hashSet.add(
Home(3,
R.string.top_albums,
0,
topAlbums,
TOP_ALBUMS,
R.drawable.ic_album_white_24dp
))
val playlists = it[4] as ArrayList<Playlist>
if (playlists.isNotEmpty()) hashSet.add(
Home(4,
R.string.favorites,
0,
playlists,
PLAYLISTS,
R.drawable.ic_favorite_white_24dp
))
return@combineLatest hashSet
}.subscribe {
view.sections(ArrayList(it))
}
}*/
}
}
/*class HomePresenter(
private val view: HomeContract.HomeView,
private val repositoryImpl: RepositoryImpl
) : Presenter(), HomeContract.HomePresenter {
private val hashSet: HashSet<Home> = HashSet()
override fun homeSections() {
loadRecentArtists()
loadRecentAlbums()
loadTopArtists()
loadATopAlbums()
loadFavorite()
}
override fun subscribe() {
homeSections()
}
override fun unsubscribe() {
disposable.dispose()
}
private fun loadRecentArtists() {
disposable += repositoryImpl.recentArtistsFlowable
.subscribe({
if (it.isNotEmpty()) hashSet.add(Home(0, R.string.recent_artists, 0, it, RECENT_ARTISTS, R.drawable.ic_artist_white_24dp))
view.showData(ArrayList(hashSet))
}, {
view.showEmptyView()
})
}
private fun loadRecentAlbums() {
disposable += repositoryImpl.recentAlbumsFlowable
.subscribe({
if (it.isNotEmpty()) hashSet.add(Home(1, R.string.recent_albums, 0, it, RECENT_ALBUMS, R.drawable.ic_album_white_24dp))
view.showData(ArrayList(hashSet))
}, {
view.showEmptyView()
})
}
private fun loadATopAlbums() {
disposable += repositoryImpl.topAlbumsFlowable
.subscribe({
if (it.isNotEmpty()) hashSet.add(Home(3, R.string.top_albums, 0, it, TOP_ALBUMS, R.drawable.ic_album_white_24dp))
view.showData(ArrayList(hashSet))
}, {
view.showEmptyView()
})
}
private fun loadTopArtists() {
disposable += repositoryImpl.topArtistsFlowable
.subscribe({
if (it.isNotEmpty()) hashSet.add(Home(2, R.string.top_artists, 0, it, TOP_ARTISTS, R.drawable.ic_artist_white_24dp))
view.showData(ArrayList(hashSet))
}, {
view.showEmptyView()
})
}
private fun loadFavorite() {
disposable += repositoryImpl.favoritePlaylistFlowable
.subscribe({
if (it.isNotEmpty()) hashSet.add(Home(4, R.string.favorites, 0, it, PLAYLISTS, R.drawable.ic_favorite_white_24dp))
view.showData(ArrayList(hashSet))
}, {
view.showEmptyView()
})
}
}*/
}

View File

@ -14,13 +14,15 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.mvp.BaseView
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.PresenterImpl
import code.name.monkey.retromusic.providers.interfaces.Repository
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.*
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
/**
@ -37,13 +39,29 @@ interface PlaylistsPresenter : Presenter<PlaylistView> {
class PlaylistsPresenterImpl @Inject constructor(
private val repository: Repository
) : PresenterImpl<PlaylistView>(), PlaylistsPresenter {
) : PresenterImpl<PlaylistView>(), PlaylistsPresenter, CoroutineScope {
private var disposable: Disposable? = null
private val job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO + job
override fun detachView() {
super.detachView()
job.cancel()
}
override fun playlists() {
disposable = repository.allPlaylistsFlowable
.subscribe({ view?.playlists(it) }, { t -> println(t) })
launch {
when (val result = repository.allPlaylists()) {
is Result.Success -> withContext(Dispatchers.Main) {
view?.playlists(result.data)
}
is Result.Error -> withContext(Dispatchers.Main) {
view?.showEmptyView()
}
}
}
}
}
}

View File

@ -14,14 +14,16 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.model.Playlist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.BaseView
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.PresenterImpl
import code.name.monkey.retromusic.providers.interfaces.Repository
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.*
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
/**
* Created by hemanths on 20/08/17.
@ -35,18 +37,29 @@ interface PlaylistSongsPresenter : Presenter<PlaylistSongsView> {
class PlaylistSongsPresenterImpl @Inject constructor(
private val repository: Repository
) : PresenterImpl<PlaylistSongsView>(), PlaylistSongsPresenter {
) : PresenterImpl<PlaylistSongsView>(), PlaylistSongsPresenter, CoroutineScope {
private var disposable: Disposable? = null
private var job: Job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO + job
override fun loadPlaylistSongs(playlist: Playlist) {
disposable = repository.getPlaylistSongsFlowable(playlist)
.subscribe({ view?.songs(it) }, { t -> println(t) })
launch {
when (val songs = repository.getPlaylistSongs(playlist)) {
is Result.Success -> withContext(Dispatchers.Main) {
view?.songs(songs.data)
}
is Result.Error -> withContext(Dispatchers.Main) {
view?.showEmptyView()
}
}
}
}
override fun detachView() {
super.detachView()
disposable?.dispose()
job.cancel()
}
}
}

View File

@ -14,19 +14,22 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.Result.Error
import code.name.monkey.retromusic.Result.Success
import code.name.monkey.retromusic.mvp.BaseView
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.PresenterImpl
import code.name.monkey.retromusic.providers.interfaces.Repository
import kotlinx.coroutines.*
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
/**
* Created by hemanths on 20/08/17.
*/
interface SearchView {
interface SearchView : BaseView {
fun showData(data: MutableList<Any>)
fun showEmptyView()
}
interface SearchPresenter : Presenter<SearchView> {
@ -35,18 +38,27 @@ interface SearchPresenter : Presenter<SearchView> {
class SearchPresenterImpl @Inject constructor(
private val repository: Repository
) : PresenterImpl<SearchView>(), SearchPresenter {
) : PresenterImpl<SearchView>(), SearchPresenter, CoroutineScope {
override fun attachView(view: SearchView) {
super.attachView(view)
}
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO + job
private var job: Job = Job()
override fun detachView() {
super.detachView()
job.cancel()
}
override fun search(query: String?) {
view?.showData(repository.search(query))
launch {
when (val result = repository.search(query)) {
is Success -> withContext(Dispatchers.Main) {
view?.showData(result.data)
}
is Error -> withContext(Dispatchers.Main) { view?.showEmptyView() }
}
}
}
}
}

View File

@ -14,13 +14,15 @@
package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.Presenter
import code.name.monkey.retromusic.mvp.PresenterImpl
import code.name.monkey.retromusic.providers.interfaces.Repository
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.*
import java.util.*
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
/**
* Created by hemanths on 10/08/17.
@ -33,21 +35,27 @@ interface SongView {
interface SongPresenter : Presenter<SongView> {
fun loadSongs()
class SongPresenterImpl @Inject constructor(
private val repository: Repository
) : PresenterImpl<SongView>(), SongPresenter {
) : PresenterImpl<SongView>(), SongPresenter, CoroutineScope {
private var disposable: Disposable? = null
private var job: Job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO + job
override fun loadSongs() {
disposable = repository.allSongsFlowable
.subscribe({ view?.songs(it) }, { t -> print(t) })
launch {
when (val songs = repository.allSongs()) {
is Result.Success -> withContext(Dispatchers.Main) { view?.songs(songs.data) }
is Result.Error -> view?.showEmptyView()
}
}
}
override fun detachView() {
super.detachView()
disposable?.dispose()
job.cancel();
}
}
}

View File

@ -15,7 +15,11 @@
package code.name.monkey.retromusic.providers
import android.content.Context
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.Result.Error
import code.name.monkey.retromusic.Result.Success
import code.name.monkey.retromusic.adapter.HomeAdapter
import code.name.monkey.retromusic.loaders.*
import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.providers.interfaces.Repository
@ -27,6 +31,205 @@ import io.reactivex.schedulers.Schedulers
class RepositoryImpl(private val context: Context) : Repository {
override suspend fun allAlbums(): Result<ArrayList<Album>> {
return try {
val albums = AlbumLoader.getAllAlbums(context)
if (albums.isNotEmpty()) {
Success(albums)
} else {
Error(Throwable("No items found"))
}
} catch (e: Exception) {
Error(e)
}
}
override suspend fun allArtists(): Result<ArrayList<Artist>> {
return try {
val artists = ArtistLoader.getAllArtists(context)
if (artists.isNotEmpty()) {
Success(artists)
} else {
Error(Throwable("No items found"))
}
} catch (e: Exception) {
Error(e)
}
}
override suspend fun allPlaylists(): Result<ArrayList<Playlist>> {
return try {
val playlists = PlaylistLoader.getAllPlaylists(context)
if (playlists.isNotEmpty()) {
Success(playlists)
} else {
Error(Throwable("No items found"))
}
} catch (e: Exception) {
Error(e)
}
}
override suspend fun allGenres(): Result<ArrayList<Genre>> {
return try {
val genres = GenreLoader.getAllGenres(context)
if (genres.isNotEmpty()) {
Success(genres)
} else {
Error(Throwable("No items found"))
}
} catch (e: Exception) {
Error(e)
}
}
override suspend fun search(query: String?): Result<MutableList<Any>> {
return try {
val result = SearchLoader.searchAll(context, query)
if (result.isNotEmpty()) {
Success(result)
} else {
Error(Throwable("No items found"))
}
} catch (e: Exception) {
Error(e)
}
}
override suspend fun allSongs(): Result<ArrayList<Song>> {
return try {
val songs = SongLoader.getAllSongs(context);
if (songs.isEmpty()) {
Error(Throwable("No items found"))
} else {
Success(songs);
}
} catch (e: Exception) {
Error(e);
}
}
override suspend fun getPlaylistSongs(playlist: Playlist): Result<ArrayList<Song>> {
return try {
val songs: ArrayList<Song> = if (playlist is AbsCustomPlaylist) {
playlist.getSongs(context)
} else {
PlaylistSongsLoader.getPlaylistSongList(context, playlist.id)
}
Success(songs);
} catch (e: Exception) {
Error(e)
}
}
override suspend fun getGenre(genreId: Int): Result<ArrayList<Song>> {
return try {
val songs = GenreLoader.getSongs(context, genreId)
if (songs.isEmpty()) {
Error(Throwable("No items found"))
} else {
Success(songs);
}
} catch (e: Exception) {
Error(e)
}
}
override suspend fun recentArtists(): Result<Home> {
return try {
val artists = LastAddedSongsLoader.getLastAddedArtists(context)
if (artists.isEmpty()) {
Error(Throwable("No items found"))
} else {
Success(Home(0,
R.string.recent_artists,
R.string.recent_added_artists,
artists,
HomeAdapter.RECENT_ARTISTS,
R.drawable.ic_artist_white_24dp))
}
} catch (e: Exception) {
Error(e)
}
}
override suspend fun recentAlbums(): Result<Home> {
return try {
val albums = LastAddedSongsLoader.getLastAddedAlbums(context)
if (albums.isEmpty()) {
Error(Throwable("No items found"))
} else {
Success(Home(1,
R.string.recent_albums,
R.string.recent_added_albums,
albums,
HomeAdapter.RECENT_ALBUMS,
R.drawable.ic_album_white_24dp
));
}
} catch (e: Exception) {
Error(e)
}
}
override suspend fun topAlbums(): Result<Home> {
return try {
val albums = TopAndRecentlyPlayedTracksLoader.getTopAlbums(context)
if (albums.isEmpty()) {
Error(Throwable("No items found"))
} else {
Success(Home(3,
R.string.top_albums,
R.string.most_played_albums,
albums,
HomeAdapter.TOP_ALBUMS,
R.drawable.ic_album_white_24dp
));
}
} catch (e: Exception) {
Error(e)
}
}
override suspend fun topArtists(): Result<Home> {
return try {
val artists = TopAndRecentlyPlayedTracksLoader.getTopArtists(context)
if (artists.isEmpty()) {
Error(Throwable("No items found"))
} else {
Success(Home(2,
R.string.top_artists,
R.string.most_played_artists,
artists,
HomeAdapter.TOP_ARTISTS,
R.drawable.ic_artist_white_24dp
));
}
} catch (e: Exception) {
Error(e)
}
}
override suspend fun favoritePlaylist(): Result<Home> {
return try {
val playlists = PlaylistLoader.getFavoritePlaylist(context)
if (playlists.isEmpty()) {
Error(Throwable("No items found"))
} else {
Success(Home(4,
R.string.favorites,
R.string.favorites_songs,
playlists,
HomeAdapter.PLAYLISTS,
R.drawable.ic_favorite_white_24dp
));
}
} catch (e: Exception) {
Error(e)
}
}
override fun artistInfoFloable(
name: String,
lang: String?,
@ -37,41 +240,6 @@ class RepositoryImpl(private val context: Context) : Repository {
.observeOn(AndroidSchedulers.mainThread())
}
override fun search(query: String?): MutableList<Any> {
return SearchLoader.searchAll(context, query)
}
override fun allAlbums(): ArrayList<Album> {
return AlbumLoader.getAllAlbums(context)
}
override fun recentAlbums(): ArrayList<Album> {
return LastAddedSongsLoader.getLastAddedAlbums(context)
}
override fun topAlbums(): ArrayList<Album> {
return TopAndRecentlyPlayedTracksLoader.getTopAlbums(context)
}
override fun allArtists(): ArrayList<Artist> {
return ArtistLoader.getAllArtists(context)
}
override fun recentArtists(): ArrayList<Artist> {
return LastAddedSongsLoader.getLastAddedArtists(context)
}
override fun topArtists(): ArrayList<Artist> {
return TopAndRecentlyPlayedTracksLoader.getTopArtists(context)
}
override fun allPlaylists(): ArrayList<Playlist> {
return PlaylistLoader.getAllPlaylists(context)
}
override fun allGenres(): ArrayList<Genre> {
return GenreLoader.getAllGenres(context)
}
override fun getSongFlowable(id: Int): Observable<Song> {
return SongLoader.getSongFlowable(context, id)
@ -91,10 +259,9 @@ class RepositoryImpl(private val context: Context) : Repository {
.observeOn(AndroidSchedulers.mainThread())
}
override fun getPlaylistSongsFlowable(playlist: Playlist): Observable<ArrayList<Song>> {
return PlaylistSongsLoader.getPlaylistSongListFlowable(context, playlist)
.subscribeOn(Schedulers.io())
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
}
@ -104,12 +271,6 @@ class RepositoryImpl(private val context: Context) : Repository {
.observeOn(AndroidSchedulers.mainThread())
}
override val favoritePlaylist: ArrayList<Playlist>
get() = PlaylistLoader.getFavoritePlaylist(context)
override fun allSongs(): ArrayList<Song> {
return SongLoader.getAllSongs(context)
}
override val favoritePlaylistFlowable: Observable<ArrayList<Playlist>>
get() = PlaylistLoader.getFavoritePlaylistFlowable(context)
@ -180,13 +341,5 @@ class RepositoryImpl(private val context: Context) : Repository {
return ArtistLoader.getArtist(context, artistId.toInt())
}
override fun getPlaylistSongs(playlist: Playlist): ArrayList<Song> {
return PlaylistSongsLoader.getPlaylistSongList(context, playlist)
}
override fun getGenre(genreId: Int): ArrayList<Song> {
return GenreLoader.getSongs(context, genreId)
}
}

View File

@ -14,6 +14,7 @@
package code.name.monkey.retromusic.providers.interfaces
import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.model.*
import code.name.monkey.retromusic.rest.model.LastFmArtist
import io.reactivex.Observable
@ -24,44 +25,57 @@ import io.reactivex.Observable
interface Repository {
val allSongsFlowable: Observable<ArrayList<Song>>
suspend fun allAlbums(): Result<ArrayList<Album>>
fun allSongs(): ArrayList<Song>
suspend fun allSongs(): Result<ArrayList<Song>>
suspend fun allArtists(): Result<ArrayList<Artist>>
suspend fun allPlaylists(): Result<ArrayList<Playlist>>
suspend fun allGenres(): Result<ArrayList<Genre>>
suspend fun search(query: String?): Result<MutableList<Any>>
suspend fun getPlaylistSongs(playlist: Playlist): Result<ArrayList<Song>>
suspend fun getGenre(genreId: Int): Result<ArrayList<Song>>
suspend fun recentArtists(): Result<Home>
suspend fun topArtists(): Result<Home>
suspend fun topAlbums(): Result<Home>
suspend fun recentAlbums(): Result<Home>
suspend fun favoritePlaylist(): Result<Home>
val allSongsFlowable: Observable<ArrayList<Song>>
val suggestionSongsFlowable: Observable<ArrayList<Song>>
val allAlbumsFlowable: Observable<ArrayList<Album>>
fun allAlbums(): ArrayList<Album>
val recentAlbumsFlowable: Observable<ArrayList<Album>>
fun recentAlbums(): ArrayList<Album>
val topAlbumsFlowable: Observable<ArrayList<Album>>
fun topAlbums(): ArrayList<Album>
val allArtistsFlowable: Observable<ArrayList<Artist>>
fun allArtists(): ArrayList<Artist>
val recentArtistsFlowable: Observable<ArrayList<Artist>>
fun recentArtists(): ArrayList<Artist>
val topArtistsFlowable: Observable<ArrayList<Artist>>
fun topArtists(): ArrayList<Artist>
val allPlaylistsFlowable: Observable<ArrayList<Playlist>>
fun allPlaylists(): ArrayList<Playlist>
val allGenresFlowable: Observable<ArrayList<Genre>>
fun allGenres(): ArrayList<Genre>
fun getSongFlowable(id: Int): Observable<Song>
fun getSong(id: Int): Song
@ -74,19 +88,13 @@ interface Repository {
fun getArtistById(artistId: Long): Artist
fun search(query: String?): MutableList<Any>
fun getPlaylistSongsFlowable(playlist: Playlist): Observable<ArrayList<Song>>
fun getPlaylistSongs(playlist: Playlist): ArrayList<Song>
fun getGenreFlowable(genreId: Int): Observable<ArrayList<Song>>
fun getGenre(genreId: Int): ArrayList<Song>
val favoritePlaylistFlowable: Observable<ArrayList<Playlist>>
val favoritePlaylist: ArrayList<Playlist>
fun artistInfoFloable(name: String,
lang: String?,

View File

@ -54,8 +54,16 @@
tools:background="@color/md_red_400"
tools:ignore="ContentDescription"
tools:srcCompat="@tools:sample/backgrounds/scenic[9]" />
<View
android:layout_width="match_parent"
android:layout_height="24dp"
android:layout_gravity="bottom"
android:background="@drawable/shadow_up_full_theme"
android:backgroundTint="?colorPrimary" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -78,6 +86,7 @@
android:layout_marginTop="@dimen/toolbar_margin_vertical"
android:layout_marginEnd="@dimen/toolbar_margin_horizontal"
android:layout_marginBottom="@dimen/toolbar_margin_vertical"
app:cardBackgroundColor="@android:color/transparent"
app:cardCornerRadius="8dp"
app:cardElevation="6dp"
app:cardUseCompatPadding="true"
@ -114,8 +123,8 @@
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardElevation="8dp"
app:cardBackgroundColor="?colorPrimary"
app:cardElevation="8dp"
app:shapeAppearanceOverlay="@style/TopCornerCardView">
<include layout="@layout/home_content" />

View File

@ -53,8 +53,16 @@
tools:background="@color/md_red_400"
tools:ignore="ContentDescription"
tools:srcCompat="@tools:sample/backgrounds/scenic[9]" />
<View
android:layout_width="match_parent"
android:layout_height="24dp"
android:layout_gravity="bottom"
android:background="@drawable/shadow_up_full_theme"
android:backgroundTint="?colorPrimary" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -77,6 +85,7 @@
android:layout_marginTop="@dimen/toolbar_margin_vertical"
android:layout_marginEnd="@dimen/toolbar_margin_horizontal"
android:layout_marginBottom="@dimen/toolbar_margin_vertical"
app:cardBackgroundColor="@android:color/transparent"
app:cardCornerRadius="8dp"
app:cardElevation="6dp"
app:cardUseCompatPadding="true"

View File

@ -53,6 +53,13 @@
tools:background="@color/md_red_400"
tools:ignore="ContentDescription"
tools:srcCompat="@tools:sample/backgrounds/scenic[9]" />
<View
android:layout_width="match_parent"
android:layout_height="24dp"
android:layout_gravity="bottom"
android:background="@drawable/shadow_up_full_theme"
android:backgroundTint="?colorPrimary" />
</FrameLayout>
<LinearLayout
@ -77,6 +84,7 @@
android:layout_marginTop="@dimen/toolbar_margin_vertical"
android:layout_marginEnd="@dimen/toolbar_margin_horizontal"
android:layout_marginBottom="@dimen/toolbar_margin_vertical"
app:cardBackgroundColor="@android:color/transparent"
app:cardCornerRadius="8dp"
app:cardElevation="6dp"
app:cardUseCompatPadding="true"
@ -111,8 +119,8 @@
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/toolbar_margin_horizontal"
android:layout_marginEnd="@dimen/toolbar_margin_horizontal"
app:cardElevation="8dp"
app:cardBackgroundColor="?colorPrimary"
app:cardElevation="8dp"
app:shapeAppearanceOverlay="@style/TopCornerCardView">
<include layout="@layout/home_content" />

View File

@ -29,43 +29,27 @@
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways">
<ViewStub
android:id="@+id/cab_stub"
android:layout_width="match_parent"
android:layout_height="48dp" />
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
style="@style/Toolbar"
app:navigationIcon="@drawable/ic_keyboard_backspace_black_24dp"
app:titleTextAppearance="@style/ToolbarTextAppearanceNormal" />
<ViewStub
android:id="@+id/cab_stub"
android:layout_width="match_parent"
android:layout_height="48dp" />
</FrameLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
<com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollbars="none" />
<Space
android:layout_width="match_parent"
android:layout_height="52dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
android:clipToPadding="false"
android:scrollbars="none"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
<LinearLayout
android:id="@android:id/empty"
@ -73,7 +57,9 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical">
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="96dp"

View File

@ -69,36 +69,25 @@
</com.google.android.material.card.MaterialCardView>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
<com.google.android.material.textview.MaterialTextView
android:id="@android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/no_results"
android:textAppearance="@style/TextViewHeadline6"
android:visibility="gone"
tools:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textview.MaterialTextView
android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="48dp"
android:paddingBottom="48dp"
android:text="@string/no_results"
android:textAppearance="@style/TextViewHeadline6"
android:visibility="gone"
tools:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical" />
</FrameLayout>
</androidx.core.widget.NestedScrollView>
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/keyboardPopup"

View File

@ -66,7 +66,7 @@
</FrameLayout>
<FrameLayout
<com.google.android.material.card.MaterialCardView
android:id="@+id/toolbarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -74,6 +74,9 @@
android:layout_marginTop="@dimen/toolbar_margin_vertical"
android:layout_marginEnd="@dimen/toolbar_margin_horizontal"
android:layout_marginBottom="@dimen/toolbar_margin_vertical"
app:cardBackgroundColor="@android:color/transparent"
app:cardCornerRadius="8dp"
app:cardUseCompatPadding="true"
app:layout_scrollFlags="scroll|enterAlways"
app:shapeAppearance="@style/ToolbarCornerCardView">
@ -89,7 +92,7 @@
app:titleMarginStart="0dp"
app:titleTextAppearance="@style/ToolbarTextAppearanceSearch"
tools:ignore="UnusedAttribute" />
</FrameLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
@ -103,8 +106,8 @@
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="8dp"
app:cardBackgroundColor="?colorPrimary"
app:cardElevation="8dp"
app:shapeAppearanceOverlay="@style/TopCornerCardView">
<include layout="@layout/home_content" />

View File

@ -42,6 +42,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextViewCaption"
android:visibility="gone"
tools:text="@tools:sample/full_names" />
</LinearLayout>

View File

@ -39,6 +39,7 @@
<com.google.android.material.textview.MaterialTextView
android:id="@+id/text"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextViewCaption"

View File

@ -620,7 +620,7 @@
<string name="grid_style_label"><![CDATA[Grids & Style]]></string>
<string name="welcome">Welcome,</string>
<string name="premium">Get Premium</string>
<string name="pro_summary">Now playing themes, Carousel effect, Color theme and more..</string>
<string name="pro_summary">Now playing themes, Carousel effect and more..</string>
<string name="action_play_all">Play all</string>
<string name="start_play_music">Start playing music.</string>
<string name="keyboard">Keyboard</string>

View File

@ -27,7 +27,7 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.1.0-alpha10'
implementation 'com.google.android.material:material:1.1.0-beta01'
implementation 'androidx.preference:preference:1.1.0'
implementation 'androidx.cardview:cardview:1.0.0'
// Used for the list preference classes