Playlist refresh
Bottom navigation shows when coming from notification
Removed animation for lyrics page
Added playlist reorder
Added refresh for album & artist details when update
Fix when scan to update library
Added sort for playlist
Fix album art not showing in lockscreen
This commit is contained in:
Hemanth S 2020-10-09 23:14:02 +05:30
parent e5f6e83dd4
commit 33f4f31066
55 changed files with 2532 additions and 2199 deletions

View file

@ -222,8 +222,11 @@ class LibraryViewModel(
repository.renameRoomPlaylist(playListId, name)
}
fun deleteSongsInPlaylist(songs: List<SongEntity>) = viewModelScope.launch(IO) {
repository.deleteSongsInPlaylist(songs)
fun deleteSongsInPlaylist(songs: List<SongEntity>) {
viewModelScope.launch(IO) {
repository.deleteSongsInPlaylist(songs)
forceReload(Playlists)
}
}
fun deleteSongsFromPlaylist(playlists: List<PlaylistEntity>) = viewModelScope.launch(IO) {

View file

@ -15,8 +15,10 @@
package code.name.monkey.retromusic.fragments.albums
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.liveData
import androidx.lifecycle.viewModelScope
import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
@ -24,16 +26,26 @@ import code.name.monkey.retromusic.network.Result
import code.name.monkey.retromusic.network.model.LastFmAlbum
import code.name.monkey.retromusic.repository.RealRepository
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
class AlbumDetailsViewModel(
private val repository: RealRepository,
private val albumId: Long
) : ViewModel(), IMusicServiceEventListener {
private val albumDetails = MutableLiveData<Album>()
fun getAlbum(): LiveData<Album> = liveData(IO) {
emit(repository.albumByIdAsync(albumId))
init {
fetchAlbum()
}
private fun fetchAlbum() {
viewModelScope.launch(IO) {
albumDetails.postValue(repository.albumByIdAsync(albumId))
}
}
fun getAlbum(): LiveData<Album> = albumDetails
fun getArtist(artistId: Long): LiveData<Artist> = liveData(IO) {
val artist = repository.artistById(artistId)
emit(artist)
@ -51,6 +63,7 @@ class AlbumDetailsViewModel(
}
override fun onMediaStoreChanged() {
fetchAlbum()
}
override fun onServiceConnected() {}

View file

@ -94,16 +94,14 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true)
libraryViewModel.setPanelState(NowPlayingPanelState.COLLAPSED_WITHOUT)
mainActivity.setSupportActionBar(toolbar)
libraryViewModel.setPanelState(NowPlayingPanelState.COLLAPSED_WITHOUT)
toolbar.title = null
setupRecyclerView()
ViewCompat.setTransitionName(container, "artist")
postponeEnterTransition()
detailsViewModel.getArtist().observe(viewLifecycleOwner, Observer {
startPostponedEnterTransition()

View file

@ -15,25 +15,36 @@
package code.name.monkey.retromusic.fragments.artists
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.liveData
import androidx.lifecycle.viewModelScope
import code.name.monkey.retromusic.interfaces.IMusicServiceEventListener
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.network.Result
import code.name.monkey.retromusic.network.model.LastFmArtist
import code.name.monkey.retromusic.repository.RealRepository
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
class ArtistDetailsViewModel(
private val realRepository: RealRepository,
private val artistId: Long
) : ViewModel(), IMusicServiceEventListener {
private val artistDetails = MutableLiveData<Artist>()
fun getArtist(): LiveData<Artist> = liveData(IO) {
val artist = realRepository.artistById(artistId)
emit(artist)
init {
fetchArtist()
}
private fun fetchArtist() {
viewModelScope.launch(IO) {
artistDetails.postValue(realRepository.artistById(artistId))
}
}
fun getArtist(): LiveData<Artist> = artistDetails
fun getArtistInfo(
name: String,
lang: String?,
@ -45,7 +56,7 @@ class ArtistDetailsViewModel(
}
override fun onMediaStoreChanged() {
getArtist()
fetchArtist()
}
override fun onServiceConnected() {}

View file

@ -73,6 +73,7 @@ abstract class AbsRecyclerViewCustomGridSizeFragment<A : RecyclerView.Adapter<*>
fun setAndSaveSortOrder(sortOrder: String) {
this.sortOrder = sortOrder
println(sortOrder)
saveSortOrder(sortOrder)
setSortOrder(sortOrder)
}

View file

@ -61,6 +61,7 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
println("AbsRecyclerViewFragment")
libraryViewModel.setPanelState(NowPlayingPanelState.COLLAPSED_WITH)
mainActivity.setSupportActionBar(toolbar)
mainActivity.supportActionBar?.title = null

View file

@ -52,6 +52,7 @@ class HomeFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
println("AbsMainActivityFragment")
libraryViewModel.setPanelState(NowPlayingPanelState.COLLAPSED_WITH)
mainActivity.setSupportActionBar(toolbar)
mainActivity.supportActionBar?.title = null

View file

@ -5,10 +5,12 @@ import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.song.PlaylistSongAdapter
import code.name.monkey.retromusic.db.PlaylistWithSongs
@ -18,6 +20,7 @@ import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.state.NowPlayingPanelState
import com.google.android.material.transition.MaterialContainerTransform
import kotlinx.android.synthetic.main.fragment_playlist_detail.*
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
@ -31,18 +34,29 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
private lateinit var playlist: PlaylistWithSongs
private lateinit var playlistSongAdapter: PlaylistSongAdapter
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
private fun setUpTransitions() {
val transform = MaterialContainerTransform()
transform.setAllContainerColors(ATHUtil.resolveColor(requireContext(), R.attr.colorSurface))
sharedElementEnterTransition = transform
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setUpTransitions()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
libraryViewModel.setPanelState(NowPlayingPanelState.COLLAPSED_WITHOUT)
mainActivity.addMusicServiceEventListener(viewModel)
mainActivity.setSupportActionBar(toolbar)
ViewCompat.setTransitionName(container, "playlist")
playlist = arguments.extraPlaylist
toolbar.title = playlist.playlistEntity.playlistName
setUpRecyclerView()
viewModel.getSongs().observe(viewLifecycleOwner, {
songs(it.toSongs())
})

View file

@ -33,26 +33,7 @@ class PlaylistDetailsViewModel(
fun getSongs(): LiveData<List<SongEntity>> =
realRepository.playlistSongs(playlist.playlistEntity.playListId)
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) {
viewModelScope.launch {
playlist = realRepository.playlist(playlist.id)
_playlist.postValue(playlist)
}
}
}
loadPlaylistSongs(playlist)*/
}
override fun onMediaStoreChanged() {}
override fun onServiceConnected() {}
override fun onServiceDisconnected() {}
override fun onQueueChanged() {}

View file

@ -18,19 +18,31 @@ import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.SubMenu
import android.view.View
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.core.os.bundleOf
import androidx.core.view.MenuCompat
import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
import code.name.monkey.retromusic.EXTRA_PLAYLIST
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.playlist.PlaylistAdapter
import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewFragment
import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.fragments.ReloadType
import code.name.monkey.retromusic.fragments.base.AbsRecyclerViewCustomGridSizeFragment
import code.name.monkey.retromusic.helper.SortOrder.PlaylistSortOrder
import code.name.monkey.retromusic.interfaces.IPlaylistClickListener
import code.name.monkey.retromusic.util.PreferenceUtil
import kotlinx.android.synthetic.main.fragment_library.*
class PlaylistsFragment : AbsRecyclerViewFragment<PlaylistAdapter, LinearLayoutManager>() {
class PlaylistsFragment :
AbsRecyclerViewCustomGridSizeFragment<PlaylistAdapter, GridLayoutManager>(),
IPlaylistClickListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
libraryViewModel.getPlaylists().observe(viewLifecycleOwner, Observer {
libraryViewModel.getPlaylists().observe(viewLifecycleOwner, {
if (it.isNotEmpty())
adapter?.swapDataSet(it)
else
@ -41,8 +53,8 @@ class PlaylistsFragment : AbsRecyclerViewFragment<PlaylistAdapter, LinearLayoutM
override val emptyMessage: Int
get() = R.string.no_playlists
override fun createLayoutManager(): LinearLayoutManager {
return LinearLayoutManager(requireContext())
override fun createLayoutManager(): GridLayoutManager {
return GridLayoutManager(requireContext(), getGridSize())
}
override fun createAdapter(): PlaylistAdapter {
@ -50,7 +62,8 @@ class PlaylistsFragment : AbsRecyclerViewFragment<PlaylistAdapter, LinearLayoutM
requireActivity(),
ArrayList(),
R.layout.item_list,
null
null,
this
)
}
@ -63,9 +76,118 @@ class PlaylistsFragment : AbsRecyclerViewFragment<PlaylistAdapter, LinearLayoutM
super.onCreateOptionsMenu(menu, inflater)
menu.removeItem(R.id.action_grid_size)
menu.removeItem(R.id.action_layout_type)
menu.removeItem(R.id.action_sort_order)
menu.add(0, R.id.action_add_to_playlist, 0, R.string.new_playlist_title)
menu.add(0, R.id.action_import_playlist, 0, R.string.import_playlist)
menu.findItem(R.id.action_settings).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER)
setUpSortOrderMenu(menu.findItem(R.id.action_sort_order).subMenu)
MenuCompat.setGroupDividerEnabled(menu, true);
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (handleSortOrderMenuItem(item)) {
return true
}
return super.onOptionsItemSelected(item)
}
private fun setUpSortOrderMenu(subMenu: SubMenu) {
val order: String? = getSortOrder()
subMenu.clear()
createId(
subMenu,
R.id.action_song_sort_order_asc,
R.string.sort_order_a_z,
order == PlaylistSortOrder.PLAYLIST_A_Z
)
createId(
subMenu,
R.id.action_song_sort_order_desc,
R.string.sort_order_z_a,
order == PlaylistSortOrder.PLAYLIST_Z_A
)
createId(
subMenu,
R.id.action_playlist_sort_order,
R.string.sort_order_num_songs,
order == PlaylistSortOrder.PLAYLIST_SONG_COUNT
)
createId(
subMenu,
R.id.action_playlist_sort_order_desc,
R.string.sort_order_num_songs_desc,
order == PlaylistSortOrder.PLAYLIST_SONG_COUNT_DESC
)
subMenu.setGroupCheckable(0, true, true)
}
private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
val sortOrder: String = when (item.itemId) {
R.id.action_song_sort_order_asc -> PlaylistSortOrder.PLAYLIST_A_Z
R.id.action_song_sort_order_desc -> PlaylistSortOrder.PLAYLIST_Z_A
R.id.action_playlist_sort_order -> PlaylistSortOrder.PLAYLIST_SONG_COUNT
R.id.action_playlist_sort_order_desc -> PlaylistSortOrder.PLAYLIST_SONG_COUNT_DESC
else -> PreferenceUtil.playlistSortOrder
}
if (sortOrder != PreferenceUtil.playlistSortOrder) {
item.isChecked = true
setAndSaveSortOrder(sortOrder)
return true
}
return false
}
private fun createId(menu: SubMenu, id: Int, title: Int, checked: Boolean) {
menu.add(0, id, 0, title).isChecked = checked
}
override fun setGridSize(gridSize: Int) {
TODO("Not yet implemented")
}
override fun setSortOrder(sortOrder: String) {
libraryViewModel.forceReload(ReloadType.Playlists)
}
override fun loadSortOrder(): String {
return PreferenceUtil.playlistSortOrder
}
override fun saveSortOrder(sortOrder: String) {
PreferenceUtil.playlistSortOrder = sortOrder
}
override fun loadGridSize(): Int {
return 1
}
override fun saveGridSize(gridColumns: Int) {
//Add grid save
}
override fun loadGridSizeLand(): Int {
return 2
}
override fun saveGridSizeLand(gridColumns: Int) {
//Add land grid save
}
override fun loadLayoutRes(): Int {
return R.layout.item_list
}
override fun saveLayoutRes(layoutRes: Int) {
//Save layout
}
override fun onPlaylistClick(playlistWithSongs: PlaylistWithSongs, view: View) {
findNavController().navigate(
R.id.playlistDetailsFragment,
bundleOf(EXTRA_PLAYLIST to playlistWithSongs),
null,
FragmentNavigatorExtras(view to "playlist")
)
}
}