Add play all and shuffle all buttons for lists

This commit is contained in:
Hemanth S 2020-11-16 23:07:16 +05:30
parent c059176982
commit bf2f4ac757
14 changed files with 77 additions and 116 deletions

View file

@ -86,6 +86,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
setMiniPlayerAlphaProgress(slideOffset)
dimBackground.show()
dimBackground.alpha = slideOffset
println(slideOffset)
}
override fun onStateChanged(bottomSheet: View, newState: Int) {
@ -97,6 +98,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
onPanelCollapsed()
dimBackground.hide()
}
else -> {
println("Do something")
}
@ -114,11 +116,11 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
setupBottomSheet()
updateColor()
val themeColor = ATHUtil.resolveColor(this, android.R.attr.windowBackground, Color.GRAY)
val themeColor = resolveColor(android.R.attr.windowBackground, Color.GRAY)
dimBackground.setBackgroundColor(ColorUtil.withAlpha(themeColor, 0.5f))
dimBackground.setOnClickListener {
println("dimBackground")
collapsePanel()
}
}
@ -154,6 +156,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() {
fun collapsePanel() {
bottomSheetBehavior.state = STATE_COLLAPSED
setMiniPlayerAlphaProgress(0f)
}
fun expandPanel() {

View file

@ -98,7 +98,8 @@ public class WriteTagsAsyncTask extends DialogAsyncTask<LoadingInfo, Integer, Li
Context context = getContext();
if (context != null) {
if (wroteArtwork) {
MusicUtil.INSTANCE.insertAlbumArt(context, info.getArtworkInfo().getAlbumId(), albumArtFile.getPath());
MusicUtil.INSTANCE.
insertAlbumArt(context, info.getArtworkInfo().getAlbumId(), albumArtFile.getPath());
} else if (deletedArtwork) {
MusicUtil.INSTANCE.deleteAlbumArt(context, info.getArtworkInfo().getAlbumId());
}

View file

@ -15,15 +15,18 @@
package code.name.monkey.retromusic.adapter.song
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.FragmentActivity
import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.applyColor
import code.name.monkey.retromusic.extensions.applyOutlineColor
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.ICabHolder
import code.name.monkey.retromusic.model.Song
import com.google.android.material.button.MaterialButton
class ShuffleButtonSongAdapter(
activity: AppCompatActivity,
activity: FragmentActivity,
dataSet: MutableList<Song>,
itemLayoutRes: Int,
ICabHolder: ICabHolder?
@ -35,16 +38,19 @@ class ShuffleButtonSongAdapter(
override fun onBindViewHolder(holder: SongAdapter.ViewHolder, position: Int) {
if (holder.itemViewType == OFFSET_ITEM) {
val color = ThemeStore.accentColor(activity)
val viewHolder = holder as ViewHolder
viewHolder.playAction?.let {
it.setOnClickListener {
MusicPlayerRemote.openQueue(dataSet, 0, true)
}
it.applyOutlineColor(color)
}
viewHolder.shuffleAction?.let {
it.setOnClickListener {
MusicPlayerRemote.openAndShuffleQueue(dataSet, true)
}
it.applyColor(color)
}
} else {
super.onBindViewHolder(holder, position - 1)

View file

@ -19,7 +19,7 @@ import androidx.room.RoomDatabase
@Database(
entities = [PlaylistEntity::class, SongEntity::class, HistoryEntity::class, PlayCountEntity::class, BlackListStoreEntity::class, LyricsEntity::class],
version = 22,
version = 23,
exportSchema = false
)
abstract class RetroDatabase : RoomDatabase() {

View file

@ -1,37 +0,0 @@
/*
* Copyright (c) 2020 Hemanth Savarla.
*
* 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.fragments
import androidx.lifecycle.ViewModel
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.*
open class CoroutineViewModel(
private val mainDispatcher: CoroutineDispatcher
) : ViewModel() {
private val job = Job()
protected val scope = CoroutineScope(job + mainDispatcher)
protected fun launch(
context: CoroutineContext = mainDispatcher,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
) = scope.launch(context, start, block)
override fun onCleared() {
super.onCleared()
job.cancel()
}
}

View file

@ -26,6 +26,7 @@ import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.adapter.album.AlbumAdapter
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
import code.name.monkey.retromusic.adapter.song.ShuffleButtonSongAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.db.toSong
import code.name.monkey.retromusic.extensions.dipToPix
@ -34,7 +35,6 @@ import code.name.monkey.retromusic.interfaces.IAlbumClickListener
import code.name.monkey.retromusic.interfaces.IArtistClickListener
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.state.NowPlayingPanelState
import code.name.monkey.retromusic.util.RetroUtil
import kotlinx.android.synthetic.main.fragment_playlist_detail.*
@ -48,18 +48,10 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
mainActivity.setSupportActionBar(toolbar)
progressIndicator.hide()
when (args.type) {
TOP_ARTISTS -> {
loadArtists(R.string.top_artists, TOP_ARTISTS)
}
RECENT_ARTISTS -> {
loadArtists(R.string.recent_artists, RECENT_ARTISTS)
}
TOP_ALBUMS -> {
loadAlbums(R.string.top_albums, TOP_ALBUMS)
}
RECENT_ALBUMS -> {
loadAlbums(R.string.recent_albums, RECENT_ALBUMS)
}
TOP_ARTISTS -> loadArtists(R.string.top_artists, TOP_ARTISTS)
RECENT_ARTISTS -> loadArtists(R.string.recent_artists, RECENT_ARTISTS)
TOP_ALBUMS -> loadAlbums(R.string.top_albums, TOP_ALBUMS)
RECENT_ALBUMS -> loadAlbums(R.string.recent_albums, RECENT_ALBUMS)
FAVOURITES -> loadFavorite()
HISTORY_PLAYLIST -> loadHistory()
LAST_ADDED_PLAYLIST -> lastAddedSongs()
@ -77,7 +69,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
private fun lastAddedSongs() {
toolbar.setTitle(R.string.last_added)
val songAdapter = SongAdapter(
val songAdapter = ShuffleButtonSongAdapter(
requireActivity(),
mutableListOf(),
R.layout.item_list, null
@ -93,7 +85,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
private fun topPlayed() {
toolbar.setTitle(R.string.my_top_tracks)
val songAdapter = SongAdapter(
val songAdapter = ShuffleButtonSongAdapter(
requireActivity(),
mutableListOf(),
R.layout.item_list, null
@ -110,7 +102,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
private fun loadHistory() {
toolbar.setTitle(R.string.history)
val songAdapter = SongAdapter(
val songAdapter = ShuffleButtonSongAdapter(
requireActivity(),
mutableListOf(),
R.layout.item_list, null

View file

@ -12,14 +12,13 @@ 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.adapter.song.ShuffleButtonSongAdapter
import code.name.monkey.retromusic.db.PlaylistWithSongs
import code.name.monkey.retromusic.db.toSongs
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.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
@ -32,7 +31,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
}
private lateinit var playlist: PlaylistWithSongs
private lateinit var playlistSongAdapter: PlaylistSongAdapter
private lateinit var playlistSongAdapter: ShuffleButtonSongAdapter
private fun setUpTransitions() {
val transform = MaterialContainerTransform()
@ -61,8 +60,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
}
private fun setUpRecyclerView() {
playlistSongAdapter = PlaylistSongAdapter(
playlist.playlistEntity,
playlistSongAdapter = ShuffleButtonSongAdapter(
requireActivity(),
ArrayList(),
R.layout.item_list,

View file

@ -15,12 +15,14 @@
package code.name.monkey.retromusic.fragments.search
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.speech.RecognizerIntent
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
@ -143,6 +145,19 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
showToast(getString(R.string.speech_not_supported))
}
}
override fun onDestroyView() {
hideKeyboard(view)
super.onDestroyView()
}
private fun hideKeyboard(view: View?) {
if (view != null) {
val imm: InputMethodManager =
requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
}
}
fun TextInputEditText.clearText() {

View file

@ -72,7 +72,7 @@ class LibraryPreferenceDialog : DialogFragment() {
categoryAdapter.categoryInfos = PreferenceUtil.defaultCategories
}
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok) { _, _ -> updateCategories(categoryAdapter.categoryInfos) }
.setPositiveButton( R.string.done) { _, _ -> updateCategories(categoryAdapter.categoryInfos) }
.setView(view)
.create()
.colorButtons()

View file

@ -94,7 +94,7 @@ object MusicUtil : KoinComponent {
fun deleteAlbumArt(context: Context, albumId: Long) {
val contentResolver = context.contentResolver
val localUri = Uri.parse("content://media/external/audio/albumart")
contentResolver.delete(ContentUris.withAppendedId(localUri, albumId.toLong()), null, null)
contentResolver.delete(ContentUris.withAppendedId(localUri, albumId), null, null)
contentResolver.notifyChange(localUri, null)
}
@ -165,7 +165,7 @@ object MusicUtil : KoinComponent {
try {
val newLyrics =
FileUtil.read(f)
if (newLyrics != null && !newLyrics.trim { it <= ' ' }.isEmpty()) {
if (newLyrics != null && newLyrics.trim { it <= ' ' }.isNotEmpty()) {
if (AbsSynchronizedLyrics.isSynchronized(newLyrics)) {
return newLyrics
}
@ -283,9 +283,8 @@ object MusicUtil : KoinComponent {
path: String?
) {
val contentResolver = context.contentResolver
val artworkUri =
Uri.parse("content://media/external/audio/albumart")
contentResolver.delete(ContentUris.withAppendedId(artworkUri, albumId.toLong()), null, null)
val artworkUri = Uri.parse("content://media/external/audio/albumart")
contentResolver.delete(ContentUris.withAppendedId(artworkUri, albumId), null, null)
val values = ContentValues()
values.put("album_id", albumId)
values.put("_data", path)
@ -444,9 +443,7 @@ object MusicUtil : KoinComponent {
}
fun deleteTracks(context: Context, songs: List<Song>) {
val projection = arrayOf(
BaseColumns._ID, MediaStore.MediaColumns.DATA
)
val projection = arrayOf(BaseColumns._ID, MediaStore.MediaColumns.DATA)
val selection = StringBuilder()
selection.append(BaseColumns._ID + " IN (")
for (i in songs.indices) {

View file

@ -12,59 +12,48 @@
~ See the GNU General Public License for more details.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|end"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/playAction"
android:layout_width="wrap_content"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="4dp"
android:layout_weight="1"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:text="@string/action_play_all"
android:visibility="gone"
android:textColor="?android:attr/textColorPrimary"
app:backgroundTint="?attr/colorSurface"
app:icon="@drawable/ic_play_arrow" />
app:cornerRadius="8dp"
app:layout_constraintEnd_toStartOf="@+id/shuffleAction"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/shuffleAction"
android:layout_width="wrap_content"
style="@style/Widget.MaterialComponents.Button.TextButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:text="@string/shuffle"
android:visibility="gone"
android:textColor="?android:attr/textColorPrimary"
app:backgroundTint="?attr/colorSurface"
app:icon="@drawable/ic_shuffle" />
app:cornerRadius="8dp"
app:layout_constraintBottom_toBottomOf="@+id/playAction"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/playAction"
app:layout_constraintTop_toTopOf="@+id/playAction" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:padding="16dp"
app:srcCompat="@drawable/ic_sort"
app:tint="?attr/colorControlNormal" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:padding="16dp"
app:srcCompat="@drawable/ic_grid_size"
app:tint="?attr/colorControlNormal" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:padding="16dp"
app:srcCompat="@drawable/ic_layout"
app:tint="?attr/colorControlNormal" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -20,6 +20,7 @@
android:background="?attr/rectSelector"
android:descendantFocusability="blocksDescendants"
android:focusable="true"
android:minHeight="@dimen/md_listitem_height"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingEnd="0dp"
@ -41,11 +42,7 @@
android:layout_weight="1"
android:ellipsize="end"
android:gravity="center_vertical"
android:minHeight="@dimen/md_listitem_height"
android:paddingStart="@dimen/md_listitem_control_margin"
android:paddingLeft="@dimen/md_listitem_control_margin"
android:paddingTop="@dimen/md_listitem_vertical_margin_choice"
android:paddingBottom="@dimen/md_listitem_vertical_margin_choice"
android:paddingHorizontal="16dp"
android:singleLine="true"
android:textAppearance="@style/TextViewNormal"
android:textColor="?android:attr/textColorPrimary"

View file

@ -7,7 +7,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.2'
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
def nav_version = "2.3.0"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"

View file

@ -1,6 +1,6 @@
#Sat Jun 06 02:12:18 IST 2020
#Fri Nov 13 20:52:31 IST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip