diff --git a/app/src/main/java/code/name/monkey/retromusic/MainModule.kt b/app/src/main/java/code/name/monkey/retromusic/MainModule.kt index dbb5bcc78..548fb576b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/MainModule.kt +++ b/app/src/main/java/code/name/monkey/retromusic/MainModule.kt @@ -168,10 +168,10 @@ private val viewModules = module { ) } - viewModel { (playlist: PlaylistWithSongs) -> + viewModel { (playlistId: Long) -> PlaylistDetailsViewModel( get(), - playlist + playlistId ) } diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/SearchAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/SearchAdapter.kt index f1b1123a4..22a60bd95 100644 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/SearchAdapter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/SearchAdapter.kt @@ -217,7 +217,7 @@ class SearchAdapter( PLAYLIST -> { activity.findNavController(R.id.fragment_container).navigate( R.id.playlistDetailsFragment, - bundleOf(EXTRA_PLAYLIST to (item as PlaylistWithSongs)) + bundleOf(EXTRA_PLAYLIST_ID to (item as PlaylistWithSongs).playlistEntity.playListId) ) } diff --git a/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt b/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt index 50b2f8129..88a0b7a8d 100644 --- a/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt +++ b/app/src/main/java/code/name/monkey/retromusic/adapter/song/OrderablePlaylistSongAdapter.kt @@ -24,12 +24,8 @@ import code.name.monkey.retromusic.db.PlaylistEntity import code.name.monkey.retromusic.db.toSongEntity import code.name.monkey.retromusic.db.toSongsEntity 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.helper.MusicPlayerRemote 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.ItemDraggableRange import kotlinx.coroutines.Dispatchers @@ -37,11 +33,11 @@ import kotlinx.coroutines.launch import org.koin.androidx.viewmodel.ext.android.viewModel class OrderablePlaylistSongAdapter( - private val playlist: PlaylistEntity, + private val playlistId: Long, activity: FragmentActivity, dataSet: MutableList, itemLayoutRes: Int, -) : AbsOffsetSongAdapter(activity, dataSet, itemLayoutRes), +) : SongAdapter(activity, dataSet, itemLayoutRes), DraggableItemAdapter { val libraryViewModel: LibraryViewModel by activity.viewModel() @@ -65,45 +61,20 @@ class OrderablePlaylistSongAdapter( 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) { when (menuItem.itemId) { R.id.action_remove_from_playlist -> RemoveSongFromPlaylistDialog.create( selection.toSongsEntity( - playlist + playlistId ) ) .show(activity.supportFragmentManager, "REMOVE_FROM_PLAYLIST") + else -> super.onMultipleItemAction(menuItem, selection) } } - inner class ViewHolder(itemView: View) : AbsOffsetSongAdapter.ViewHolder(itemView) { - val playAction: MaterialButton? = itemView.findViewById(R.id.playAction) - val shuffleAction: MaterialButton? = itemView.findViewById(R.id.shuffleAction) + inner class ViewHolder(itemView: View) : SongAdapter.ViewHolder(itemView) { override var songMenuRes: Int get() = R.menu.menu_item_playlist_song @@ -114,7 +85,7 @@ class OrderablePlaylistSongAdapter( override fun onSongMenuItemClick(item: MenuItem): Boolean { when (item.itemId) { R.id.action_remove_from_playlist -> { - RemoveSongFromPlaylistDialog.create(song.toSongEntity(playlist.playListId)) + RemoveSongFromPlaylistDialog.create(song.toSongEntity(playlistId)) .show(activity.supportFragmentManager, "REMOVE_FROM_PLAYLIST") return true } @@ -147,7 +118,7 @@ class OrderablePlaylistSongAdapter( } 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 { diff --git a/app/src/main/java/code/name/monkey/retromusic/db/PlaylistDao.kt b/app/src/main/java/code/name/monkey/retromusic/db/PlaylistDao.kt index 5e3564346..dea1e6b7d 100644 --- a/app/src/main/java/code/name/monkey/retromusic/db/PlaylistDao.kt +++ b/app/src/main/java/code/name/monkey/retromusic/db/PlaylistDao.kt @@ -41,6 +41,10 @@ interface PlaylistDao { @Query("SELECT * FROM PlaylistEntity") suspend fun playlistsWithSongs(): List + @Transaction + @Query("SELECT * FROM PlaylistEntity WHERE playlist_id= :playlistId") + fun getPlaylist(playlistId: Long): LiveData + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertSongsToPlaylist(songEntities: List) diff --git a/app/src/main/java/code/name/monkey/retromusic/db/SongExtension.kt b/app/src/main/java/code/name/monkey/retromusic/db/SongExtension.kt index 4a3705de0..d6fe11b05 100644 --- a/app/src/main/java/code/name/monkey/retromusic/db/SongExtension.kt +++ b/app/src/main/java/code/name/monkey/retromusic/db/SongExtension.kt @@ -145,3 +145,9 @@ fun List.toSongsEntity(playlistEntity: PlaylistEntity): List { it.toSongEntity(playlistEntity.playListId) } } + +fun List.toSongsEntity(playlistId: Long): List { + return map { + it.toSongEntity(playlistId) + } +} \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsFragment.kt index 9c12a2fb6..d7dbbef88 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsFragment.kt @@ -14,15 +14,21 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import code.name.monkey.retromusic.R 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.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.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.model.Song import code.name.monkey.retromusic.util.MusicUtil import code.name.monkey.retromusic.util.ThemedFastScroller +import com.bumptech.glide.Glide import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.transition.MaterialArcMotion 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 -class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail) { +class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail_new) { private val arguments by navArgs() private val viewModel by viewModel { - parametersOf(arguments.extraPlaylist) + parametersOf(arguments.extraPlaylistId) } - private var _binding: FragmentPlaylistDetailBinding? = null + private var _binding: FragmentPlaylistDetailNewBinding? = null private val binding get() = _binding!! private lateinit var playlist: PlaylistWithSongs @@ -58,16 +64,26 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - _binding = FragmentPlaylistDetailBinding.bind(view) + _binding = FragmentPlaylistDetailNewBinding.bind(view) enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true).addTarget(view) returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false) mainActivity.setSupportActionBar(binding.toolbar) - binding.container.transitionName = "playlist" - playlist = arguments.extraPlaylist - binding.toolbar.title = playlist.playlistEntity.playlistName - binding.toolbar.subtitle = - MusicUtil.getPlaylistInfoString(requireContext(), playlist.songs.toSongs()) + binding.toolbar.title = null +// binding.container.transitionName = playlist.playlistEntity.playlistName + 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) { songs(it.toSongs()) } @@ -82,9 +98,24 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli 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() { playlistSongAdapter = OrderablePlaylistSongAdapter( - playlist.playlistEntity, + arguments.extraPlaylistId, requireActivity(), ArrayList(), R.layout.item_queue diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsViewModel.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsViewModel.kt index 0d15a279d..23599d384 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsViewModel.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistDetailsViewModel.kt @@ -18,15 +18,18 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModel import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.db.SongEntity +import code.name.monkey.retromusic.model.Playlist import code.name.monkey.retromusic.repository.RealRepository class PlaylistDetailsViewModel( private val realRepository: RealRepository, - private var playlist: PlaylistWithSongs + private var playlistId: Long ) : ViewModel() { fun getSongs(): LiveData> = - realRepository.playlistSongs(playlist.playlistEntity.playListId) + realRepository.playlistSongs(playlistId) fun playlistExists(): LiveData = - realRepository.checkPlaylistExists(playlist.playlistEntity.playListId) + realRepository.checkPlaylistExists(playlistId) + + fun getPlaylist(): LiveData = realRepository.getPlaylist(playlistId) } diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistsFragment.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistsFragment.kt index 93a304360..ea62902fb 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistsFragment.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/playlists/PlaylistsFragment.kt @@ -21,6 +21,7 @@ import androidx.core.view.MenuCompat import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.GridLayoutManager 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.adapter.playlist.PlaylistAdapter import code.name.monkey.retromusic.db.PlaylistWithSongs @@ -244,7 +245,7 @@ class PlaylistsFragment : reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false) findNavController().navigate( R.id.playlistDetailsFragment, - bundleOf(EXTRA_PLAYLIST to playlistWithSongs) + bundleOf(EXTRA_PLAYLIST_ID to playlistWithSongs.playlistEntity.playListId) ) } } diff --git a/app/src/main/java/code/name/monkey/retromusic/repository/Repository.kt b/app/src/main/java/code/name/monkey/retromusic/repository/Repository.kt index a9cd101ec..76f1fa53c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/repository/Repository.kt +++ b/app/src/main/java/code/name/monkey/retromusic/repository/Repository.kt @@ -99,6 +99,7 @@ interface Repository { suspend fun isSongFavorite(songId: Long): Boolean fun getSongByGenre(genreId: Long): Song fun checkPlaylistExists(playListId: Long): LiveData + fun getPlaylist(playlistId: Long): LiveData } class RealRepository( @@ -223,6 +224,8 @@ class RealRepository( override suspend fun fetchPlaylistWithSongs(): List = roomRepository.playlistWithSongs() + override fun getPlaylist(playlistId: Long): LiveData = roomRepository.getPlaylist(playlistId) + override suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List = playlistWithSongs.songs.map { it.toSong() diff --git a/app/src/main/java/code/name/monkey/retromusic/repository/RoomRepository.kt b/app/src/main/java/code/name/monkey/retromusic/repository/RoomRepository.kt index 876b876a8..a5231ccae 100644 --- a/app/src/main/java/code/name/monkey/retromusic/repository/RoomRepository.kt +++ b/app/src/main/java/code/name/monkey/retromusic/repository/RoomRepository.kt @@ -44,6 +44,7 @@ interface RoomRepository { suspend fun deleteSongs(songs: List) suspend fun isSongFavorite(context: Context, songId: Long): Boolean fun checkPlaylistExists(playListId: Long): LiveData + fun getPlaylist(playlistId: Long): LiveData } class RealRoomRepository( @@ -81,6 +82,9 @@ class RealRoomRepository( } } + @WorkerThread + override fun getPlaylist(playlistId: Long): LiveData = playlistDao.getPlaylist(playlistId) + @WorkerThread override suspend fun insertSongs(songs: List) { diff --git a/app/src/main/res/layout/fragment_playlist_detail_new.xml b/app/src/main/res/layout/fragment_playlist_detail_new.xml new file mode 100644 index 000000000..1d2003ee4 --- /dev/null +++ b/app/src/main/res/layout/fragment_playlist_detail_new.xml @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/navigation/main_graph.xml b/app/src/main/res/navigation/main_graph.xml index 63abf5367..d82f88fec 100644 --- a/app/src/main/res/navigation/main_graph.xml +++ b/app/src/main/res/navigation/main_graph.xml @@ -20,8 +20,8 @@ android:label="PlaylistDetailsFragment" tools:layout="@layout/fragment_playlist_detail"> + android:name="extra_playlist_id" + app:argType="long" />