mirror of
https://github.com/cmclark00/RetroMusicPlayer.git
synced 2025-05-17 23:55:21 +01:00
Merge branch 'RetroMusicPlayer:dev' into md3
This commit is contained in:
commit
8036fe1dc5
8 changed files with 137 additions and 7 deletions
|
@ -161,4 +161,5 @@ const val CIRCLE_PLAY_BUTTON = "circle_play_button"
|
|||
const val SWIPE_ANYWHERE_NOW_PLAYING = "swipe_anywhere_now_playing"
|
||||
const val PAUSE_HISTORY = "pause_history"
|
||||
const val MANAGE_AUDIO_FOCUS = "manage_audio_focus"
|
||||
const val SWIPE_DOWN_DISMISS = "swipe_to_dismiss"
|
||||
const val SWIPE_DOWN_DISMISS = "swipe_to_dismiss"
|
||||
const val ENABLE_SEARCH_PLAYLIST= "enable_search_playlist"
|
|
@ -25,6 +25,7 @@ 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.fragments.LibraryViewModel
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.ViewUtil
|
||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.DraggableItemAdapter
|
||||
|
@ -43,9 +44,20 @@ class OrderablePlaylistSongAdapter(
|
|||
|
||||
val libraryViewModel: LibraryViewModel by activity.viewModel()
|
||||
|
||||
private var filtered = false
|
||||
private var filter: CharSequence? = null
|
||||
private var fullDataSet: MutableList<Song>
|
||||
|
||||
init {
|
||||
this.setHasStableIds(true)
|
||||
this.setMultiSelectMenuRes(R.menu.menu_playlists_songs_selection)
|
||||
fullDataSet = dataSet.toMutableList()
|
||||
}
|
||||
|
||||
override fun swapDataSet(dataSet: List<Song>) {
|
||||
super.swapDataSet(dataSet)
|
||||
fullDataSet = dataSet.toMutableList()
|
||||
onFilter(filter)
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
|
@ -90,13 +102,22 @@ class OrderablePlaylistSongAdapter(
|
|||
return super.onSongMenuItemClick(item)
|
||||
}
|
||||
|
||||
override fun onClick(v: View?) {
|
||||
if (isInQuickSelectMode || !filtered) {
|
||||
super.onClick(v)
|
||||
} else {
|
||||
val position = fullDataSet.indexOf(dataSet.get(layoutPosition))
|
||||
MusicPlayerRemote.openQueueKeepShuffleMode(fullDataSet, position, true)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
dragView?.isVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCheckCanStartDrag(holder: ViewHolder, position: Int, x: Int, y: Int): Boolean {
|
||||
if (isInQuickSelectMode) {
|
||||
if (isInQuickSelectMode || filtered) {
|
||||
return false
|
||||
}
|
||||
return ViewUtil.hitTest(holder.imageText!!, x, y) || ViewUtil.hitTest(
|
||||
|
@ -127,8 +148,27 @@ class OrderablePlaylistSongAdapter(
|
|||
}
|
||||
|
||||
fun saveSongs(playlistEntity: PlaylistEntity) {
|
||||
onFilter(null)
|
||||
activity.lifecycleScope.launch(Dispatchers.IO) {
|
||||
libraryViewModel.insertSongs(dataSet.toSongsEntity(playlistEntity))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun onFilter(text: CharSequence?) {
|
||||
filter = text
|
||||
if (text.isNullOrEmpty()) {
|
||||
filtered = false
|
||||
dataSet = fullDataSet
|
||||
} else {
|
||||
filtered = true
|
||||
dataSet = fullDataSet.filter { song -> song.title.contains(text, ignoreCase = true) }
|
||||
.toMutableList()
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun hasSongs(): Boolean {
|
||||
return itemCount > 0 || (filtered && fullDataSet.size > 0)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import android.view.MenuItem
|
|||
import android.view.View
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.widget.addTextChangedListener
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
|
@ -21,12 +23,14 @@ 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.fragments.search.clearText
|
||||
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.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.ThemedFastScroller
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.material.shape.MaterialShapeDrawable
|
||||
|
@ -35,6 +39,9 @@ import com.google.android.material.transition.MaterialContainerTransform
|
|||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import com.h6ah4i.android.widget.advrecyclerview.animator.DraggableItemAnimator
|
||||
import com.h6ah4i.android.widget.advrecyclerview.draggable.RecyclerViewDragDropManager
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import org.koin.core.parameter.parametersOf
|
||||
|
||||
|
@ -51,6 +58,8 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
|||
private lateinit var playlist: PlaylistWithSongs
|
||||
private lateinit var playlistSongAdapter: OrderablePlaylistSongAdapter
|
||||
|
||||
private val _searchFlow = MutableSharedFlow<CharSequence?>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
sharedElementEnterTransition = MaterialContainerTransform(requireContext(), true).apply {
|
||||
|
@ -71,6 +80,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
|||
// binding.container.transitionName = playlist.playlistEntity.playlistName
|
||||
|
||||
setUpRecyclerView()
|
||||
setUpSearch()
|
||||
setupButtons()
|
||||
viewModel.getPlaylist().observe(viewLifecycleOwner) { playlistWithSongs ->
|
||||
playlist = playlistWithSongs
|
||||
|
@ -112,6 +122,33 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
|||
}
|
||||
}
|
||||
|
||||
private fun setUpSearch() {
|
||||
if (!PreferenceUtil.enableSearchPlaylist) {
|
||||
binding.playlistSearchView.visibility = View.GONE
|
||||
} else {
|
||||
binding.playlistSearchView.visibility = View.VISIBLE
|
||||
}
|
||||
binding.playlistSearchView.addTextChangedListener { text ->
|
||||
lifecycleScope.launch {
|
||||
_searchFlow.emit(text)
|
||||
binding.clearSearch.visibility =
|
||||
if (text.isNullOrBlank()) View.GONE else View.VISIBLE
|
||||
}
|
||||
}
|
||||
binding.clearSearch.setOnClickListener {
|
||||
lifecycleScope.launch {
|
||||
_searchFlow.emit(null)
|
||||
binding.playlistSearchView.clearText()
|
||||
binding.clearSearch.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
lifecycleScope.launch {
|
||||
_searchFlow.debounce(300).collect { text ->
|
||||
playlistSongAdapter.onFilter(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUpRecyclerView() {
|
||||
playlistSongAdapter = OrderablePlaylistSongAdapter(
|
||||
arguments.extraPlaylistId,
|
||||
|
@ -150,8 +187,18 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
|||
}
|
||||
|
||||
private fun checkIsEmpty() {
|
||||
binding.empty.isVisible = playlistSongAdapter.itemCount == 0
|
||||
binding.emptyText.isVisible = playlistSongAdapter.itemCount == 0
|
||||
if (_binding != null) {
|
||||
if (playlistSongAdapter.itemCount != 0) {
|
||||
binding.empty.isVisible = false
|
||||
} else {
|
||||
binding.empty.isVisible = true
|
||||
if (playlistSongAdapter.hasSongs()) {
|
||||
binding.emptyText.text = getString(R.string.no_search_results)
|
||||
} else {
|
||||
binding.emptyText.text = getString(R.string.no_songs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
@ -160,6 +207,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
|
|||
}
|
||||
|
||||
override fun onPause() {
|
||||
binding.playlistSearchView.clearText()
|
||||
playlistSongAdapter.saveSongs(playlist.playlistEntity)
|
||||
super.onPause()
|
||||
}
|
||||
|
|
|
@ -680,6 +680,9 @@ object PreferenceUtil {
|
|||
val rememberLastTab: Boolean
|
||||
get() = sharedPreferences.getBoolean(REMEMBER_LAST_TAB, true)
|
||||
|
||||
val enableSearchPlaylist: Boolean
|
||||
get() = sharedPreferences.getBoolean(ENABLE_SEARCH_PLAYLIST, true)
|
||||
|
||||
var lastTab: Int
|
||||
get() = sharedPreferences
|
||||
.getInt(LAST_USED_TAB, 0)
|
||||
|
|
|
@ -30,6 +30,33 @@
|
|||
android:paddingBottom="16dp"
|
||||
android:paddingHorizontal="16dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/playlistSearchView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/play_button"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toLeftOf="@id/clear_search"
|
||||
android:background="@null"
|
||||
android:hint="@string/action_search"
|
||||
android:inputType="text|textAutoComplete"
|
||||
android:padding="12dp"
|
||||
android:textAppearance="@style/TextViewSubtitle1">
|
||||
</com.google.android.material.textfield.TextInputEditText>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/clear_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?roundSelector"
|
||||
android:padding="10dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/playlistSearchView"
|
||||
app:srcCompat="@drawable/ic_close"
|
||||
app:tint="?attr/colorControlNormal"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.imageview.ShapeableImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="0dp"
|
||||
|
@ -116,12 +143,13 @@
|
|||
|
||||
<LinearLayout
|
||||
android:id="@android:id/empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="30dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
|
|
|
@ -277,6 +277,7 @@
|
|||
<string name="no_purchase_found">No purchase found.</string>
|
||||
<string name="no_results">No results</string>
|
||||
<string name="no_songs">You have no songs</string>
|
||||
<string name="no_search_results">No search results</string>
|
||||
<string name="normal">Normal</string>
|
||||
<string name="normal_lyrics">Normal lyrics</string>
|
||||
<string name="not_listed_in_media_store"><![CDATA[<b>%s</b> is not listed in the media store.]]></string>
|
||||
|
@ -365,6 +366,7 @@
|
|||
<string name="pref_summary_open_source_licences">License details for open source software</string>
|
||||
<string name="pref_summary_pause_history">When enabled, newly played songs won\'t show in history</string>
|
||||
<string name="pref_summary_remember_tab">Navigate to the last used tab on start</string>
|
||||
<string name="pref_summary_enable_search_playlist">Show a search field in a playlist</string>
|
||||
<string name="pref_summary_show_lyrics">Display synced lyrics over album cover</string>
|
||||
<string name="pref_summary_suggestions">Show New Music Mix on homescreen</string>
|
||||
<string name="pref_summary_swipe_anywhere_now_playing">Enables changing song by swiping anywhere on the now playing screen</string>
|
||||
|
@ -412,6 +414,7 @@
|
|||
<string name="pref_title_open_source_licences">Open source licences</string>
|
||||
<string name="pref_title_pause_history">Pause history</string>
|
||||
<string name="pref_title_remember_tab">Remember last tab</string>
|
||||
<string name="pref_title_enable_search_playlist">Enable search in playlist</string>
|
||||
<string name="pref_title_show_lyrics">Show lyrics</string>
|
||||
<string name="pref_title_suggestions">Show suggestions</string>
|
||||
<string name="pref_title_swipe_anywhere_now_playing">Swipe anywhere to change song</string>
|
||||
|
|
|
@ -67,6 +67,13 @@
|
|||
android:summary="@string/pref_summary_remember_tab"
|
||||
android:title="@string/pref_title_remember_tab" />
|
||||
|
||||
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATESwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="enable_search_playlist"
|
||||
android:layout="@layout/list_item_view_switch"
|
||||
android:summary="@string/pref_summary_enable_search_playlist"
|
||||
android:title="@string/pref_title_enable_search_playlist" />
|
||||
|
||||
<code.name.monkey.appthemehelper.common.prefs.supportv7.ATEListPreference
|
||||
android:defaultValue="0"
|
||||
android:entries="@array/pref_tab_text_mode_titles"
|
||||
|
|
|
@ -17,7 +17,7 @@ yslibrary_keyboardvisibilityevent_version = "3.0.0-RC3"
|
|||
koinAndroid = "3.4.0"
|
||||
kotlinGradlePlugin = "1.9.22"
|
||||
|
||||
kotlinxCoroutinesAndroid = "1.7.3"
|
||||
kotlinxCoroutinesAndroid = "1.8.1"
|
||||
android_tab_library_version = "2.2.0"
|
||||
fast_scroll_libraryVersion = "1.2.0"
|
||||
lifecycle_version = "2.7.0"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue