From 64829dc198c499ba0ade26027d00dc52a60c8639 Mon Sep 17 00:00:00 2001 From: Nikita Date: Mon, 11 Mar 2024 21:36:27 +0300 Subject: [PATCH] fix: btnTop scroll didn't work in replies --- .../ui/fragments/CommentsMainFragment.kt | 27 +++++++++--- .../ui/fragments/CommentsRepliesFragment.kt | 43 ++++++++++++++++++- .../libretube/ui/models/CommentsViewModel.kt | 22 +++++++++- 3 files changed, 83 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/github/libretube/ui/fragments/CommentsMainFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/CommentsMainFragment.kt index e6e276e24..013f1637f 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/CommentsMainFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/CommentsMainFragment.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.ViewTreeObserver import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels @@ -25,6 +26,8 @@ class CommentsMainFragment : Fragment() { private val binding get() = _binding!! private val viewModel: CommentsViewModel by activityViewModels() + private var scrollListener: ViewTreeObserver.OnScrollChangedListener? = null + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -45,17 +48,19 @@ class CommentsMainFragment : Fragment() { val commentsSheet = parentFragment as? CommentsSheet commentsSheet?.binding?.btnScrollToTop?.setOnClickListener { // scroll back to the top / first comment - _binding?.commentsRV?.smoothScrollToPosition(0) - viewModel.currentCommentsPosition = 0 + _binding?.commentsRV?.smoothScrollToPosition(POSITION_START) + viewModel.setCommentsPosition(POSITION_START) } - binding.commentsRV.viewTreeObserver.addOnScrollChangedListener { + scrollListener = ViewTreeObserver.OnScrollChangedListener { // save the last scroll position to become used next time when the sheet is opened - viewModel.currentCommentsPosition = layoutManager.findFirstVisibleItemPosition() - + viewModel.setCommentsPosition(layoutManager.findFirstVisibleItemPosition()) // hide or show the scroll to top button - commentsSheet?.binding?.btnScrollToTop?.isVisible = viewModel.currentCommentsPosition != 0 + commentsSheet?.binding?.btnScrollToTop?.isVisible = + viewModel.currentCommentsPosition.value != 0 } + binding.commentsRV.viewTreeObserver.addOnScrollChangedListener(scrollListener) + commentsSheet?.updateFragmentInfo(false, getString(R.string.comments)) val commentPagingAdapter = CommentPagingAdapter( @@ -97,8 +102,18 @@ class CommentsMainFragment : Fragment() { } } + override fun onPause() { + super.onPause() + binding.commentsRV.viewTreeObserver.removeOnScrollChangedListener(scrollListener) + scrollListener = null + } + override fun onDestroyView() { super.onDestroyView() _binding = null } + + companion object { + private const val POSITION_START = 0 + } } diff --git a/app/src/main/java/com/github/libretube/ui/fragments/CommentsRepliesFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/CommentsRepliesFragment.kt index 32d9bf75c..03663c670 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/CommentsRepliesFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/CommentsRepliesFragment.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.ViewTreeObserver import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.view.updatePadding @@ -31,6 +32,8 @@ class CommentsRepliesFragment : Fragment() { private val viewModel: CommentsViewModel by activityViewModels() + private var scrollListener: ViewTreeObserver.OnScrollChangedListener? = null + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -66,9 +69,37 @@ class CommentsRepliesFragment : Fragment() { ) binding.commentsRV.updatePadding(top = 0) - binding.commentsRV.layoutManager = LinearLayoutManager(context) + + val layoutManager = LinearLayoutManager(context) + binding.commentsRV.layoutManager = layoutManager + binding.commentsRV.adapter = repliesAdapter + // init scroll position + if (viewModel.currentRepliesPosition.value != null) { + if (viewModel.currentRepliesPosition.value!! > POSITION_START) { + layoutManager.scrollToPosition(viewModel.currentRepliesPosition.value!!) + } else { + layoutManager.scrollToPosition(POSITION_START) + } + } + + commentsSheet?.binding?.btnScrollToTop?.setOnClickListener { + // scroll back to the top / first comment + layoutManager.scrollToPosition(POSITION_START) + viewModel.setRepliesPosition(POSITION_START) + } + + scrollListener = ViewTreeObserver.OnScrollChangedListener { + // save the last scroll position to become used next time when the sheet is opened + viewModel.setRepliesPosition(layoutManager.findFirstVisibleItemPosition()) + // hide or show the scroll to top button + commentsSheet?.binding?.btnScrollToTop?.isVisible = + viewModel.currentRepliesPosition.value != 0 + } + + binding.commentsRV.viewTreeObserver.addOnScrollChangedListener(scrollListener) + viewModel.selectedCommentLiveData.postValue(comment.repliesPage) viewLifecycleOwner.lifecycleScope.launch { @@ -88,8 +119,18 @@ class CommentsRepliesFragment : Fragment() { } } + override fun onPause() { + super.onPause() + binding.commentsRV.viewTreeObserver.removeOnScrollChangedListener(scrollListener) + scrollListener = null + } + override fun onDestroyView() { super.onDestroyView() _binding = null } + + companion object { + const val POSITION_START = 0 + } } diff --git a/app/src/main/java/com/github/libretube/ui/models/CommentsViewModel.kt b/app/src/main/java/com/github/libretube/ui/models/CommentsViewModel.kt index 1e5c23963..76308a2ea 100644 --- a/app/src/main/java/com/github/libretube/ui/models/CommentsViewModel.kt +++ b/app/src/main/java/com/github/libretube/ui/models/CommentsViewModel.kt @@ -1,5 +1,6 @@ package com.github.libretube.ui.models +import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.asFlow @@ -41,7 +42,12 @@ class CommentsViewModel : ViewModel() { var channelAvatar: String? = null var handleLink: ((url: String) -> Unit)? = null - var currentCommentsPosition = 0 + private val _currentCommentsPosition = MutableLiveData(0) + val currentCommentsPosition: LiveData = _currentCommentsPosition + + private val _currentRepliesPosition = MutableLiveData(0) + val currentRepliesPosition: LiveData = _currentRepliesPosition + var commentsSheetDismiss: (() -> Unit)? = null fun setCommentSheetExpand(value: Boolean?) { @@ -52,6 +58,18 @@ class CommentsViewModel : ViewModel() { fun reset() { setCommentSheetExpand(null) - currentCommentsPosition = 0 + _currentCommentsPosition.value = 0 + } + + fun setCommentsPosition(position: Int) { + if (position != currentCommentsPosition.value) { + _currentCommentsPosition.postValue(position) + } + } + + fun setRepliesPosition(position: Int) { + if (position != currentRepliesPosition.value) { + _currentRepliesPosition.postValue(position) + } } }