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 675f5abd..e1f77f0e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/MainModule.kt +++ b/app/src/main/java/code/name/monkey/retromusic/MainModule.kt @@ -1,6 +1,7 @@ package code.name.monkey.retromusic import code.name.monkey.retromusic.db.PlaylistDatabase +import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.db.RealRoomPlaylistRepository import code.name.monkey.retromusic.db.RoomPlaylistRepository import code.name.monkey.retromusic.fragments.LibraryViewModel @@ -10,7 +11,6 @@ import code.name.monkey.retromusic.fragments.genres.GenreDetailsViewModel import code.name.monkey.retromusic.fragments.playlists.PlaylistDetailsViewModel import code.name.monkey.retromusic.fragments.search.SearchViewModel import code.name.monkey.retromusic.model.Genre -import code.name.monkey.retromusic.model.Playlist import code.name.monkey.retromusic.network.networkModule import code.name.monkey.retromusic.repository.* import org.koin.android.ext.koin.androidContext @@ -100,7 +100,7 @@ private val viewModules = module { ) } - viewModel { (playlist: Playlist) -> + viewModel { (playlist: PlaylistWithSongs) -> PlaylistDetailsViewModel( get(), playlist diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.kt index 45d94b07..16491acc 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.kt @@ -10,7 +10,6 @@ import android.view.View import androidx.lifecycle.lifecycleScope import code.name.monkey.retromusic.* import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity -import code.name.monkey.retromusic.db.RoomPlaylistRepository import code.name.monkey.retromusic.extensions.findNavController import code.name.monkey.retromusic.fragments.LibraryViewModel import code.name.monkey.retromusic.helper.MusicPlayerRemote.openAndShuffleQueue @@ -26,7 +25,6 @@ import code.name.monkey.retromusic.util.AppRater.appLaunched import code.name.monkey.retromusic.util.PreferenceUtil import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import org.koin.android.ext.android.get import org.koin.android.ext.android.inject import java.util.* @@ -57,11 +55,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(), OnSharedPreferenceChangeLis appLaunched(this) addMusicServiceEventListener(libraryViewModel) updateTabs() - - val playlistRepository = get() - lifecycleScope.launch { - println("Size:${playlistRepository.playlistWithSongs()}") - } } override fun onSupportNavigateUp(): 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 efe2e437..caf41875 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 @@ -9,7 +9,7 @@ interface PlaylistDao { suspend fun checkPlaylistExists(name: String): List @Insert - suspend fun createPlaylist(playlistEntity: PlaylistEntity) + suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long @Query("SELECT * FROM PlaylistEntity") suspend fun playlists(): List @@ -23,4 +23,7 @@ interface PlaylistDao { @Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistName AND song_id = :songId") suspend fun checkSongExistsWithPlaylistName(playlistName: String, songId: Int): List + + @Query("SELECT * FROM SongEntity WHERE playlist_creator_id = :playlistId ORDER BY song_key") + suspend fun getSongs(playlistId: Int): List } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/db/PlaylistWithSongs.kt b/app/src/main/java/code/name/monkey/retromusic/db/PlaylistWithSongs.kt index 6645d6cd..405c7944 100644 --- a/app/src/main/java/code/name/monkey/retromusic/db/PlaylistWithSongs.kt +++ b/app/src/main/java/code/name/monkey/retromusic/db/PlaylistWithSongs.kt @@ -1,12 +1,16 @@ package code.name.monkey.retromusic.db +import android.os.Parcelable import androidx.room.Embedded import androidx.room.Relation +import kotlinx.android.parcel.Parcelize +@Parcelize data class PlaylistWithSongs( @Embedded val playlistEntity: PlaylistEntity, @Relation( parentColumn = "playlist_id", entityColumn = "playlist_creator_id" - ) val songs: List -) \ No newline at end of file + ) + val songs: List +):Parcelable \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/db/RoomPlaylistRepository.kt b/app/src/main/java/code/name/monkey/retromusic/db/RoomPlaylistRepository.kt index 7ab60e80..bdd7e0be 100644 --- a/app/src/main/java/code/name/monkey/retromusic/db/RoomPlaylistRepository.kt +++ b/app/src/main/java/code/name/monkey/retromusic/db/RoomPlaylistRepository.kt @@ -4,16 +4,17 @@ import androidx.annotation.WorkerThread interface RoomPlaylistRepository { - suspend fun createPlaylist(playlistEntity: PlaylistEntity) + suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long suspend fun checkPlaylistExists(playlistName: String): List suspend fun playlists(): List suspend fun playlistWithSongs(): List suspend fun insertSongs(songs: List) + suspend fun getSongs(playlistEntity: PlaylistEntity): List } class RealRoomPlaylistRepository(private val playlistDao: PlaylistDao) : RoomPlaylistRepository { @WorkerThread - override suspend fun createPlaylist(playlistEntity: PlaylistEntity) = + override suspend fun createPlaylist(playlistEntity: PlaylistEntity): Long = playlistDao.createPlaylist(playlistEntity) @WorkerThread @@ -29,12 +30,16 @@ class RealRoomPlaylistRepository(private val playlistDao: PlaylistDao) : RoomPla @WorkerThread override suspend fun insertSongs(songs: List) { - /* val tempList = ArrayList(songs) - val existingSongs = songs.map { - playlistDao.checkSongExistsWithPlaylistName(it.playlistCreatorName, it.songId) - }.first() - println("Existing ${existingSongs.size}") - tempList.removeAll(existingSongs)*/ + /* val tempList = ArrayList(songs) + val existingSongs = songs.map { + playlistDao.checkSongExistsWithPlaylistName(it.playlistCreatorName, it.songId) + }.first() + println("Existing ${existingSongs.size}") + tempList.removeAll(existingSongs)*/ playlistDao.insertSongs(songs) } + + override suspend fun getSongs(playlistEntity: PlaylistEntity): List { + return playlistDao.getSongs(playlistEntity.playListId) + } } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/db/SongEntity.kt b/app/src/main/java/code/name/monkey/retromusic/db/SongEntity.kt index 75c096ac..c7410bcf 100644 --- a/app/src/main/java/code/name/monkey/retromusic/db/SongEntity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/db/SongEntity.kt @@ -1,16 +1,19 @@ package code.name.monkey.retromusic.db +import android.os.Parcelable import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey +import kotlinx.android.parcel.Parcelize +@Parcelize @Entity class SongEntity( @ColumnInfo(name = "song_id") val songId: Int, @ColumnInfo(name = "playlist_creator_id") val playlistCreatorId: Int -) { +) : Parcelable { @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "song_key") var songPrimaryKey: Long = 0 diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/CreateRetroPlaylist.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/CreateRetroPlaylist.kt index 9f0b6ea3..74402ede 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/CreateRetroPlaylist.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/CreateRetroPlaylist.kt @@ -11,13 +11,18 @@ import code.name.monkey.retromusic.db.PlaylistEntity import code.name.monkey.retromusic.db.RoomPlaylistRepository import code.name.monkey.retromusic.extensions.colorButtons import code.name.monkey.retromusic.extensions.materialDialog +import code.name.monkey.retromusic.fragments.LibraryViewModel +import code.name.monkey.retromusic.fragments.ReloadType import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputLayout import kotlinx.android.synthetic.main.dialog_playlist.view.* import kotlinx.coroutines.launch -import org.koin.android.ext.android.get +import org.koin.android.ext.android.inject +import org.koin.androidx.viewmodel.ext.android.sharedViewModel class CreateRetroPlaylist : DialogFragment() { + private val playlistRepository by inject() + private val libraryViewModel by sharedViewModel() override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val view = LayoutInflater.from(requireActivity()).inflate(R.layout.dialog_playlist, null) val playlistView: TextInputEditText = view.actionNewPlaylist @@ -29,13 +34,16 @@ class CreateRetroPlaylist : DialogFragment() { ) { _, _ -> val playlistName = playlistView.text.toString() if (!TextUtils.isEmpty(playlistName)) { - val playlistRepository: RoomPlaylistRepository = get() lifecycleScope.launch { if (playlistRepository.checkPlaylistExists(playlistName).isEmpty()) { - playlistRepository.createPlaylist(PlaylistEntity(playlistName)) + val id: Long = + playlistRepository.createPlaylist(PlaylistEntity(playlistName)) + println(id) + libraryViewModel.forceReload(ReloadType.Playlists) } else { println("Playlist exists") } + } } else { playlistContainer.error = "Playlist is can't be empty" diff --git a/app/src/main/java/code/name/monkey/retromusic/fragments/LibraryViewModel.kt b/app/src/main/java/code/name/monkey/retromusic/fragments/LibraryViewModel.kt index baa117a6..53952e5c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/fragments/LibraryViewModel.kt +++ b/app/src/main/java/code/name/monkey/retromusic/fragments/LibraryViewModel.kt @@ -89,6 +89,8 @@ class LibraryViewModel( Albums -> albums.value = loadAlbums.await() Artists -> artists.value = loadArtists.await() HomeSections -> home.value = loadHome.await() + Playlists -> roomPlaylists.value = loadPlaylistsWithSongs.await() + Genres -> genres.value = loadGenres.await() } } @@ -136,5 +138,7 @@ enum class ReloadType { Songs, Albums, Artists, - HomeSections + HomeSections, + Playlists, + Genres, } \ 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 5c2d989b..e8b65a1e 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 @@ -12,11 +12,9 @@ import androidx.recyclerview.widget.RecyclerView import code.name.monkey.retromusic.R import code.name.monkey.retromusic.adapter.song.OrderablePlaylistSongAdapter import code.name.monkey.retromusic.adapter.song.SongAdapter +import code.name.monkey.retromusic.db.PlaylistWithSongs import code.name.monkey.retromusic.extensions.dipToPix import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment -import code.name.monkey.retromusic.helper.menu.PlaylistMenuHelper -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.util.PlaylistsUtil import com.h6ah4i.android.widget.advrecyclerview.animator.RefactoredDefaultItemAnimator @@ -32,7 +30,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli parametersOf(arguments.extraPlaylist) } - private lateinit var playlist: Playlist + private lateinit var playlist: PlaylistWithSongs private lateinit var adapter: SongAdapter private var wrappedAdapter: RecyclerView.Adapter<*>? = null @@ -46,53 +44,49 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli mainActivity.hideBottomBarVisibility(false) playlist = arguments.extraPlaylist + toolbar.title = playlist.playlistEntity.playlistName setUpRecyclerView() viewModel.getSongs().observe(viewLifecycleOwner, Observer { songs(it) }) - - viewModel.getPlaylist().observe(viewLifecycleOwner, Observer { - playlist = it - toolbar.title = it.name - }) } private fun setUpRecyclerView() { recyclerView.layoutManager = LinearLayoutManager(requireContext()) - if (playlist is AbsCustomPlaylist) { + /*if (playlist is AbsCustomPlaylist) { adapter = SongAdapter(requireActivity(), ArrayList(), R.layout.item_list, null) recyclerView.adapter = adapter - } else { - recyclerViewDragDropManager = RecyclerViewDragDropManager() - val animator = RefactoredDefaultItemAnimator() - adapter = OrderablePlaylistSongAdapter(requireActivity(), - ArrayList(), - R.layout.item_list, - null, - object : OrderablePlaylistSongAdapter.OnMoveItemListener { - override fun onMoveItem(fromPosition: Int, toPosition: Int) { - if (PlaylistsUtil.moveItem( - requireContext(), - playlist.id, - fromPosition, - toPosition - ) - ) { - val song = adapter.dataSet.removeAt(fromPosition) - adapter.dataSet.add(toPosition, song) - adapter.notifyItemMoved(fromPosition, toPosition) - } + } else {*/ + recyclerViewDragDropManager = RecyclerViewDragDropManager() + val animator = RefactoredDefaultItemAnimator() + adapter = OrderablePlaylistSongAdapter(requireActivity(), + ArrayList(), + R.layout.item_list, + null, + object : OrderablePlaylistSongAdapter.OnMoveItemListener { + override fun onMoveItem(fromPosition: Int, toPosition: Int) { + if (PlaylistsUtil.moveItem( + requireContext(), + playlist.playlistEntity.playListId, + fromPosition, + toPosition + ) + ) { + val song = adapter.dataSet.removeAt(fromPosition) + adapter.dataSet.add(toPosition, song) + adapter.notifyItemMoved(fromPosition, toPosition) } - }) - wrappedAdapter = recyclerViewDragDropManager!!.createWrappedAdapter(adapter) + } + }) + wrappedAdapter = recyclerViewDragDropManager!!.createWrappedAdapter(adapter) - recyclerView.adapter = wrappedAdapter - recyclerView.itemAnimator = animator + recyclerView.adapter = wrappedAdapter + recyclerView.itemAnimator = animator + + recyclerViewDragDropManager?.attachRecyclerView(recyclerView) - recyclerViewDragDropManager?.attachRecyclerView(recyclerView) - } adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { override fun onChanged() { super.onChanged() @@ -103,14 +97,14 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { super.onCreateOptionsMenu(menu, inflater) - val menuRes = if (playlist is AbsCustomPlaylist) + val menuRes =/* if (playlist is AbsCustomPlaylist) R.menu.menu_smart_playlist_detail - else R.menu.menu_playlist_detail + else*/ R.menu.menu_playlist_detail inflater.inflate(menuRes, menu) } override fun onOptionsItemSelected(item: MenuItem): Boolean { - return PlaylistMenuHelper.handleMenuClick(requireActivity(), playlist, item) + return true//PlaylistMenuHelper.handleMenuClick(requireActivity(), playlist, item) } private fun checkForPadding() { @@ -160,11 +154,11 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli } fun songs(songs: List) { + progressIndicator.hide() if (songs.isNotEmpty()) { adapter.swapDataSet(songs) } else { showEmptyView() } } - } \ No newline at end of file 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 de61bdeb..d8147f93 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 @@ -4,27 +4,26 @@ 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.db.PlaylistWithSongs import code.name.monkey.retromusic.interfaces.MusicServiceEventListener -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.repository.RealRepository -import code.name.monkey.retromusic.util.PlaylistsUtil +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.launch import kotlinx.coroutines.withContext class PlaylistDetailsViewModel( private val realRepository: RealRepository, - private var playlist: Playlist + private var playlist: PlaylistWithSongs ) : ViewModel(), MusicServiceEventListener { + private val _playListSongs = MutableLiveData>() - private val _playlist = MutableLiveData().apply { + private val _playlist = MutableLiveData().apply { postValue(playlist) } - fun getPlaylist(): LiveData = _playlist + fun getPlaylist(): LiveData = _playlist fun getSongs(): LiveData> = _playListSongs @@ -32,13 +31,13 @@ class PlaylistDetailsViewModel( loadPlaylistSongs(playlist) } - private fun loadPlaylistSongs(playlist: Playlist) = viewModelScope.launch { - val songs = realRepository.getPlaylistSongs(playlist) + private fun loadPlaylistSongs(playlist: PlaylistWithSongs) = viewModelScope.launch(Dispatchers.IO) { + val songs: List = realRepository.playlistSongs(playlist) withContext(Main) { _playListSongs.postValue(songs) } } override fun onMediaStoreChanged() { - if (playlist !is AbsCustomPlaylist) { + /*if (playlist !is AbsCustomPlaylist) { // Playlist deleted if (!PlaylistsUtil.doesPlaylistExist(App.getContext(), playlist.id)) { //TODO Finish the page @@ -54,7 +53,7 @@ class PlaylistDetailsViewModel( } } } - loadPlaylistSongs(playlist) + loadPlaylistSongs(playlist)*/ } override fun onServiceConnected() {} 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 5ebdc374..dbe85844 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 @@ -88,6 +88,8 @@ interface Repository { suspend fun playlistWithSongs(): List + suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs): List + fun songsFlow(): Flow>> fun albumsFlow(): Flow>> @@ -223,6 +225,12 @@ class RealRepository( override suspend fun playlistWithSongs(): List = roomPlaylistRepository.playlistWithSongs() + override suspend fun playlistSongs(playlistWithSongs: PlaylistWithSongs ): List { + return playlistWithSongs.songs.map { + songRepository.song(it.songId) + } + } + override suspend fun suggestionsHome(): Home { val songs = NotPlayedPlaylist().songs().shuffled().takeIf { @@ -263,7 +271,7 @@ class RealRepository( playlistRepository.favoritePlaylist(context.getString(R.string.favorites)).take(5) val songs = if (playlists.isNotEmpty()) PlaylistSongsLoader.getPlaylistSongList(context, playlists[0]) - else emptyList() + else emptyList() return Home(songs, FAVOURITES) } diff --git a/app/src/main/java/code/name/monkey/retromusic/repository/SongRepository.kt b/app/src/main/java/code/name/monkey/retromusic/repository/SongRepository.kt index 430401a6..e136a9b5 100644 --- a/app/src/main/java/code/name/monkey/retromusic/repository/SongRepository.kt +++ b/app/src/main/java/code/name/monkey/retromusic/repository/SongRepository.kt @@ -151,17 +151,14 @@ class RealSongRepository(private val context: Context) : SongRepository { } selectionFinal = selectionFinal + " AND " + MediaStore.Audio.Media.DURATION + ">= " + (PreferenceUtil.filterLength * 1000) - try { - return context.contentResolver.query( - MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, - baseProjection, - selectionFinal, - selectionValuesFinal, - sortOrder - ) - } catch (e: SecurityException) { - return null - } + + return context.contentResolver.query( + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + baseProjection, + selectionFinal, + selectionValuesFinal, + sortOrder + ) } private fun generateBlacklistSelection( diff --git a/app/src/main/res/layout/fragment_playlist_detail.xml b/app/src/main/res/layout/fragment_playlist_detail.xml index 8c3e7dd4..d75b5ba1 100644 --- a/app/src/main/res/layout/fragment_playlist_detail.xml +++ b/app/src/main/res/layout/fragment_playlist_detail.xml @@ -70,4 +70,12 @@ android:textColor="?android:attr/textColorSecondary" tools:visibility="visible" /> + + \ No newline at end of file diff --git a/app/src/main/res/navigation/main_graph.xml b/app/src/main/res/navigation/main_graph.xml index beead4b8..c3d3f444 100644 --- a/app/src/main/res/navigation/main_graph.xml +++ b/app/src/main/res/navigation/main_graph.xml @@ -26,7 +26,7 @@ tools:layout="@layout/fragment_playlist_detail"> + app:argType="code.name.monkey.retromusic.db.PlaylistWithSongs" />