feat: Minor redesign in Playlist details page
This commit is contained in:
parent
c6dd54d200
commit
b9f3e7979b
12 changed files with 233 additions and 56 deletions
|
@ -168,10 +168,10 @@ private val viewModules = module {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel { (playlist: PlaylistWithSongs) ->
|
viewModel { (playlistId: Long) ->
|
||||||
PlaylistDetailsViewModel(
|
PlaylistDetailsViewModel(
|
||||||
get(),
|
get(),
|
||||||
playlist
|
playlistId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,7 +217,7 @@ class SearchAdapter(
|
||||||
PLAYLIST -> {
|
PLAYLIST -> {
|
||||||
activity.findNavController(R.id.fragment_container).navigate(
|
activity.findNavController(R.id.fragment_container).navigate(
|
||||||
R.id.playlistDetailsFragment,
|
R.id.playlistDetailsFragment,
|
||||||
bundleOf(EXTRA_PLAYLIST to (item as PlaylistWithSongs))
|
bundleOf(EXTRA_PLAYLIST_ID to (item as PlaylistWithSongs).playlistEntity.playListId)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,8 @@ import code.name.monkey.retromusic.db.PlaylistEntity
|
||||||
import code.name.monkey.retromusic.db.toSongEntity
|
import code.name.monkey.retromusic.db.toSongEntity
|
||||||
import code.name.monkey.retromusic.db.toSongsEntity
|
import code.name.monkey.retromusic.db.toSongsEntity
|
||||||
import code.name.monkey.retromusic.dialogs.RemoveSongFromPlaylistDialog
|
import code.name.monkey.retromusic.dialogs.RemoveSongFromPlaylistDialog
|
||||||
import code.name.monkey.retromusic.extensions.accentColor
|
|
||||||
import code.name.monkey.retromusic.extensions.accentOutlineColor
|
|
||||||
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
import code.name.monkey.retromusic.fragments.LibraryViewModel
|
||||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
import com.google.android.material.button.MaterialButton
|
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter
|
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter
|
||||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange
|
import com.h6ah4i.android.widget.advrecyclerview.draggable.ItemDraggableRange
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
@ -37,11 +33,11 @@ import kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
|
|
||||||
class OrderablePlaylistSongAdapter(
|
class OrderablePlaylistSongAdapter(
|
||||||
private val playlist: PlaylistEntity,
|
private val playlistId: Long,
|
||||||
activity: FragmentActivity,
|
activity: FragmentActivity,
|
||||||
dataSet: MutableList<Song>,
|
dataSet: MutableList<Song>,
|
||||||
itemLayoutRes: Int,
|
itemLayoutRes: Int,
|
||||||
) : AbsOffsetSongAdapter(activity, dataSet, itemLayoutRes),
|
) : SongAdapter(activity, dataSet, itemLayoutRes),
|
||||||
DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> {
|
DraggableItemAdapter<OrderablePlaylistSongAdapter.ViewHolder> {
|
||||||
|
|
||||||
val libraryViewModel: LibraryViewModel by activity.viewModel()
|
val libraryViewModel: LibraryViewModel by activity.viewModel()
|
||||||
|
@ -65,45 +61,20 @@ class OrderablePlaylistSongAdapter(
|
||||||
return ViewHolder(view)
|
return ViewHolder(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
|
||||||
return if (position == 0) OFFSET_ITEM else SONG
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: SongAdapter.ViewHolder, position: Int) {
|
|
||||||
if (holder.itemViewType == OFFSET_ITEM) {
|
|
||||||
val viewHolder = holder as ViewHolder
|
|
||||||
viewHolder.playAction?.let {
|
|
||||||
it.setOnClickListener {
|
|
||||||
MusicPlayerRemote.openQueue(dataSet, 0, true)
|
|
||||||
}
|
|
||||||
it.accentOutlineColor()
|
|
||||||
}
|
|
||||||
viewHolder.shuffleAction?.let {
|
|
||||||
it.setOnClickListener {
|
|
||||||
MusicPlayerRemote.openAndShuffleQueue(dataSet, true)
|
|
||||||
}
|
|
||||||
it.accentColor()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.onBindViewHolder(holder, position - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMultipleItemAction(menuItem: MenuItem, selection: List<Song>) {
|
override fun onMultipleItemAction(menuItem: MenuItem, selection: List<Song>) {
|
||||||
when (menuItem.itemId) {
|
when (menuItem.itemId) {
|
||||||
R.id.action_remove_from_playlist -> RemoveSongFromPlaylistDialog.create(
|
R.id.action_remove_from_playlist -> RemoveSongFromPlaylistDialog.create(
|
||||||
selection.toSongsEntity(
|
selection.toSongsEntity(
|
||||||
playlist
|
playlistId
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.show(activity.supportFragmentManager, "REMOVE_FROM_PLAYLIST")
|
.show(activity.supportFragmentManager, "REMOVE_FROM_PLAYLIST")
|
||||||
|
|
||||||
else -> super.onMultipleItemAction(menuItem, selection)
|
else -> super.onMultipleItemAction(menuItem, selection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class ViewHolder(itemView: View) : AbsOffsetSongAdapter.ViewHolder(itemView) {
|
inner class ViewHolder(itemView: View) : SongAdapter.ViewHolder(itemView) {
|
||||||
val playAction: MaterialButton? = itemView.findViewById(R.id.playAction)
|
|
||||||
val shuffleAction: MaterialButton? = itemView.findViewById(R.id.shuffleAction)
|
|
||||||
|
|
||||||
override var songMenuRes: Int
|
override var songMenuRes: Int
|
||||||
get() = R.menu.menu_item_playlist_song
|
get() = R.menu.menu_item_playlist_song
|
||||||
|
@ -114,7 +85,7 @@ class OrderablePlaylistSongAdapter(
|
||||||
override fun onSongMenuItemClick(item: MenuItem): Boolean {
|
override fun onSongMenuItemClick(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_remove_from_playlist -> {
|
R.id.action_remove_from_playlist -> {
|
||||||
RemoveSongFromPlaylistDialog.create(song.toSongEntity(playlist.playListId))
|
RemoveSongFromPlaylistDialog.create(song.toSongEntity(playlistId))
|
||||||
.show(activity.supportFragmentManager, "REMOVE_FROM_PLAYLIST")
|
.show(activity.supportFragmentManager, "REMOVE_FROM_PLAYLIST")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -147,7 +118,7 @@ class OrderablePlaylistSongAdapter(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange {
|
override fun onGetItemDraggableRange(holder: ViewHolder, position: Int): ItemDraggableRange {
|
||||||
return ItemDraggableRange(1, itemCount - 1)
|
return ItemDraggableRange(0, itemCount - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCheckCanDrop(draggingPosition: Int, dropPosition: Int): Boolean {
|
override fun onCheckCanDrop(draggingPosition: Int, dropPosition: Int): Boolean {
|
||||||
|
|
|
@ -41,6 +41,10 @@ interface PlaylistDao {
|
||||||
@Query("SELECT * FROM PlaylistEntity")
|
@Query("SELECT * FROM PlaylistEntity")
|
||||||
suspend fun playlistsWithSongs(): List<PlaylistWithSongs>
|
suspend fun playlistsWithSongs(): List<PlaylistWithSongs>
|
||||||
|
|
||||||
|
@Transaction
|
||||||
|
@Query("SELECT * FROM PlaylistEntity WHERE playlist_id= :playlistId")
|
||||||
|
fun getPlaylist(playlistId: Long): LiveData<PlaylistWithSongs>
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun insertSongsToPlaylist(songEntities: List<SongEntity>)
|
suspend fun insertSongsToPlaylist(songEntities: List<SongEntity>)
|
||||||
|
|
||||||
|
|
|
@ -145,3 +145,9 @@ fun List<Song>.toSongsEntity(playlistEntity: PlaylistEntity): List<SongEntity> {
|
||||||
it.toSongEntity(playlistEntity.playListId)
|
it.toSongEntity(playlistEntity.playListId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun List<Song>.toSongsEntity(playlistId: Long): List<SongEntity> {
|
||||||
|
return map {
|
||||||
|
it.toSongEntity(playlistId)
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,15 +14,21 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter
|
import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter
|
||||||
import code.name.monkey.retromusic.databinding.FragmentPlaylistDetailBinding
|
import code.name.monkey.retromusic.databinding.FragmentPlaylistDetailNewBinding
|
||||||
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
||||||
import code.name.monkey.retromusic.db.toSongs
|
import code.name.monkey.retromusic.db.toSongs
|
||||||
|
import code.name.monkey.retromusic.extensions.accentColor
|
||||||
|
import code.name.monkey.retromusic.extensions.elevatedAccentColor
|
||||||
import code.name.monkey.retromusic.extensions.surfaceColor
|
import code.name.monkey.retromusic.extensions.surfaceColor
|
||||||
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
|
||||||
|
import code.name.monkey.retromusic.glide.RetroGlideExtension.playlistOptions
|
||||||
|
import code.name.monkey.retromusic.glide.playlistPreview.PlaylistPreview
|
||||||
|
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||||
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
|
import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper
|
||||||
import code.name.monkey.retromusic.model.Song
|
import code.name.monkey.retromusic.model.Song
|
||||||
import code.name.monkey.retromusic.util.MusicUtil
|
import code.name.monkey.retromusic.util.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.ThemedFastScroller
|
import code.name.monkey.retromusic.util.ThemedFastScroller
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import com.google.android.material.transition.MaterialArcMotion
|
import com.google.android.material.transition.MaterialArcMotion
|
||||||
import com.google.android.material.transition.MaterialContainerTransform
|
import com.google.android.material.transition.MaterialContainerTransform
|
||||||
|
@ -34,13 +40,13 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
|
|
||||||
class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail) {
|
class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail_new) {
|
||||||
private val arguments by navArgs<PlaylistDetailsFragmentArgs>()
|
private val arguments by navArgs<PlaylistDetailsFragmentArgs>()
|
||||||
private val viewModel by viewModel<PlaylistDetailsViewModel> {
|
private val viewModel by viewModel<PlaylistDetailsViewModel> {
|
||||||
parametersOf(arguments.extraPlaylist)
|
parametersOf(arguments.extraPlaylistId)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var _binding: FragmentPlaylistDetailBinding? = null
|
private var _binding: FragmentPlaylistDetailNewBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private lateinit var playlist: PlaylistWithSongs
|
private lateinit var playlist: PlaylistWithSongs
|
||||||
|
@ -58,16 +64,26 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
_binding = FragmentPlaylistDetailBinding.bind(view)
|
_binding = FragmentPlaylistDetailNewBinding.bind(view)
|
||||||
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).addTarget(view)
|
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).addTarget(view)
|
||||||
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||||
mainActivity.setSupportActionBar(binding.toolbar)
|
mainActivity.setSupportActionBar(binding.toolbar)
|
||||||
binding.container.transitionName = "playlist"
|
binding.toolbar.title = null
|
||||||
playlist = arguments.extraPlaylist
|
// binding.container.transitionName = playlist.playlistEntity.playlistName
|
||||||
binding.toolbar.title = playlist.playlistEntity.playlistName
|
|
||||||
binding.toolbar.subtitle =
|
|
||||||
MusicUtil.getPlaylistInfoString(requireContext(), playlist.songs.toSongs())
|
|
||||||
setUpRecyclerView()
|
setUpRecyclerView()
|
||||||
|
setupButtons()
|
||||||
|
viewModel.getPlaylist().observe(viewLifecycleOwner) { playlistWithSongs ->
|
||||||
|
playlist = playlistWithSongs
|
||||||
|
Glide.with(this)
|
||||||
|
.load(PlaylistPreview(playlist))
|
||||||
|
.playlistOptions()
|
||||||
|
.into(binding.image)
|
||||||
|
binding.title.text = playlist.playlistEntity.playlistName
|
||||||
|
binding.subtitle.text =
|
||||||
|
MusicUtil.getPlaylistInfoString(requireContext(), playlist.songs.toSongs())
|
||||||
|
binding.collapsingAppBarLayout.title = playlist.playlistEntity.playlistName
|
||||||
|
}
|
||||||
viewModel.getSongs().observe(viewLifecycleOwner) {
|
viewModel.getSongs().observe(viewLifecycleOwner) {
|
||||||
songs(it.toSongs())
|
songs(it.toSongs())
|
||||||
}
|
}
|
||||||
|
@ -82,9 +98,24 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
||||||
MaterialShapeDrawable.createWithElevationOverlay(requireContext())
|
MaterialShapeDrawable.createWithElevationOverlay(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupButtons() {
|
||||||
|
binding.playButton.apply {
|
||||||
|
setOnClickListener {
|
||||||
|
MusicPlayerRemote.openQueue(playlistSongAdapter.dataSet, 0, true)
|
||||||
|
}
|
||||||
|
accentColor()
|
||||||
|
}
|
||||||
|
binding.shuffleButton.apply {
|
||||||
|
setOnClickListener {
|
||||||
|
MusicPlayerRemote.openAndShuffleQueue(playlistSongAdapter.dataSet, true)
|
||||||
|
}
|
||||||
|
elevatedAccentColor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setUpRecyclerView() {
|
private fun setUpRecyclerView() {
|
||||||
playlistSongAdapter = OrderablePlaylistSongAdapter(
|
playlistSongAdapter = OrderablePlaylistSongAdapter(
|
||||||
playlist.playlistEntity,
|
arguments.extraPlaylistId,
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
ArrayList(),
|
ArrayList(),
|
||||||
R.layout.item_queue
|
R.layout.item_queue
|
||||||
|
|
|
@ -18,15 +18,18 @@ import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
||||||
import code.name.monkey.retromusic.db.SongEntity
|
import code.name.monkey.retromusic.db.SongEntity
|
||||||
|
import code.name.monkey.retromusic.model.Playlist
|
||||||
import code.name.monkey.retromusic.repository.RealRepository
|
import code.name.monkey.retromusic.repository.RealRepository
|
||||||
|
|
||||||
class PlaylistDetailsViewModel(
|
class PlaylistDetailsViewModel(
|
||||||
private val realRepository: RealRepository,
|
private val realRepository: RealRepository,
|
||||||
private var playlist: PlaylistWithSongs
|
private var playlistId: Long
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
fun getSongs(): LiveData<List<SongEntity>> =
|
fun getSongs(): LiveData<List<SongEntity>> =
|
||||||
realRepository.playlistSongs(playlist.playlistEntity.playListId)
|
realRepository.playlistSongs(playlistId)
|
||||||
|
|
||||||
fun playlistExists(): LiveData<Boolean> =
|
fun playlistExists(): LiveData<Boolean> =
|
||||||
realRepository.checkPlaylistExists(playlist.playlistEntity.playListId)
|
realRepository.checkPlaylistExists(playlistId)
|
||||||
|
|
||||||
|
fun getPlaylist(): LiveData<PlaylistWithSongs> = realRepository.getPlaylist(playlistId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import androidx.core.view.MenuCompat
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import code.name.monkey.retromusic.EXTRA_PLAYLIST
|
import code.name.monkey.retromusic.EXTRA_PLAYLIST
|
||||||
|
import code.name.monkey.retromusic.EXTRA_PLAYLIST_ID
|
||||||
import code.name.monkey.retromusic.R
|
import code.name.monkey.retromusic.R
|
||||||
import code.name.monkey.retromusic.adapter.playlist.PlaylistAdapter
|
import code.name.monkey.retromusic.adapter.playlist.PlaylistAdapter
|
||||||
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
import code.name.monkey.retromusic.db.PlaylistWithSongs
|
||||||
|
@ -244,7 +245,7 @@ class PlaylistsFragment :
|
||||||
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
R.id.playlistDetailsFragment,
|
R.id.playlistDetailsFragment,
|
||||||
bundleOf(EXTRA_PLAYLIST to playlistWithSongs)
|
bundleOf(EXTRA_PLAYLIST_ID to playlistWithSongs.playlistEntity.playListId)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,7 @@ interface Repository {
|
||||||
suspend fun isSongFavorite(songId: Long): Boolean
|
suspend fun isSongFavorite(songId: Long): Boolean
|
||||||
fun getSongByGenre(genreId: Long): Song
|
fun getSongByGenre(genreId: Long): Song
|
||||||
fun checkPlaylistExists(playListId: Long): LiveData<Boolean>
|
fun checkPlaylistExists(playListId: Long): LiveData<Boolean>
|
||||||
|
fun getPlaylist(playlistId: Long): LiveData<PlaylistWithSongs>
|
||||||
}
|
}
|
||||||
|
|
||||||
class RealRepository(
|
class RealRepository(
|
||||||
|
@ -223,6 +224,8 @@ class RealRepository(
|
||||||
override suspend fun fetchPlaylistWithSongs(): List<PlaylistWithSongs> =
|
override suspend fun fetchPlaylistWithSongs(): List<PlaylistWithSongs> =
|
||||||
roomRepository.playlistWithSongs()
|
roomRepository.playlistWithSongs()
|
||||||
|
|
||||||
|
override fun getPlaylist(playlistId: Long): LiveData<PlaylistWithSongs> = roomRepository.getPlaylist(playlistId)
|
||||||
|
|
||||||
override suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List<Song> =
|
override suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List<Song> =
|
||||||
playlistWithSongs.songs.map {
|
playlistWithSongs.songs.map {
|
||||||
it.toSong()
|
it.toSong()
|
||||||
|
|
|
@ -44,6 +44,7 @@ interface RoomRepository {
|
||||||
suspend fun deleteSongs(songs: List<Song>)
|
suspend fun deleteSongs(songs: List<Song>)
|
||||||
suspend fun isSongFavorite(context: Context, songId: Long): Boolean
|
suspend fun isSongFavorite(context: Context, songId: Long): Boolean
|
||||||
fun checkPlaylistExists(playListId: Long): LiveData<Boolean>
|
fun checkPlaylistExists(playListId: Long): LiveData<Boolean>
|
||||||
|
fun getPlaylist(playlistId: Long): LiveData<PlaylistWithSongs>
|
||||||
}
|
}
|
||||||
|
|
||||||
class RealRoomRepository(
|
class RealRoomRepository(
|
||||||
|
@ -81,6 +82,9 @@ class RealRoomRepository(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
override fun getPlaylist(playlistId: Long): LiveData<PlaylistWithSongs> = playlistDao.getPlaylist(playlistId)
|
||||||
|
|
||||||
@WorkerThread
|
@WorkerThread
|
||||||
override suspend fun insertSongs(songs: List<SongEntity>) {
|
override suspend fun insertSongs(songs: List<SongEntity>) {
|
||||||
|
|
||||||
|
|
154
app/src/main/res/layout/fragment_playlist_detail_new.xml
Normal file
154
app/src/main/res/layout/fragment_playlist_detail_new.xml
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:transitionGroup="true">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
|
android:id="@+id/appBarLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
app:liftOnScroll="true">
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||||
|
android:id="@+id/collapsingAppBarLayout"
|
||||||
|
style="?attr/collapsingToolbarLayoutLargeStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:expandedTitleTextColor="@color/transparent"
|
||||||
|
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="?actionBarSize"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:paddingHorizontal="16dp">
|
||||||
|
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:id="@+id/image"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/title"
|
||||||
|
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||||
|
app:layout_constraintHorizontal_weight="0.4"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:shapeAppearanceOverlay="?shapeAppearanceCornerExtraLarge"
|
||||||
|
tools:src="@tools:sample/avatars[0]" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:textAppearance="?textAppearanceDisplaySmall"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_weight="0.6"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/image"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/image"
|
||||||
|
tools:text="Playlist" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/subtitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/title"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/title"
|
||||||
|
tools:text="Playlist" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/play_button"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:padding="16dp"
|
||||||
|
app:icon="@drawable/ic_play_arrow"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/shuffle_button"
|
||||||
|
app:layout_constraintStart_toStartOf="@+id/subtitle"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/subtitle" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/shuffle_button"
|
||||||
|
style="@style/Widget.Material3.Button.IconButton.Filled.Tonal"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:backgroundTint="?colorTertiaryContainer"
|
||||||
|
android:padding="16dp"
|
||||||
|
app:icon="@drawable/ic_shuffle"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/play_button"
|
||||||
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/play_button" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?actionBarSize"
|
||||||
|
app:layout_collapseMode="pin"
|
||||||
|
app:navigationIcon="@drawable/ic_arrow_back"
|
||||||
|
app:titleTextAppearance="@style/ToolbarTextAppearanceNormal" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<code.name.monkey.retromusic.views.insets.InsetsRecyclerView
|
||||||
|
android:id="@+id/recyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:layoutAnimation="@anim/layout_anim_fade"
|
||||||
|
android:overScrollMode="@integer/overScrollMode"
|
||||||
|
android:paddingBottom="@dimen/mini_player_height"
|
||||||
|
android:scrollbars="none"
|
||||||
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
|
||||||
|
tools:listitem="@layout/item_song" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@android:id/empty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/emptyEmoji"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:text="@string/empty_text_emoji"
|
||||||
|
android:textAppearance="@style/TextViewHeadline3" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/emptyText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:text="@string/no_songs"
|
||||||
|
android:textAppearance="@style/TextViewHeadline5"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
|
android:id="@+id/progressIndicator"
|
||||||
|
android:layout_width="100dp"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -20,8 +20,8 @@
|
||||||
android:label="PlaylistDetailsFragment"
|
android:label="PlaylistDetailsFragment"
|
||||||
tools:layout="@layout/fragment_playlist_detail">
|
tools:layout="@layout/fragment_playlist_detail">
|
||||||
<argument
|
<argument
|
||||||
android:name="extra_playlist"
|
android:name="extra_playlist_id"
|
||||||
app:argType="code.name.monkey.retromusic.db.PlaylistWithSongs" />
|
app:argType="long" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue