MVP is Gone
parent
f0663c2b43
commit
17a66450d4
|
@ -163,4 +163,9 @@ dependencies {
|
||||||
implementation 'me.jorgecastillo:androidcolorx:0.2.0'
|
implementation 'me.jorgecastillo:androidcolorx:0.2.0'
|
||||||
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
|
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
|
||||||
implementation 'com.github.dhaval2404:imagepicker:1.7.1'
|
implementation 'com.github.dhaval2404:imagepicker:1.7.1'
|
||||||
|
|
||||||
|
def koin_version = "2.1.5"
|
||||||
|
implementation "org.koin:koin-core:$koin_version"
|
||||||
|
implementation "org.koin:koin-android:$koin_version"
|
||||||
|
implementation "org.koin:koin-android-viewmodel:$koin_version"
|
||||||
}
|
}
|
|
@ -107,7 +107,7 @@
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".activities.albums.AlbumDetailsActivity" />
|
<activity android:name=".activities.albums.AlbumDetailsActivity" />
|
||||||
<activity android:name=".activities.artists.ArtistDetailActivity" />
|
<activity android:name=".activities.artists.ArtistDetailActivity" />
|
||||||
<activity android:name=".activities.PlaylistDetailActivity" />
|
<activity android:name=".activities.playlist.PlaylistDetailActivity" />
|
||||||
<activity android:name=".activities.PlayingQueueActivity" />
|
<activity android:name=".activities.PlayingQueueActivity" />
|
||||||
<activity android:name=".activities.AboutActivity" />
|
<activity android:name=".activities.AboutActivity" />
|
||||||
<activity android:name=".activities.tageditor.AlbumTagEditorActivity" />
|
<activity android:name=".activities.tageditor.AlbumTagEditorActivity" />
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
<activity android:name=".activities.LyricsActivity" />
|
<activity android:name=".activities.LyricsActivity" />
|
||||||
<activity android:name=".activities.UserInfoActivity" />
|
<activity android:name=".activities.UserInfoActivity" />
|
||||||
<activity android:name=".activities.SupportDevelopmentActivity" />
|
<activity android:name=".activities.SupportDevelopmentActivity" />
|
||||||
<activity android:name=".activities.GenreDetailsActivity" />
|
<activity android:name=".activities.genre.GenreDetailsActivity" />
|
||||||
<activity android:name=".activities.LicenseActivity" />
|
<activity android:name=".activities.LicenseActivity" />
|
||||||
<activity android:name=".activities.PurchaseActivity" />
|
<activity android:name=".activities.PurchaseActivity" />
|
||||||
<activity android:name=".activities.WhatsNewActivity" />
|
<activity android:name=".activities.WhatsNewActivity" />
|
||||||
|
@ -124,7 +124,7 @@
|
||||||
<activity android:name=".activities.ShareInstagramStory" />
|
<activity android:name=".activities.ShareInstagramStory" />
|
||||||
<activity android:name=".activities.DriveModeActivity" />
|
<activity android:name=".activities.DriveModeActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.SearchActivity"
|
android:name=".activities.search.SearchActivity"
|
||||||
android:windowSoftInputMode="stateVisible" />
|
android:windowSoftInputMode="stateVisible" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
|
|
@ -20,8 +20,11 @@ import code.name.monkey.appthemehelper.ThemeStore
|
||||||
import code.name.monkey.appthemehelper.util.VersionUtils
|
import code.name.monkey.appthemehelper.util.VersionUtils
|
||||||
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
|
import code.name.monkey.retromusic.Constants.PRO_VERSION_PRODUCT_ID
|
||||||
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
import code.name.monkey.retromusic.appshortcuts.DynamicShortcutManager
|
||||||
|
import code.name.monkey.retromusic.providers.provideModules
|
||||||
import com.anjlab.android.iab.v3.BillingProcessor
|
import com.anjlab.android.iab.v3.BillingProcessor
|
||||||
import com.anjlab.android.iab.v3.TransactionDetails
|
import com.anjlab.android.iab.v3.TransactionDetails
|
||||||
|
import org.koin.android.ext.koin.androidContext
|
||||||
|
import org.koin.core.context.startKoin
|
||||||
|
|
||||||
class App : MultiDexApplication() {
|
class App : MultiDexApplication() {
|
||||||
|
|
||||||
|
@ -31,6 +34,10 @@ class App : MultiDexApplication() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
instance = this
|
instance = this
|
||||||
|
|
||||||
|
startKoin {
|
||||||
|
androidContext(this@App)
|
||||||
|
modules(listOf(mainModule, provideModules))
|
||||||
|
}
|
||||||
// default theme
|
// default theme
|
||||||
if (!ThemeStore.isConfigured(this, 3)) {
|
if (!ThemeStore.isConfigured(this, 3)) {
|
||||||
ThemeStore.editTheme(this)
|
ThemeStore.editTheme(this)
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package code.name.monkey.retromusic
|
||||||
|
|
||||||
|
import code.name.monkey.retromusic.activities.albums.AlbumDetailsViewModel
|
||||||
|
import code.name.monkey.retromusic.activities.artists.ArtistDetailsViewModel
|
||||||
|
import code.name.monkey.retromusic.activities.genre.GenreDetailsViewModel
|
||||||
|
import code.name.monkey.retromusic.activities.playlist.PlaylistDetailsViewModel
|
||||||
|
import code.name.monkey.retromusic.activities.search.SearchViewModel
|
||||||
|
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||||
|
import code.name.monkey.retromusic.model.Genre
|
||||||
|
import code.name.monkey.retromusic.model.Playlist
|
||||||
|
import org.koin.android.viewmodel.dsl.viewModel
|
||||||
|
import org.koin.dsl.module
|
||||||
|
|
||||||
|
|
||||||
|
val mainModule = module {
|
||||||
|
|
||||||
|
viewModel {
|
||||||
|
LibraryViewModel(get())
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel { (albumId: Int) ->
|
||||||
|
AlbumDetailsViewModel(get(), albumId)
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel { (artistId: Int) ->
|
||||||
|
ArtistDetailsViewModel(get(), artistId)
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel { (playlist: Playlist) ->
|
||||||
|
PlaylistDetailsViewModel(get(), playlist)
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel { (genre: Genre) ->
|
||||||
|
GenreDetailsViewModel(get(), genre)
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel {
|
||||||
|
SearchViewModel(get())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* 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>()
|
|
||||||
}
|
|
|
@ -13,7 +13,6 @@ import android.view.View
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.commit
|
import androidx.fragment.app.commit
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import code.name.monkey.appthemehelper.ThemeStore.Companion.accentColor
|
import code.name.monkey.appthemehelper.ThemeStore.Companion.accentColor
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil.resolveColor
|
import code.name.monkey.appthemehelper.util.ATHUtil.resolveColor
|
||||||
|
@ -64,6 +63,7 @@ import com.google.android.play.core.install.model.InstallStatus.INSTALLED
|
||||||
import com.google.android.play.core.install.model.UpdateAvailability
|
import com.google.android.play.core.install.model.UpdateAvailability
|
||||||
import com.google.android.play.core.tasks.Task
|
import com.google.android.play.core.tasks.Task
|
||||||
import kotlinx.android.synthetic.main.activity_main_content.*
|
import kotlinx.android.synthetic.main.activity_main_content.*
|
||||||
|
import org.koin.android.ext.android.inject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class MainActivity : AbsSlidingMusicPanelActivity(),
|
class MainActivity : AbsSlidingMusicPanelActivity(),
|
||||||
|
@ -74,7 +74,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
|
||||||
const val APP_UPDATE_REQUEST_CODE = 9002
|
const val APP_UPDATE_REQUEST_CODE = 9002
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var libraryViewModel: LibraryViewModel
|
val libraryViewModel: LibraryViewModel by inject()
|
||||||
private var cab: MaterialCab? = null
|
private var cab: MaterialCab? = null
|
||||||
private val intentFilter = IntentFilter(Intent.ACTION_SCREEN_OFF)
|
private val intentFilter = IntentFilter(Intent.ACTION_SCREEN_OFF)
|
||||||
private lateinit var currentFragment: MainActivityFragmentCallbacks
|
private lateinit var currentFragment: MainActivityFragmentCallbacks
|
||||||
|
@ -123,9 +123,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(),
|
||||||
hideStatusBar()
|
hideStatusBar()
|
||||||
setBottomBarVisibility(View.VISIBLE)
|
setBottomBarVisibility(View.VISIBLE)
|
||||||
|
|
||||||
libraryViewModel = ViewModelProvider(this).get(LibraryViewModel::class.java)
|
|
||||||
addMusicServiceEventListener(libraryViewModel)
|
addMusicServiceEventListener(libraryViewModel)
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
selectedFragment(PreferenceUtil.lastPage)
|
selectedFragment(PreferenceUtil.lastPage)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import android.view.SubMenu
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
@ -37,7 +36,6 @@ import code.name.monkey.retromusic.helper.SortOrder.AlbumSongSortOrder
|
||||||
import code.name.monkey.retromusic.interfaces.CabHolder
|
import code.name.monkey.retromusic.interfaces.CabHolder
|
||||||
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.mvp.presenter.AlbumDetailsView
|
|
||||||
import code.name.monkey.retromusic.rest.model.LastFmAlbum
|
import code.name.monkey.retromusic.rest.model.LastFmAlbum
|
||||||
import code.name.monkey.retromusic.util.*
|
import code.name.monkey.retromusic.util.*
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -45,10 +43,12 @@ import com.afollestad.materialcab.MaterialCab
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import kotlinx.android.synthetic.main.activity_album.*
|
import kotlinx.android.synthetic.main.activity_album.*
|
||||||
import kotlinx.android.synthetic.main.activity_album_content.*
|
import kotlinx.android.synthetic.main.activity_album_content.*
|
||||||
|
import org.koin.android.viewmodel.ext.android.viewModel
|
||||||
|
import org.koin.core.parameter.parametersOf
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import android.util.Pair as UtilPair
|
import android.util.Pair as UtilPair
|
||||||
|
|
||||||
class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, CabHolder {
|
class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
|
||||||
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
||||||
cab?.let {
|
cab?.let {
|
||||||
if (it.isActive) it.finish()
|
if (it.isActive) it.finish()
|
||||||
|
@ -68,7 +68,9 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
return cab as MaterialCab
|
return cab as MaterialCab
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var viewModel: AlbumDetailsViewModel
|
private val detailsViewModel: AlbumDetailsViewModel by viewModel {
|
||||||
|
parametersOf(extraNotNull<Int>(EXTRA_ALBUM_ID).value)
|
||||||
|
}
|
||||||
private lateinit var simpleSongAdapter: SimpleSongAdapter
|
private lateinit var simpleSongAdapter: SimpleSongAdapter
|
||||||
private lateinit var album: Album
|
private lateinit var album: Album
|
||||||
private lateinit var artistImage: ImageView
|
private lateinit var artistImage: ImageView
|
||||||
|
@ -100,19 +102,19 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
window.sharedElementsUseOverlay = true
|
window.sharedElementsUseOverlay = true
|
||||||
windowEnterTransition()
|
windowEnterTransition()
|
||||||
|
|
||||||
val albumId = extraNotNull<Int>(EXTRA_ALBUM_ID).value
|
addMusicServiceEventListener(detailsViewModel)
|
||||||
ActivityCompat.postponeEnterTransition(this)
|
ActivityCompat.postponeEnterTransition(this)
|
||||||
val viewModelFactory = AlbumDetailsViewModelFactory(application, albumId)
|
//val viewModelFactory = AlbumDetailsViewModelFactory(application, albumId)
|
||||||
viewModel = ViewModelProvider(this, viewModelFactory).get(AlbumDetailsViewModel::class.java)
|
//viewModel = ViewModelProvider(this, viewModelFactory).get(AlbumDetailsViewModel::class.java)
|
||||||
addMusicServiceEventListener(viewModel)
|
|
||||||
viewModel.getAlbum().observe(this, androidx.lifecycle.Observer {
|
detailsViewModel.getAlbum().observe(this, androidx.lifecycle.Observer {
|
||||||
ActivityCompat.startPostponedEnterTransition(this@AlbumDetailsActivity)
|
ActivityCompat.startPostponedEnterTransition(this@AlbumDetailsActivity)
|
||||||
album(it)
|
album(it)
|
||||||
})
|
})
|
||||||
viewModel.getArtist().observe(this, androidx.lifecycle.Observer {
|
detailsViewModel.getArtist().observe(this, androidx.lifecycle.Observer {
|
||||||
loadArtistImage(it)
|
loadArtistImage(it)
|
||||||
})
|
})
|
||||||
viewModel.getAlbumInfo().observe(this, androidx.lifecycle.Observer {
|
detailsViewModel.getAlbumInfo().observe(this, androidx.lifecycle.Observer {
|
||||||
aboutAlbum(it)
|
aboutAlbum(it)
|
||||||
})
|
})
|
||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
|
@ -153,11 +155,11 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun complete() {
|
fun complete() {
|
||||||
ActivityCompat.startPostponedEnterTransition(this)
|
ActivityCompat.startPostponedEnterTransition(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun album(album: Album) {
|
fun album(album: Album) {
|
||||||
complete()
|
complete()
|
||||||
if (album.songs!!.isEmpty()) {
|
if (album.songs!!.isEmpty()) {
|
||||||
finish()
|
finish()
|
||||||
|
@ -190,11 +192,11 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
}
|
}
|
||||||
loadAlbumCover()
|
loadAlbumCover()
|
||||||
simpleSongAdapter.swapDataSet(album.songs)
|
simpleSongAdapter.swapDataSet(album.songs)
|
||||||
viewModel.loadArtist(album.artistId)
|
detailsViewModel.loadArtist(album.artistId)
|
||||||
viewModel.loadAlbumInfo(album)
|
detailsViewModel.loadAlbumInfo(album)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun moreAlbums(albums: List<Album>) {
|
fun moreAlbums(albums: List<Album>) {
|
||||||
moreTitle.show()
|
moreTitle.show()
|
||||||
moreRecyclerView.show()
|
moreRecyclerView.show()
|
||||||
moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName)
|
moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName)
|
||||||
|
@ -209,7 +211,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
moreRecyclerView.adapter = albumAdapter
|
moreRecyclerView.adapter = albumAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun aboutAlbum(lastFmAlbum: LastFmAlbum) {
|
fun aboutAlbum(lastFmAlbum: LastFmAlbum) {
|
||||||
if (lastFmAlbum.album != null) {
|
if (lastFmAlbum.album != null) {
|
||||||
if (lastFmAlbum.album.wiki != null) {
|
if (lastFmAlbum.album.wiki != null) {
|
||||||
aboutAlbumText.show()
|
aboutAlbumText.show()
|
||||||
|
@ -230,7 +232,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadArtistImage(artist: Artist) {
|
fun loadArtistImage(artist: Artist) {
|
||||||
ArtistGlideRequest.Builder.from(Glide.with(this), artist)
|
ArtistGlideRequest.Builder.from(Glide.with(this), artist)
|
||||||
.generatePalette(this)
|
.generatePalette(this)
|
||||||
.build()
|
.build()
|
||||||
|
@ -391,8 +393,9 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
removeMusicServiceEventListener(viewModel)
|
removeMusicServiceEventListener(detailsViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val EXTRA_ALBUM_ID = "extra_album_id"
|
const val EXTRA_ALBUM_ID = "extra_album_id"
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package code.name.monkey.retromusic.activities.albums
|
package code.name.monkey.retromusic.activities.albums
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import androidx.lifecycle.AndroidViewModel
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||||
import code.name.monkey.retromusic.model.Album
|
import code.name.monkey.retromusic.model.Album
|
||||||
|
@ -16,10 +15,10 @@ import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class AlbumDetailsViewModel(
|
class AlbumDetailsViewModel(
|
||||||
application: Application,
|
private val repository: RepositoryImpl,
|
||||||
private val albumId: Int
|
private val albumId: Int
|
||||||
) : AndroidViewModel(application), MusicServiceEventListener {
|
) : ViewModel(), MusicServiceEventListener {
|
||||||
private val _repository = RepositoryImpl(application.applicationContext)
|
|
||||||
private val _album = MutableLiveData<Album>()
|
private val _album = MutableLiveData<Album>()
|
||||||
private val _artist = MutableLiveData<Artist>()
|
private val _artist = MutableLiveData<Artist>()
|
||||||
private val _lastFmAlbum = MutableLiveData<LastFmAlbum>()
|
private val _lastFmAlbum = MutableLiveData<LastFmAlbum>()
|
||||||
|
@ -38,18 +37,18 @@ class AlbumDetailsViewModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadAlbumInfo(album: Album) = viewModelScope.launch(Dispatchers.IO) {
|
fun loadAlbumInfo(album: Album) = viewModelScope.launch(Dispatchers.IO) {
|
||||||
val lastFmAlbum = _repository.albumInfo(album.artistName ?: "-", album.title ?: "-")
|
val lastFmAlbum = repository.albumInfo(album.artistName ?: "-", album.title ?: "-")
|
||||||
_lastFmAlbum.postValue(lastFmAlbum)
|
_lastFmAlbum.postValue(lastFmAlbum)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadArtist(artistId: Int) = viewModelScope.launch(Dispatchers.IO) {
|
fun loadArtist(artistId: Int) = viewModelScope.launch(Dispatchers.IO) {
|
||||||
val artist = _repository.artistById(artistId)
|
val artist = repository.artistById(artistId)
|
||||||
_artist.postValue(artist)
|
_artist.postValue(artist)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val loadAlbumAsync: Deferred<Album?>
|
private val loadAlbumAsync: Deferred<Album?>
|
||||||
get() = viewModelScope.async(Dispatchers.IO) {
|
get() = viewModelScope.async(Dispatchers.IO) {
|
||||||
_repository.albumById(albumId)
|
repository.albumById(albumId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMediaStoreChanged() {
|
override fun onMediaStoreChanged() {
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package code.name.monkey.retromusic.activities.albums
|
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
|
|
||||||
class AlbumDetailsViewModelFactory(
|
|
||||||
private val application: Application,
|
|
||||||
private val albumId: Int
|
|
||||||
) :
|
|
||||||
ViewModelProvider.AndroidViewModelFactory(application) {
|
|
||||||
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
|
||||||
return if (modelClass.isAssignableFrom(AlbumDetailsViewModel::class.java)) {
|
|
||||||
AlbumDetailsViewModel(application, albumId) as T
|
|
||||||
} else {
|
|
||||||
throw IllegalArgumentException("ViewModel Not Found")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,7 +11,6 @@ import android.view.View
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.recyclerview.widget.DefaultItemAnimator
|
import androidx.recyclerview.widget.DefaultItemAnimator
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
@ -31,7 +30,6 @@ import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.interfaces.CabHolder
|
import code.name.monkey.retromusic.interfaces.CabHolder
|
||||||
import code.name.monkey.retromusic.model.Artist
|
import code.name.monkey.retromusic.model.Artist
|
||||||
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsView
|
|
||||||
import code.name.monkey.retromusic.rest.model.LastFmArtist
|
import code.name.monkey.retromusic.rest.model.LastFmArtist
|
||||||
import code.name.monkey.retromusic.util.*
|
import code.name.monkey.retromusic.util.*
|
||||||
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
import code.name.monkey.retromusic.util.color.MediaNotificationProcessor
|
||||||
|
@ -39,10 +37,12 @@ import com.afollestad.materialcab.MaterialCab
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import kotlinx.android.synthetic.main.activity_artist_content.*
|
import kotlinx.android.synthetic.main.activity_artist_content.*
|
||||||
import kotlinx.android.synthetic.main.activity_artist_details.*
|
import kotlinx.android.synthetic.main.activity_artist_details.*
|
||||||
|
import org.koin.android.viewmodel.ext.android.viewModel
|
||||||
|
import org.koin.core.parameter.parametersOf
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView, CabHolder {
|
class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
|
||||||
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
override fun openCab(menuRes: Int, callback: MaterialCab.Callback): MaterialCab {
|
||||||
cab?.let {
|
cab?.let {
|
||||||
if (it.isActive) it.finish()
|
if (it.isActive) it.finish()
|
||||||
|
@ -68,7 +68,9 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
private lateinit var songAdapter: SimpleSongAdapter
|
private lateinit var songAdapter: SimpleSongAdapter
|
||||||
private lateinit var albumAdapter: HorizontalAlbumAdapter
|
private lateinit var albumAdapter: HorizontalAlbumAdapter
|
||||||
private var forceDownload: Boolean = false
|
private var forceDownload: Boolean = false
|
||||||
private lateinit var viewModel: ArtistDetailsViewModel
|
private val detailsViewModel: ArtistDetailsViewModel by viewModel {
|
||||||
|
parametersOf(extraNotNull<Int>(EXTRA_ARTIST_ID).value)
|
||||||
|
}
|
||||||
|
|
||||||
override fun createContentView(): View {
|
override fun createContentView(): View {
|
||||||
return wrapSlidingMusicPanel(R.layout.activity_artist_details)
|
return wrapSlidingMusicPanel(R.layout.activity_artist_details)
|
||||||
|
@ -93,23 +95,16 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
setBottomBarVisibility(View.GONE)
|
setBottomBarVisibility(View.GONE)
|
||||||
window.sharedElementsUseOverlay = true
|
window.sharedElementsUseOverlay = true
|
||||||
windowEnterTransition()
|
windowEnterTransition()
|
||||||
|
ActivityCompat.postponeEnterTransition(this)
|
||||||
val artistId = extraNotNull<Int>(EXTRA_ARTIST_ID).value
|
addMusicServiceEventListener(detailsViewModel)
|
||||||
val viewModelFactory = ArtistDetailsViewModelFactory(application, artistId)
|
detailsViewModel.getArtist().observe(this, androidx.lifecycle.Observer {
|
||||||
viewModel =
|
|
||||||
ViewModelProvider(this, viewModelFactory).get(ArtistDetailsViewModel::class.java)
|
|
||||||
addMusicServiceEventListener(viewModel)
|
|
||||||
viewModel.getArtist().observe(this, androidx.lifecycle.Observer {
|
|
||||||
ActivityCompat.startPostponedEnterTransition(this@ArtistDetailActivity)
|
ActivityCompat.startPostponedEnterTransition(this@ArtistDetailActivity)
|
||||||
artist(it)
|
artist(it)
|
||||||
})
|
})
|
||||||
viewModel.getArtistInfo().observe(this, androidx.lifecycle.Observer {
|
detailsViewModel.getArtistInfo().observe(this, androidx.lifecycle.Observer {
|
||||||
artistInfo(it)
|
artistInfo(it)
|
||||||
})
|
})
|
||||||
ActivityCompat.postponeEnterTransition(this)
|
|
||||||
|
|
||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
|
|
||||||
playAction.apply {
|
playAction.apply {
|
||||||
setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) }
|
setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) }
|
||||||
}
|
}
|
||||||
|
@ -155,14 +150,11 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showEmptyView() {
|
fun complete() {
|
||||||
}
|
|
||||||
|
|
||||||
override fun complete() {
|
|
||||||
ActivityCompat.startPostponedEnterTransition(this)
|
ActivityCompat.startPostponedEnterTransition(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun artist(artist: Artist) {
|
fun artist(artist: Artist) {
|
||||||
complete()
|
complete()
|
||||||
if (artist.songCount <= 0) {
|
if (artist.songCount <= 0) {
|
||||||
finish()
|
finish()
|
||||||
|
@ -203,10 +195,10 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
) {
|
) {
|
||||||
biography = null
|
biography = null
|
||||||
this.lang = lang
|
this.lang = lang
|
||||||
viewModel.loadBiography(name, lang, null)
|
detailsViewModel.loadBiography(name, lang, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun artistInfo(lastFmArtist: LastFmArtist?) {
|
fun artistInfo(lastFmArtist: LastFmArtist?) {
|
||||||
if (lastFmArtist != null && lastFmArtist.artist != null) {
|
if (lastFmArtist != null && lastFmArtist.artist != null) {
|
||||||
val bioContent = lastFmArtist.artist.bio.content
|
val bioContent = lastFmArtist.artist.bio.content
|
||||||
if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
|
if (bioContent != null && bioContent.trim { it <= ' ' }.isNotEmpty()) {
|
||||||
|
@ -323,7 +315,7 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
removeMusicServiceEventListener(viewModel)
|
removeMusicServiceEventListener(detailsViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package code.name.monkey.retromusic.activities.artists
|
package code.name.monkey.retromusic.activities.artists
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import androidx.lifecycle.AndroidViewModel
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||||
import code.name.monkey.retromusic.model.Artist
|
import code.name.monkey.retromusic.model.Artist
|
||||||
|
@ -15,15 +14,15 @@ import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class ArtistDetailsViewModel(
|
class ArtistDetailsViewModel(
|
||||||
application: Application,
|
private val repository: RepositoryImpl,
|
||||||
private val artistId: Int
|
private val artistId: Int
|
||||||
) : AndroidViewModel(application), MusicServiceEventListener {
|
) : ViewModel(), MusicServiceEventListener {
|
||||||
|
|
||||||
private val loadArtistDetailsAsync: Deferred<Artist?>
|
private val loadArtistDetailsAsync: Deferred<Artist?>
|
||||||
get() = viewModelScope.async(Dispatchers.IO) {
|
get() = viewModelScope.async(Dispatchers.IO) {
|
||||||
_repository.artistById(artistId)
|
repository.artistById(artistId)
|
||||||
}
|
}
|
||||||
private val _repository = RepositoryImpl(application.applicationContext)
|
|
||||||
private val _artist = MutableLiveData<Artist>()
|
private val _artist = MutableLiveData<Artist>()
|
||||||
private val _lastFmArtist = MutableLiveData<LastFmArtist>()
|
private val _lastFmArtist = MutableLiveData<LastFmArtist>()
|
||||||
|
|
||||||
|
@ -41,7 +40,7 @@ class ArtistDetailsViewModel(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadBiography(name: String, lang: String?, cache: String?) = viewModelScope.launch {
|
fun loadBiography(name: String, lang: String?, cache: String?) = viewModelScope.launch {
|
||||||
val info = _repository.artistInfo(name, lang, cache)
|
val info = repository.artistInfo(name, lang, cache)
|
||||||
_lastFmArtist.postValue(info)
|
_lastFmArtist.postValue(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package code.name.monkey.retromusic.activities.artists
|
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
|
|
||||||
class ArtistDetailsViewModelFactory(
|
|
||||||
private val application: Application,
|
|
||||||
private val artistId: Int
|
|
||||||
) :
|
|
||||||
ViewModelProvider.AndroidViewModelFactory(application) {
|
|
||||||
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
|
||||||
return if (modelClass.isAssignableFrom(ArtistDetailsViewModel::class.java)) {
|
|
||||||
ArtistDetailsViewModel(application, artistId) as T
|
|
||||||
} else {
|
|
||||||
throw IllegalArgumentException("ViewModel Not Found")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
package code.name.monkey.retromusic.activities
|
package code.name.monkey.retromusic.activities.genre
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
@ -17,24 +17,25 @@ import code.name.monkey.retromusic.helper.menu.GenreMenuHelper
|
||||||
import code.name.monkey.retromusic.interfaces.CabHolder
|
import code.name.monkey.retromusic.interfaces.CabHolder
|
||||||
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.mvp.presenter.GenreDetailsPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.GenreDetailsPresenter.GenreDetailsPresenterImpl
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.GenreDetailsView
|
|
||||||
import code.name.monkey.retromusic.providers.RepositoryImpl
|
|
||||||
import code.name.monkey.retromusic.util.DensityUtil
|
import code.name.monkey.retromusic.util.DensityUtil
|
||||||
import code.name.monkey.retromusic.util.RetroColorUtil
|
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||||
import com.afollestad.materialcab.MaterialCab
|
import com.afollestad.materialcab.MaterialCab
|
||||||
import kotlinx.android.synthetic.main.activity_playlist_detail.*
|
import kotlinx.android.synthetic.main.activity_playlist_detail.*
|
||||||
|
import org.koin.android.viewmodel.ext.android.viewModel
|
||||||
|
import org.koin.core.parameter.parametersOf
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Hemanth S (h4h13).
|
* @author Hemanth S (h4h13).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder, GenreDetailsView {
|
class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder {
|
||||||
|
|
||||||
|
|
||||||
private lateinit var genreDetailsPresenter: GenreDetailsPresenter
|
private val detailsViewModel: GenreDetailsViewModel by viewModel {
|
||||||
|
parametersOf(extraNotNull<Genre>(EXTRA_GENRE_ID).value)
|
||||||
|
}
|
||||||
|
|
||||||
private lateinit var genre: Genre
|
private lateinit var genre: Genre
|
||||||
private lateinit var songAdapter: ShuffleButtonSongAdapter
|
private lateinit var songAdapter: ShuffleButtonSongAdapter
|
||||||
private var cab: MaterialCab? = null
|
private var cab: MaterialCab? = null
|
||||||
|
@ -62,38 +63,25 @@ class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder, GenreDet
|
||||||
setTaskDescriptionColorAuto()
|
setTaskDescriptionColorAuto()
|
||||||
setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
setBottomBarVisibility(View.GONE)
|
setBottomBarVisibility(View.GONE)
|
||||||
|
applyToolbar(toolbar)
|
||||||
genre = extraNotNull<Genre>(EXTRA_GENRE_ID).value
|
|
||||||
|
|
||||||
setUpToolBar()
|
|
||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
|
|
||||||
genreDetailsPresenter =
|
detailsViewModel.getSongs().observe(this, androidx.lifecycle.Observer {
|
||||||
GenreDetailsPresenterImpl(RepositoryImpl(this))
|
songs(it)
|
||||||
genreDetailsPresenter.attachView(this)
|
})
|
||||||
}
|
|
||||||
|
|
||||||
private fun setUpToolBar() {
|
detailsViewModel.getGenre().observe(this, androidx.lifecycle.Observer {
|
||||||
applyToolbar(toolbar)
|
genre = it
|
||||||
title = genre.name
|
supportActionBar?.title = it.name
|
||||||
}
|
})
|
||||||
|
|
||||||
override fun onResume() {
|
addMusicServiceEventListener(detailsViewModel)
|
||||||
super.onResume()
|
|
||||||
genreDetailsPresenter.loadGenreSongs(genre.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
genreDetailsPresenter.detachView()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createContentView(): View {
|
override fun createContentView(): View {
|
||||||
return wrapSlidingMusicPanel(R.layout.activity_playlist_detail)
|
return wrapSlidingMusicPanel(R.layout.activity_playlist_detail)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showEmptyView() {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
menuInflater.inflate(R.menu.menu_genre_detail, menu)
|
menuInflater.inflate(R.menu.menu_genre_detail, menu)
|
||||||
|
@ -122,7 +110,7 @@ class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder, GenreDet
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun songs(songs: List<Song>) {
|
fun songs(songs: List<Song>) {
|
||||||
songAdapter.swapDataSet(songs)
|
songAdapter.swapDataSet(songs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,11 +137,6 @@ class GenreDetailsActivity : AbsSlidingMusicPanelActivity(), CabHolder, GenreDet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMediaStoreChanged() {
|
|
||||||
super.onMediaStoreChanged()
|
|
||||||
genreDetailsPresenter.loadGenreSongs(genre.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val EXTRA_GENRE_ID = "extra_genre_id"
|
const val EXTRA_GENRE_ID = "extra_genre_id"
|
||||||
}
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package code.name.monkey.retromusic.activities.genre
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||||
|
import code.name.monkey.retromusic.model.Genre
|
||||||
|
import code.name.monkey.retromusic.model.Song
|
||||||
|
import code.name.monkey.retromusic.providers.RepositoryImpl
|
||||||
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class GenreDetailsViewModel(
|
||||||
|
private val repository: RepositoryImpl,
|
||||||
|
private val genre: Genre
|
||||||
|
) : ViewModel(), MusicServiceEventListener {
|
||||||
|
|
||||||
|
private val _playListSongs = MutableLiveData<List<Song>>()
|
||||||
|
private val _genre = MutableLiveData<Genre>().apply {
|
||||||
|
postValue(genre)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSongs(): LiveData<List<Song>> = _playListSongs
|
||||||
|
|
||||||
|
fun getGenre(): LiveData<Genre> = _genre
|
||||||
|
|
||||||
|
init {
|
||||||
|
loadGenreSongs(genre)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadGenreSongs(genre: Genre) = viewModelScope.launch {
|
||||||
|
val songs = repository.getGenre(genre.id)
|
||||||
|
withContext(Main) { _playListSongs.postValue(songs) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMediaStoreChanged() {
|
||||||
|
loadGenreSongs(genre)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceConnected() {}
|
||||||
|
override fun onServiceDisconnected() {}
|
||||||
|
override fun onQueueChanged() {}
|
||||||
|
override fun onPlayingMetaChanged() {}
|
||||||
|
override fun onPlayStateChanged() {}
|
||||||
|
override fun onRepeatModeChanged() {}
|
||||||
|
override fun onShuffleModeChanged() {}
|
||||||
|
}
|
|
@ -1,9 +1,10 @@
|
||||||
package code.name.monkey.retromusic.activities
|
package code.name.monkey.retromusic.activities.playlist
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import code.name.monkey.appthemehelper.util.ATHUtil
|
import code.name.monkey.appthemehelper.util.ATHUtil
|
||||||
|
@ -16,14 +17,9 @@ import code.name.monkey.retromusic.extensions.applyToolbar
|
||||||
import code.name.monkey.retromusic.extensions.extraNotNull
|
import code.name.monkey.retromusic.extensions.extraNotNull
|
||||||
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
|
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
|
||||||
import code.name.monkey.retromusic.interfaces.CabHolder
|
import code.name.monkey.retromusic.interfaces.CabHolder
|
||||||
import code.name.monkey.retromusic.loaders.PlaylistLoader
|
|
||||||
import code.name.monkey.retromusic.model.AbsCustomPlaylist
|
import code.name.monkey.retromusic.model.AbsCustomPlaylist
|
||||||
import code.name.monkey.retromusic.model.Playlist
|
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.mvp.presenter.PlaylistSongsPresenter
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsPresenter.PlaylistSongsPresenterImpl
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.PlaylistSongsView
|
|
||||||
import code.name.monkey.retromusic.providers.RepositoryImpl
|
|
||||||
import code.name.monkey.retromusic.util.DensityUtil
|
import code.name.monkey.retromusic.util.DensityUtil
|
||||||
import code.name.monkey.retromusic.util.PlaylistsUtil
|
import code.name.monkey.retromusic.util.PlaylistsUtil
|
||||||
import code.name.monkey.retromusic.util.RetroColorUtil
|
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||||
|
@ -32,11 +28,15 @@ import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemA
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
|
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
|
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
|
||||||
import kotlinx.android.synthetic.main.activity_playlist_detail.*
|
import kotlinx.android.synthetic.main.activity_playlist_detail.*
|
||||||
|
import org.koin.android.viewmodel.ext.android.viewModel
|
||||||
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, PlaylistSongsView {
|
class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder {
|
||||||
|
|
||||||
|
|
||||||
private lateinit var presenter: PlaylistSongsPresenter
|
private val viewModel: PlaylistDetailsViewModel by viewModel {
|
||||||
|
parametersOf(extraNotNull<Playlist>(EXTRA_PLAYLIST).value)
|
||||||
|
}
|
||||||
private lateinit var playlist: Playlist
|
private lateinit var playlist: Playlist
|
||||||
private var cab: MaterialCab? = null
|
private var cab: MaterialCab? = null
|
||||||
private lateinit var adapter: SongAdapter
|
private lateinit var adapter: SongAdapter
|
||||||
|
@ -52,13 +52,20 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
|
||||||
setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
setBottomBarVisibility(View.GONE)
|
setBottomBarVisibility(View.GONE)
|
||||||
|
|
||||||
presenter = PlaylistSongsPresenterImpl(RepositoryImpl(this))
|
|
||||||
presenter.attachView(this)
|
|
||||||
|
|
||||||
playlist = extraNotNull<Playlist>(EXTRA_PLAYLIST).value
|
playlist = extraNotNull<Playlist>(EXTRA_PLAYLIST).value
|
||||||
|
|
||||||
setUpToolBar()
|
setUpToolBar()
|
||||||
setUpRecyclerView()
|
setUpRecyclerView()
|
||||||
|
|
||||||
|
viewModel.getSongs().observe(this, Observer {
|
||||||
|
songs(it)
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.getPlaylist().observe(this, Observer {
|
||||||
|
playlist = it
|
||||||
|
supportActionBar?.title = it.name
|
||||||
|
})
|
||||||
|
addMusicServiceEventListener(viewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createContentView(): View {
|
override fun createContentView(): View {
|
||||||
|
@ -66,7 +73,6 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpRecyclerView() {
|
private fun setUpRecyclerView() {
|
||||||
|
|
||||||
recyclerView.layoutManager = LinearLayoutManager(this)
|
recyclerView.layoutManager = LinearLayoutManager(this)
|
||||||
if (playlist is AbsCustomPlaylist) {
|
if (playlist is AbsCustomPlaylist) {
|
||||||
adapter = PlaylistSongAdapter(this, ArrayList(), R.layout.item_list, this)
|
adapter = PlaylistSongAdapter(this, ArrayList(), R.layout.item_list, this)
|
||||||
|
@ -108,11 +114,6 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
presenter.loadPlaylistSongs(playlist)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setUpToolBar() {
|
private fun setUpToolBar() {
|
||||||
applyToolbar(toolbar)
|
applyToolbar(toolbar)
|
||||||
title = playlist.name
|
title = playlist.name
|
||||||
|
@ -162,28 +163,6 @@ 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) {
|
|
||||||
playlist = PlaylistLoader.getPlaylist(this, playlist.id)
|
|
||||||
setToolbarTitle(playlist.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
presenter.loadPlaylistSongs(playlist)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setToolbarTitle(title: String) {
|
|
||||||
supportActionBar?.title = title
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkForPadding() {
|
private fun checkForPadding() {
|
||||||
val height = DensityUtil.dip2px(this, 52f)
|
val height = DensityUtil.dip2px(this, 52f)
|
||||||
recyclerView.setPadding(0, 0, 0, (height))
|
recyclerView.setPadding(0, 0, 0, (height))
|
||||||
|
@ -223,16 +202,19 @@ class PlaylistDetailActivity : AbsSlidingMusicPanelActivity(), CabHolder, Playli
|
||||||
wrappedAdapter = null
|
wrappedAdapter = null
|
||||||
}
|
}
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
presenter.detachView()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showEmptyView() {
|
fun showEmptyView() {
|
||||||
empty.visibility = View.VISIBLE
|
empty.visibility = View.VISIBLE
|
||||||
emptyText.visibility = View.VISIBLE
|
emptyText.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun songs(songs: List<Song>) {
|
fun songs(songs: List<Song>) {
|
||||||
adapter.swapDataSet(songs)
|
if (songs.isNotEmpty()) {
|
||||||
|
adapter.swapDataSet(songs)
|
||||||
|
} else {
|
||||||
|
showEmptyView()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
|
@ -0,0 +1,67 @@
|
||||||
|
package code.name.monkey.retromusic.activities.playlist
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import code.name.monkey.retromusic.App
|
||||||
|
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||||
|
import code.name.monkey.retromusic.loaders.PlaylistLoader
|
||||||
|
import code.name.monkey.retromusic.model.AbsCustomPlaylist
|
||||||
|
import code.name.monkey.retromusic.model.Playlist
|
||||||
|
import code.name.monkey.retromusic.model.Song
|
||||||
|
import code.name.monkey.retromusic.providers.RepositoryImpl
|
||||||
|
import code.name.monkey.retromusic.util.PlaylistsUtil
|
||||||
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class PlaylistDetailsViewModel(
|
||||||
|
private val repository: RepositoryImpl,
|
||||||
|
private var playlist: Playlist
|
||||||
|
) : ViewModel(), MusicServiceEventListener {
|
||||||
|
private val _playListSongs = MutableLiveData<List<Song>>()
|
||||||
|
|
||||||
|
private val _playlist = MutableLiveData<Playlist>().apply {
|
||||||
|
postValue(playlist)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPlaylist(): LiveData<Playlist> = _playlist
|
||||||
|
|
||||||
|
fun getSongs(): LiveData<List<Song>> = _playListSongs
|
||||||
|
|
||||||
|
init {
|
||||||
|
loadPlaylistSongs(playlist)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadPlaylistSongs(playlist: Playlist) = viewModelScope.launch {
|
||||||
|
val songs = repository.getPlaylistSongs(playlist)
|
||||||
|
withContext(Main) { _playListSongs.postValue(songs) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMediaStoreChanged() {
|
||||||
|
if (playlist !is AbsCustomPlaylist) {
|
||||||
|
// Playlist deleted
|
||||||
|
if (!PlaylistsUtil.doesPlaylistExist(App.getContext(), playlist.id)) {
|
||||||
|
//TODO Finish the page
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Playlist renamed
|
||||||
|
val playlistName =
|
||||||
|
PlaylistsUtil.getNameForPlaylist(App.getContext(), playlist.id.toLong())
|
||||||
|
if (playlistName != playlist.name) {
|
||||||
|
playlist = PlaylistLoader.getPlaylist(App.getContext(), playlist.id)
|
||||||
|
_playlist.postValue(playlist)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadPlaylistSongs(playlist)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onServiceConnected() {}
|
||||||
|
override fun onServiceDisconnected() {}
|
||||||
|
override fun onQueueChanged() {}
|
||||||
|
override fun onPlayingMetaChanged() {}
|
||||||
|
override fun onPlayStateChanged() {}
|
||||||
|
override fun onRepeatModeChanged() {}
|
||||||
|
override fun onShuffleModeChanged() {}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package code.name.monkey.retromusic.activities
|
package code.name.monkey.retromusic.activities.search
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
|
@ -24,19 +24,17 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
import code.name.monkey.retromusic.activities.base.AbsMusicServiceActivity
|
||||||
import code.name.monkey.retromusic.adapter.SearchAdapter
|
import code.name.monkey.retromusic.adapter.SearchAdapter
|
||||||
import code.name.monkey.retromusic.mvp.presenter.SearchPresenter
|
import code.name.monkey.retromusic.extensions.extra
|
||||||
import code.name.monkey.retromusic.mvp.presenter.SearchPresenter.SearchPresenterImpl
|
|
||||||
import code.name.monkey.retromusic.mvp.presenter.SearchView
|
|
||||||
import code.name.monkey.retromusic.providers.RepositoryImpl
|
|
||||||
import code.name.monkey.retromusic.util.RetroUtil
|
import code.name.monkey.retromusic.util.RetroUtil
|
||||||
import com.google.android.material.textfield.TextInputEditText
|
import com.google.android.material.textfield.TextInputEditText
|
||||||
import kotlinx.android.synthetic.main.activity_search.*
|
import kotlinx.android.synthetic.main.activity_search.*
|
||||||
|
import org.koin.android.ext.android.inject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatcher, SearchView {
|
class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatcher {
|
||||||
|
|
||||||
private lateinit var presenter: SearchPresenter
|
private val viewModel: SearchViewModel by inject()
|
||||||
private var searchAdapter: SearchAdapter? = null
|
private var searchAdapter: SearchAdapter? = null
|
||||||
private var query: String? = null
|
private var query: String? = null
|
||||||
|
|
||||||
|
@ -49,14 +47,11 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
setTaskDescriptionColorAuto()
|
setTaskDescriptionColorAuto()
|
||||||
setLightNavigationBar(true)
|
setLightNavigationBar(true)
|
||||||
|
|
||||||
presenter = SearchPresenterImpl(RepositoryImpl(this))
|
|
||||||
presenter.attachView(this)
|
|
||||||
|
|
||||||
setupRecyclerView()
|
setupRecyclerView()
|
||||||
setUpToolBar()
|
setUpToolBar()
|
||||||
setupSearchView()
|
setupSearchView()
|
||||||
|
|
||||||
if (intent.getBooleanExtra(EXTRA_SHOW_MIC, false)) {
|
if (extra<Boolean>(EXTRA_SHOW_MIC).value == true) {
|
||||||
startMicSearch()
|
startMicSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +79,10 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
query = savedInstanceState.getString(QUERY)
|
query = savedInstanceState.getString(QUERY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.getSearchResult().observe(this, androidx.lifecycle.Observer {
|
||||||
|
showData(it)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
|
@ -114,11 +113,6 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
searchView.addTextChangedListener(this)
|
searchView.addTextChangedListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
presenter.detachView()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
outState.putString(QUERY, query)
|
outState.putString(QUERY, query)
|
||||||
|
@ -133,7 +127,7 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
TransitionManager.beginDelayedTransition(appBarLayout)
|
TransitionManager.beginDelayedTransition(appBarLayout)
|
||||||
voiceSearch.visibility = if (query.isNotEmpty()) View.GONE else View.VISIBLE
|
voiceSearch.visibility = if (query.isNotEmpty()) View.GONE else View.VISIBLE
|
||||||
clearText.visibility = if (query.isNotEmpty()) View.VISIBLE else View.GONE
|
clearText.visibility = if (query.isNotEmpty()) View.VISIBLE else View.GONE
|
||||||
presenter.search(query)
|
viewModel.search(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMediaStoreChanged() {
|
override fun onMediaStoreChanged() {
|
||||||
|
@ -158,12 +152,16 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showEmptyView() {
|
private fun showEmptyView() {
|
||||||
searchAdapter?.swapDataSet(ArrayList())
|
searchAdapter?.swapDataSet(ArrayList())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun showData(data: MutableList<Any>) {
|
private fun showData(data: MutableList<Any>) {
|
||||||
searchAdapter?.swapDataSet(data)
|
if (data.isNotEmpty()) {
|
||||||
|
searchAdapter?.swapDataSet(data)
|
||||||
|
} else {
|
||||||
|
showEmptyView()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
@ -175,7 +173,7 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
|
data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
|
||||||
query = result?.get(0)
|
query = result?.get(0)
|
||||||
searchView.setText(query, BufferType.EDITABLE)
|
searchView.setText(query, BufferType.EDITABLE)
|
||||||
presenter.search(query!!)
|
viewModel.search(query!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,7 +188,10 @@ class SearchActivity : AbsMusicServiceActivity(), OnQueryTextListener, TextWatch
|
||||||
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
|
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
|
||||||
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.speech_prompt))
|
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.speech_prompt))
|
||||||
try {
|
try {
|
||||||
startActivityForResult(intent, REQ_CODE_SPEECH_INPUT)
|
startActivityForResult(
|
||||||
|
intent,
|
||||||
|
REQ_CODE_SPEECH_INPUT
|
||||||
|
)
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: ActivityNotFoundException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Toast.makeText(this, getString(R.string.speech_not_supported), Toast.LENGTH_SHORT)
|
Toast.makeText(this, getString(R.string.speech_not_supported), Toast.LENGTH_SHORT)
|
|
@ -0,0 +1,22 @@
|
||||||
|
package code.name.monkey.retromusic.activities.search
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import code.name.monkey.retromusic.providers.RepositoryImpl
|
||||||
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class SearchViewModel(private val repository: RepositoryImpl) : ViewModel() {
|
||||||
|
private val results = MutableLiveData<MutableList<Any>>()
|
||||||
|
|
||||||
|
fun getSearchResult(): LiveData<MutableList<Any>> = results
|
||||||
|
|
||||||
|
fun search(query: String?) = viewModelScope.launch(IO) {
|
||||||
|
val result = repository.search(query)
|
||||||
|
withContext(Main) { results.postValue(result) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ package code.name.monkey.retromusic.appshortcuts
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import code.name.monkey.retromusic.activities.SearchActivity
|
import code.name.monkey.retromusic.activities.search.SearchActivity
|
||||||
import code.name.monkey.retromusic.appshortcuts.shortcuttype.LastAddedShortcutType
|
import code.name.monkey.retromusic.appshortcuts.shortcuttype.LastAddedShortcutType
|
||||||
import code.name.monkey.retromusic.appshortcuts.shortcuttype.SearchShortCutType
|
import code.name.monkey.retromusic.appshortcuts.shortcuttype.SearchShortCutType
|
||||||
import code.name.monkey.retromusic.appshortcuts.shortcuttype.ShuffleAllShortcutType
|
import code.name.monkey.retromusic.appshortcuts.shortcuttype.ShuffleAllShortcutType
|
||||||
|
|
|
@ -1,25 +1,23 @@
|
||||||
package code.name.monkey.retromusic.fragments
|
package code.name.monkey.retromusic.fragments
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import androidx.lifecycle.AndroidViewModel
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import code.name.monkey.retromusic.adapter.HomeAdapter
|
import code.name.monkey.retromusic.adapter.HomeAdapter
|
||||||
import code.name.monkey.retromusic.fragments.ReloadType.*
|
import code.name.monkey.retromusic.fragments.ReloadType.*
|
||||||
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
|
||||||
import code.name.monkey.retromusic.model.*
|
import code.name.monkey.retromusic.model.*
|
||||||
import code.name.monkey.retromusic.providers.RepositoryImpl
|
import code.name.monkey.retromusic.providers.RepositoryImpl
|
||||||
import code.name.monkey.retromusic.providers.interfaces.Repository
|
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class LibraryViewModel(application: Application) :
|
class LibraryViewModel(
|
||||||
AndroidViewModel(application), MusicServiceEventListener {
|
private val repository: RepositoryImpl
|
||||||
|
) : ViewModel(), MusicServiceEventListener {
|
||||||
|
|
||||||
private val _repository: Repository = RepositoryImpl(application.applicationContext)
|
|
||||||
private val _albums = MutableLiveData<List<Album>>()
|
private val _albums = MutableLiveData<List<Album>>()
|
||||||
private val _songs = MutableLiveData<List<Song>>()
|
private val _songs = MutableLiveData<List<Song>>()
|
||||||
private val _artists = MutableLiveData<List<Artist>>()
|
private val _artists = MutableLiveData<List<Artist>>()
|
||||||
|
@ -52,12 +50,12 @@ class LibraryViewModel(application: Application) :
|
||||||
private fun loadHomeSections() = viewModelScope.launch {
|
private fun loadHomeSections() = viewModelScope.launch {
|
||||||
val list = mutableListOf<Home>()
|
val list = mutableListOf<Home>()
|
||||||
val result = listOf(
|
val result = listOf(
|
||||||
_repository.topArtists(),
|
repository.topArtists(),
|
||||||
_repository.topAlbums(),
|
repository.topAlbums(),
|
||||||
_repository.recentArtists(),
|
repository.recentArtists(),
|
||||||
_repository.recentAlbums(),
|
repository.recentAlbums(),
|
||||||
_repository.suggestions(),
|
repository.suggestions(),
|
||||||
_repository.favoritePlaylist()
|
repository.favoritePlaylist()
|
||||||
)
|
)
|
||||||
result.forEach {
|
result.forEach {
|
||||||
if (it != null && it.arrayList.isNotEmpty()) {
|
if (it != null && it.arrayList.isNotEmpty()) {
|
||||||
|
@ -75,27 +73,27 @@ class LibraryViewModel(application: Application) :
|
||||||
|
|
||||||
private val loadSongs: Deferred<List<Song>>
|
private val loadSongs: Deferred<List<Song>>
|
||||||
get() = viewModelScope.async(IO) {
|
get() = viewModelScope.async(IO) {
|
||||||
_repository.allSongs()
|
repository.allSongs()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val loadAlbums: Deferred<List<Album>>
|
private val loadAlbums: Deferred<List<Album>>
|
||||||
get() = viewModelScope.async(IO) {
|
get() = viewModelScope.async(IO) {
|
||||||
_repository.allAlbums()
|
repository.allAlbums()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val loadArtists: Deferred<List<Artist>>
|
private val loadArtists: Deferred<List<Artist>>
|
||||||
get() = viewModelScope.async(IO) {
|
get() = viewModelScope.async(IO) {
|
||||||
_repository.allArtists()
|
repository.allArtists()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val loadPlaylists: Deferred<List<Playlist>>
|
private val loadPlaylists: Deferred<List<Playlist>>
|
||||||
get() = viewModelScope.async(IO) {
|
get() = viewModelScope.async(IO) {
|
||||||
_repository.allPlaylists()
|
repository.allPlaylists()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val loadGenres: Deferred<List<Genre>>
|
private val loadGenres: Deferred<List<Genre>>
|
||||||
get() = viewModelScope.async(IO) {
|
get() = viewModelScope.async(IO) {
|
||||||
_repository.allGenres()
|
repository.allGenres()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun forceReload(reloadType: ReloadType) = viewModelScope.launch {
|
fun forceReload(reloadType: ReloadType) = viewModelScope.launch {
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.mvp
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 09/08/17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
interface BaseView {
|
|
||||||
|
|
||||||
fun showEmptyView()
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.mvp
|
|
||||||
|
|
||||||
import androidx.annotation.CallSuper
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 16/08/17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
interface Presenter<T> {
|
|
||||||
@CallSuper
|
|
||||||
fun attachView(view: T)
|
|
||||||
|
|
||||||
@CallSuper
|
|
||||||
fun detachView()
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.mvp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 2019-09-04.
|
|
||||||
*/
|
|
||||||
public abstract class PresenterImpl<T> {
|
|
||||||
protected T view;
|
|
||||||
|
|
||||||
public void attachView(T view) {
|
|
||||||
this.view = view;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void detachView() {
|
|
||||||
view = null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.mvp.presenter
|
|
||||||
|
|
||||||
import code.name.monkey.retromusic.model.Album
|
|
||||||
import code.name.monkey.retromusic.model.Artist
|
|
||||||
import code.name.monkey.retromusic.rest.model.LastFmAlbum
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 20/08/17.
|
|
||||||
*/
|
|
||||||
interface AlbumDetailsView {
|
|
||||||
|
|
||||||
fun album(album: Album)
|
|
||||||
|
|
||||||
fun complete()
|
|
||||||
|
|
||||||
fun loadArtistImage(artist: Artist)
|
|
||||||
|
|
||||||
fun moreAlbums(albums: List<Album>)
|
|
||||||
|
|
||||||
fun aboutAlbum(lastFmAlbum: LastFmAlbum)
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.mvp.presenter
|
|
||||||
|
|
||||||
import code.name.monkey.retromusic.model.Artist
|
|
||||||
import code.name.monkey.retromusic.mvp.BaseView
|
|
||||||
import code.name.monkey.retromusic.rest.model.LastFmArtist
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 20/08/17.
|
|
||||||
*/
|
|
||||||
interface ArtistDetailsView : BaseView {
|
|
||||||
|
|
||||||
fun artist(artist: Artist)
|
|
||||||
|
|
||||||
fun artistInfo(lastFmArtist: LastFmArtist?)
|
|
||||||
|
|
||||||
fun complete()
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.mvp.presenter
|
|
||||||
|
|
||||||
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 kotlinx.coroutines.*
|
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 20/08/17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
interface GenreDetailsView : BaseView {
|
|
||||||
|
|
||||||
fun songs(songs: List<Song>)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GenreDetailsPresenter : Presenter<GenreDetailsView> {
|
|
||||||
fun loadGenreSongs(genreId: Int)
|
|
||||||
|
|
||||||
class GenreDetailsPresenterImpl constructor(
|
|
||||||
private val repository: Repository
|
|
||||||
) : PresenterImpl<GenreDetailsView>(), GenreDetailsPresenter, CoroutineScope {
|
|
||||||
|
|
||||||
private val job = Job()
|
|
||||||
|
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = Dispatchers.IO + job
|
|
||||||
|
|
||||||
override fun detachView() {
|
|
||||||
super.detachView()
|
|
||||||
job.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadGenreSongs(genreId: Int) {
|
|
||||||
launch {
|
|
||||||
val result = repository.getGenre(genreId)
|
|
||||||
withContext(Main) { view?.songs(result) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.mvp.presenter
|
|
||||||
|
|
||||||
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 kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 20/08/17.
|
|
||||||
*/
|
|
||||||
interface PlaylistSongsView : BaseView {
|
|
||||||
|
|
||||||
fun songs(songs: List<Song>)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PlaylistSongsPresenter : Presenter<PlaylistSongsView> {
|
|
||||||
fun loadPlaylistSongs(playlist: Playlist)
|
|
||||||
|
|
||||||
class PlaylistSongsPresenterImpl constructor(
|
|
||||||
private val repository: Repository
|
|
||||||
) : PresenterImpl<PlaylistSongsView>(), PlaylistSongsPresenter, CoroutineScope {
|
|
||||||
|
|
||||||
private var job: Job = Job()
|
|
||||||
|
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = IO + job
|
|
||||||
|
|
||||||
override fun loadPlaylistSongs(playlist: Playlist) {
|
|
||||||
launch {
|
|
||||||
val songs = repository.getPlaylistSongs(playlist)
|
|
||||||
withContext(Main) { view?.songs(songs) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun detachView() {
|
|
||||||
super.detachView()
|
|
||||||
job.cancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.mvp.presenter
|
|
||||||
|
|
||||||
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 kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hemanths on 20/08/17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
interface SearchView : BaseView {
|
|
||||||
|
|
||||||
fun showData(data: MutableList<Any>)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SearchPresenter : Presenter<SearchView> {
|
|
||||||
|
|
||||||
fun search(query: String?)
|
|
||||||
|
|
||||||
class SearchPresenterImpl constructor(
|
|
||||||
private val repository: Repository
|
|
||||||
) : PresenterImpl<SearchView>(), SearchPresenter, CoroutineScope {
|
|
||||||
|
|
||||||
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?) {
|
|
||||||
launch {
|
|
||||||
val result = repository.search(query)
|
|
||||||
withContext(Dispatchers.Main) { view?.showData(result) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package code.name.monkey.retromusic.providers
|
||||||
|
|
||||||
|
import org.eclipse.egit.github.core.Repository
|
||||||
|
import org.koin.dsl.bind
|
||||||
|
import org.koin.dsl.module
|
||||||
|
|
||||||
|
val provideModules = module {
|
||||||
|
single {
|
||||||
|
RepositoryImpl(get())
|
||||||
|
} bind Repository::class
|
||||||
|
}
|
|
@ -30,13 +30,13 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import code.name.monkey.retromusic.R;
|
import code.name.monkey.retromusic.R;
|
||||||
import code.name.monkey.retromusic.activities.AboutActivity;
|
import code.name.monkey.retromusic.activities.AboutActivity;
|
||||||
import code.name.monkey.retromusic.activities.DriveModeActivity;
|
import code.name.monkey.retromusic.activities.DriveModeActivity;
|
||||||
import code.name.monkey.retromusic.activities.GenreDetailsActivity;
|
import code.name.monkey.retromusic.activities.genre.GenreDetailsActivity;
|
||||||
import code.name.monkey.retromusic.activities.LicenseActivity;
|
import code.name.monkey.retromusic.activities.LicenseActivity;
|
||||||
import code.name.monkey.retromusic.activities.LyricsActivity;
|
import code.name.monkey.retromusic.activities.LyricsActivity;
|
||||||
import code.name.monkey.retromusic.activities.PlayingQueueActivity;
|
import code.name.monkey.retromusic.activities.PlayingQueueActivity;
|
||||||
import code.name.monkey.retromusic.activities.PlaylistDetailActivity;
|
import code.name.monkey.retromusic.activities.playlist.PlaylistDetailActivity;
|
||||||
import code.name.monkey.retromusic.activities.PurchaseActivity;
|
import code.name.monkey.retromusic.activities.PurchaseActivity;
|
||||||
import code.name.monkey.retromusic.activities.SearchActivity;
|
import code.name.monkey.retromusic.activities.search.SearchActivity;
|
||||||
import code.name.monkey.retromusic.activities.SettingsActivity;
|
import code.name.monkey.retromusic.activities.SettingsActivity;
|
||||||
import code.name.monkey.retromusic.activities.SupportDevelopmentActivity;
|
import code.name.monkey.retromusic.activities.SupportDevelopmentActivity;
|
||||||
import code.name.monkey.retromusic.activities.UserInfoActivity;
|
import code.name.monkey.retromusic.activities.UserInfoActivity;
|
||||||
|
|
Loading…
Reference in New Issue