mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 06:10:31 +05:30
Merge pull request #3648 from Bnyro/master
Sort menu for local and private playlist
This commit is contained in:
commit
9cb2cfd6aa
@ -38,6 +38,7 @@ object PreferenceKeys {
|
||||
const val ALTERNATIVE_VIDEOS_LAYOUT = "alternative_videos_layout"
|
||||
const val NEW_VIDEOS_BADGE = "new_videos_badge"
|
||||
const val PLAYLISTS_ORDER = "playlists_order"
|
||||
const val PLAYLIST_SORT_ORDER = "playlist_sort_order"
|
||||
|
||||
/**
|
||||
* Instance
|
||||
|
@ -6,6 +6,7 @@ import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
@ -22,6 +23,7 @@ import com.github.libretube.api.RetrofitInstance
|
||||
import com.github.libretube.api.obj.Playlist
|
||||
import com.github.libretube.api.obj.StreamItem
|
||||
import com.github.libretube.constants.IntentData
|
||||
import com.github.libretube.constants.PreferenceKeys
|
||||
import com.github.libretube.databinding.FragmentPlaylistBinding
|
||||
import com.github.libretube.db.DatabaseHolder
|
||||
import com.github.libretube.enums.PlaylistType
|
||||
@ -31,8 +33,10 @@ import com.github.libretube.extensions.serializable
|
||||
import com.github.libretube.extensions.toID
|
||||
import com.github.libretube.helpers.ImageHelper
|
||||
import com.github.libretube.helpers.NavigationHelper
|
||||
import com.github.libretube.helpers.PreferenceHelper
|
||||
import com.github.libretube.ui.adapters.PlaylistAdapter
|
||||
import com.github.libretube.ui.models.PlayerViewModel
|
||||
import com.github.libretube.ui.sheets.BaseBottomSheet
|
||||
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
||||
import com.github.libretube.util.PlayingQueue
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -58,6 +62,11 @@ class PlaylistFragment : Fragment() {
|
||||
|
||||
// view models
|
||||
private val playerViewModel: PlayerViewModel by activityViewModels()
|
||||
private var selectedSortOrder = PreferenceHelper.getInt(PreferenceKeys.PLAYLIST_SORT_ORDER, 0)
|
||||
set(value) {
|
||||
PreferenceHelper.putInt(PreferenceKeys.PLAYLIST_SORT_ORDER, value)
|
||||
field = value
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -139,6 +148,8 @@ class PlaylistFragment : Fragment() {
|
||||
|
||||
binding.playlistInfo.text = getChannelAndVideoString(response, response.videos)
|
||||
|
||||
showPlaylistVideos(response)
|
||||
|
||||
// show playlist options
|
||||
binding.optionsMenu.setOnClickListener {
|
||||
PlaylistOptionsBottomSheet(
|
||||
@ -197,67 +208,17 @@ class PlaylistFragment : Fragment() {
|
||||
keepQueue = true
|
||||
)
|
||||
}
|
||||
}
|
||||
binding.sortMenu.isGone = false
|
||||
binding.sortMenu.setOnClickListener {
|
||||
val sortOptions = resources.getStringArray(R.array.playlistSortOptions)
|
||||
|
||||
playlistAdapter = PlaylistAdapter(playlistFeed, playlistId!!, playlistType)
|
||||
|
||||
// listen for playlist items to become deleted
|
||||
playlistAdapter!!.registerAdapterDataObserver(object :
|
||||
RecyclerView.AdapterDataObserver() {
|
||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||
if (positionStart == 0) {
|
||||
ImageHelper.loadImage(
|
||||
playlistFeed.firstOrNull()?.thumbnail ?: "",
|
||||
binding.thumbnail
|
||||
)
|
||||
}
|
||||
|
||||
binding.playlistInfo.text =
|
||||
getChannelAndVideoString(response, playlistFeed.size)
|
||||
BaseBottomSheet().apply {
|
||||
setSimpleItems(sortOptions.toList()) { index ->
|
||||
selectedSortOrder = index
|
||||
showPlaylistVideos(response)
|
||||
}
|
||||
}.show(childFragmentManager)
|
||||
}
|
||||
})
|
||||
|
||||
binding.playlistRecView.adapter = playlistAdapter
|
||||
binding.playlistScrollview.viewTreeObserver.addOnScrollChangedListener {
|
||||
if (_binding?.playlistScrollview?.canScrollVertically(1) == false &&
|
||||
!isLoading
|
||||
) {
|
||||
// append more playlists to the recycler view
|
||||
if (playlistType != PlaylistType.PUBLIC) {
|
||||
isLoading = true
|
||||
playlistAdapter?.showMoreItems()
|
||||
isLoading = false
|
||||
} else {
|
||||
fetchNextPage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// listener for swiping to the left or right
|
||||
if (playlistType != PlaylistType.PUBLIC) {
|
||||
val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(
|
||||
0,
|
||||
ItemTouchHelper.LEFT
|
||||
) {
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onSwiped(
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
direction: Int
|
||||
) {
|
||||
val position = viewHolder.absoluteAdapterPosition
|
||||
playlistAdapter!!.removeFromPlaylist(requireContext(), position)
|
||||
}
|
||||
}
|
||||
|
||||
val itemTouchHelper = ItemTouchHelper(itemTouchCallback)
|
||||
itemTouchHelper.attachToRecyclerView(binding.playlistRecView)
|
||||
}
|
||||
|
||||
withContext(Dispatchers.IO) {
|
||||
@ -275,6 +236,88 @@ class PlaylistFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPlaylistVideos(playlist: Playlist) {
|
||||
val videos = if (playlistType == PlaylistType.PUBLIC) playlistFeed
|
||||
else {
|
||||
when (selectedSortOrder) {
|
||||
0, 1 -> {
|
||||
if (playlistType == PlaylistType.LOCAL) playlistFeed.sortedBy {
|
||||
it.url.orEmpty().toInt()
|
||||
} else playlistFeed
|
||||
}
|
||||
2, 3 -> {
|
||||
playlistFeed.sortedBy { it.duration }
|
||||
}
|
||||
4, 5 -> {
|
||||
playlistFeed.sortedBy { it.title }
|
||||
}
|
||||
else -> throw IllegalArgumentException()
|
||||
}.let {
|
||||
if (selectedSortOrder % 2 == 0) it else it.reversed()
|
||||
}
|
||||
}
|
||||
|
||||
playlistAdapter = PlaylistAdapter(videos.toMutableList(), playlistId!!, playlistType)
|
||||
binding.playlistRecView.adapter = playlistAdapter
|
||||
|
||||
// listen for playlist items to become deleted
|
||||
playlistAdapter!!.registerAdapterDataObserver(object :
|
||||
RecyclerView.AdapterDataObserver() {
|
||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||
if (positionStart == 0) {
|
||||
ImageHelper.loadImage(
|
||||
playlistFeed.firstOrNull()?.thumbnail ?: "",
|
||||
binding.thumbnail
|
||||
)
|
||||
}
|
||||
|
||||
binding.playlistInfo.text = getChannelAndVideoString(playlist, playlistFeed.size)
|
||||
}
|
||||
})
|
||||
|
||||
binding.playlistScrollview.viewTreeObserver.addOnScrollChangedListener {
|
||||
if (_binding?.playlistScrollview?.canScrollVertically(1) == false &&
|
||||
!isLoading
|
||||
) {
|
||||
// append more playlists to the recycler view
|
||||
if (playlistType != PlaylistType.PUBLIC) {
|
||||
isLoading = true
|
||||
playlistAdapter?.showMoreItems()
|
||||
isLoading = false
|
||||
} else {
|
||||
fetchNextPage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// listener for swiping to the left or right
|
||||
if (playlistType != PlaylistType.PUBLIC) {
|
||||
val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(
|
||||
0,
|
||||
ItemTouchHelper.LEFT
|
||||
) {
|
||||
override fun onMove(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
target: RecyclerView.ViewHolder
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onSwiped(
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
direction: Int
|
||||
) {
|
||||
val position = viewHolder.absoluteAdapterPosition
|
||||
playlistAdapter!!.removeFromPlaylist(requireContext(), position)
|
||||
}
|
||||
}
|
||||
|
||||
val itemTouchHelper = ItemTouchHelper(itemTouchCallback)
|
||||
itemTouchHelper.attachToRecyclerView(binding.playlistRecView)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("StringFormatInvalid", "StringFormatMatches")
|
||||
private fun getChannelAndVideoString(playlist: Playlist, count: Int): String {
|
||||
return playlist.uploader?.let {
|
||||
|
10
app/src/main/res/drawable/ic_sort.xml
Normal file
10
app/src/main/res/drawable/ic_sort.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:autoMirrored="true"
|
||||
android:height="24dp"
|
||||
android:tint="?colorControlNormal"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:width="24dp">
|
||||
<path android:fillColor="@android:color/white"
|
||||
android:pathData="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z"/>
|
||||
</vector>
|
@ -53,6 +53,15 @@
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/sortMenu"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/ic_sort"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/optionsMenu"
|
||||
android:layout_width="20dp"
|
||||
|
@ -127,7 +127,7 @@
|
||||
android:paddingHorizontal="10dp"
|
||||
android:text="@string/most_recent"
|
||||
android:textSize="16sp"
|
||||
app:drawableEndCompat="@drawable/ic_arrow_downward" />
|
||||
app:drawableEndCompat="@drawable/ic_sort" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
@ -286,6 +286,15 @@
|
||||
<item>@string/yt_shorts</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="playlistSortOptions">
|
||||
<item>@string/least_recent</item>
|
||||
<item>@string/most_recent</item>
|
||||
<item>@string/duration</item>
|
||||
<item>@string/duration_reversed</item>
|
||||
<item>@string/playlist_name_az</item>
|
||||
<item>@string/playlist_name_za</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="requiredNetwork">
|
||||
<item>@string/network_all</item>
|
||||
<item>@string/network_wifi</item>
|
||||
|
@ -408,6 +408,10 @@
|
||||
<string name="play_automatically_summary">Start playing video automatically when selecting</string>
|
||||
<string name="fullscreen_gestures">Enter/exit fullscreen gestures</string>
|
||||
<string name="go_to_video">Go to video</string>
|
||||
<string name="playlist_name_az">Playlist Name (A-Z)</string>
|
||||
<string name="playlist_name_za">Playlist Name (Z-A)</string>
|
||||
<string name="duration">Duration</string>
|
||||
<string name="duration_reversed">Duration (reversed)</string>
|
||||
|
||||
<!-- Notification channel strings -->
|
||||
<string name="download_channel_name">Download Service</string>
|
||||
|
Loading…
Reference in New Issue
Block a user