mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-13 22:00:30 +05:30
feat: add pagination to dearrow in feed
This commit is contained in:
parent
ccaedfafbc
commit
800d6704cf
@ -34,30 +34,14 @@ import com.github.libretube.util.TextUtils
|
||||
|
||||
class VideosAdapter(
|
||||
private val streamItems: MutableList<StreamItem>,
|
||||
private val showAllAtOnce: Boolean = true,
|
||||
private val forceMode: LayoutMode = LayoutMode.RESPECT_PREF
|
||||
) : RecyclerView.Adapter<VideosViewHolder>() {
|
||||
|
||||
private var visibleCount = minOf(10, streamItems.size)
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return when {
|
||||
showAllAtOnce -> streamItems.size
|
||||
else -> minOf(streamItems.size, visibleCount)
|
||||
}
|
||||
}
|
||||
override fun getItemCount() = streamItems.size
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (streamItems[position].type == CAUGHT_UP_STREAM_TYPE) CAUGHT_UP_TYPE else NORMAL_TYPE
|
||||
}
|
||||
|
||||
fun updateItems() {
|
||||
val oldSize = visibleCount
|
||||
visibleCount += minOf(10, streamItems.size - oldSize)
|
||||
if (visibleCount == oldSize) return
|
||||
notifyItemRangeInserted(oldSize, visibleCount)
|
||||
}
|
||||
|
||||
fun insertItems(newItems: List<StreamItem>) {
|
||||
val feedSize = streamItems.size
|
||||
streamItems.addAll(newItems)
|
||||
@ -69,7 +53,7 @@ class VideosAdapter(
|
||||
it.url?.toID() == videoId
|
||||
}.takeIf { it > 0 } ?: return
|
||||
streamItems.removeAt(index)
|
||||
visibleCount--
|
||||
|
||||
notifyItemRemoved(index)
|
||||
notifyItemRangeChanged(index, itemCount)
|
||||
}
|
||||
|
@ -45,9 +45,11 @@ import com.github.libretube.ui.sheets.ChannelGroupsSheet
|
||||
import com.github.libretube.ui.sheets.FilterSortBottomSheet
|
||||
import com.github.libretube.ui.sheets.FilterSortBottomSheet.Companion.FILTER_SORT_REQUEST_KEY
|
||||
import com.github.libretube.util.PlayingQueue
|
||||
import com.github.libretube.util.deArrow
|
||||
import com.google.android.material.chip.Chip
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class SubscriptionsFragment : DynamicLayoutManagerFragment() {
|
||||
private var _binding: FragmentSubscriptionsBinding? = null
|
||||
@ -60,7 +62,9 @@ class SubscriptionsFragment : DynamicLayoutManagerFragment() {
|
||||
private var isCurrentTabSubChannels = false
|
||||
private var isAppBarFullyExpanded = true
|
||||
|
||||
var feedAdapter: VideosAdapter? = null
|
||||
private var feedAdapter: VideosAdapter? = null
|
||||
private val sortedFeed: MutableList<StreamItem> = mutableListOf()
|
||||
|
||||
private var channelsAdapter: SubscriptionChannelAdapter? = null
|
||||
private var selectedSortOrder = PreferenceHelper.getInt(PreferenceKeys.FEED_SORT_ORDER, 0)
|
||||
set(value) {
|
||||
@ -153,13 +157,7 @@ class SubscriptionsFragment : DynamicLayoutManagerFragment() {
|
||||
}
|
||||
|
||||
binding.subFeed.addOnBottomReachedListener {
|
||||
val binding = _binding ?: return@addOnBottomReachedListener
|
||||
|
||||
if (viewModel.videoFeed.value != null && !isCurrentTabSubChannels) {
|
||||
binding.subRefresh.isRefreshing = true
|
||||
feedAdapter?.updateItems()
|
||||
binding.subRefresh.isRefreshing = false
|
||||
}
|
||||
loadNextFeedItems()
|
||||
}
|
||||
|
||||
// add some extra margin to the subscribed channels while the mini player is visible
|
||||
@ -205,6 +203,30 @@ class SubscriptionsFragment : DynamicLayoutManagerFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadNextFeedItems() {
|
||||
val binding = _binding ?: return
|
||||
|
||||
val feedAdapter = feedAdapter ?: return
|
||||
|
||||
val hasMore = sortedFeed.size > feedAdapter.itemCount
|
||||
if (viewModel.videoFeed.value != null && !isCurrentTabSubChannels && !binding.subRefresh.isRefreshing && hasMore) {
|
||||
binding.subRefresh.isRefreshing = true
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
val toIndex = minOf(feedAdapter.itemCount + 10, sortedFeed.size)
|
||||
|
||||
val streamItemsToInsert = sortedFeed
|
||||
.subList(feedAdapter.itemCount, toIndex)
|
||||
.deArrow()
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
feedAdapter.insertItems(streamItemsToInsert)
|
||||
binding.subRefresh.isRefreshing = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupSortAndFilter() {
|
||||
binding.filterSort.setOnClickListener {
|
||||
val activityCompat = context as AppCompatActivity
|
||||
@ -332,9 +354,11 @@ class SubscriptionsFragment : DynamicLayoutManagerFragment() {
|
||||
DatabaseHelper.filterByStatusAndWatchPosition(it, hideWatched)
|
||||
}
|
||||
|
||||
val sortedFeed = feed
|
||||
val sorted = feed
|
||||
.sortedBySelectedOrder()
|
||||
.toMutableList()
|
||||
sortedFeed.clear()
|
||||
sortedFeed.addAll(sorted)
|
||||
|
||||
// add an "all caught up item"
|
||||
if (selectedSortOrder == 0) {
|
||||
@ -355,10 +379,9 @@ class SubscriptionsFragment : DynamicLayoutManagerFragment() {
|
||||
binding.subFeed.isGone = notLoaded
|
||||
binding.emptyFeed.isVisible = notLoaded
|
||||
|
||||
feedAdapter = VideosAdapter(
|
||||
sortedFeed.toMutableList(),
|
||||
showAllAtOnce = false
|
||||
)
|
||||
feedAdapter = VideosAdapter(mutableListOf())
|
||||
loadNextFeedItems()
|
||||
|
||||
binding.subFeed.adapter = feedAdapter
|
||||
binding.toggleSubs.text = getString(R.string.subscriptions)
|
||||
|
||||
@ -401,6 +424,11 @@ class SubscriptionsFragment : DynamicLayoutManagerFragment() {
|
||||
binding.toggleSubs.text = "${getString(R.string.subscriptions)} ($subCount)"
|
||||
}
|
||||
|
||||
fun removeItem(videoId: String) {
|
||||
feedAdapter?.removeItemById(videoId)
|
||||
sortedFeed.removeAll { it.url!!.toID() != videoId }
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
// manually restore the recyclerview state due to https://github.com/material-components/material-components-android/issues/3473
|
||||
|
@ -111,7 +111,7 @@ class VideoOptionsBottomSheet : BaseBottomSheet() {
|
||||
// get the current fragment
|
||||
val fragment = navHostFragment?.childFragmentManager?.fragments
|
||||
?.firstOrNull() as? SubscriptionsFragment
|
||||
fragment?.feedAdapter?.removeItemById(videoId)
|
||||
fragment?.removeItem(videoId)
|
||||
}
|
||||
setFragmentResult(VIDEO_OPTIONS_SHEET_REQUEST_KEY, bundleOf())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user