Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add pagination to dearrow in feed #5984

Merged
merged 1 commit into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -69,7 +53,7 @@ class VideosAdapter(
it.url?.toID() == videoId
}.takeIf { it > 0 } ?: return
streamItems.removeAt(index)
visibleCount--

notifyItemRemoved(index)
notifyItemRangeChanged(index, itemCount)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@
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
Expand All @@ -60,7 +62,9 @@
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) {
Expand Down Expand Up @@ -153,13 +157,7 @@
}

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
Expand Down Expand Up @@ -205,6 +203,30 @@
}
}

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

Check failure on line 218 in app/src/main/java/com/github/libretube/ui/fragments/SubscriptionsFragment.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 A multiline expression should start on a new line Raw Output: app/src/main/java/com/github/libretube/ui/fragments/SubscriptionsFragment.kt:218:43: error: A multiline expression should start on a new line (standard:multiline-expression-wrapping)
.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
Expand Down Expand Up @@ -332,9 +354,11 @@
DatabaseHelper.filterByStatusAndWatchPosition(it, hideWatched)
}

val sortedFeed = feed
val sorted = feed

Check failure on line 357 in app/src/main/java/com/github/libretube/ui/fragments/SubscriptionsFragment.kt

View workflow job for this annotation

GitHub Actions / Check Code Quality

[ktlint] reported by reviewdog 🐶 A multiline expression should start on a new line Raw Output: app/src/main/java/com/github/libretube/ui/fragments/SubscriptionsFragment.kt:357:22: error: A multiline expression should start on a new line (standard:multiline-expression-wrapping)
.sortedBySelectedOrder()
.toMutableList()
sortedFeed.clear()
sortedFeed.addAll(sorted)

// add an "all caught up item"
if (selectedSortOrder == 0) {
Expand All @@ -355,10 +379,9 @@
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)

Expand Down Expand Up @@ -401,6 +424,11 @@
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
Expand Down
Loading