From 479b63ca20ed09b32be8948a5726a197f214d14a Mon Sep 17 00:00:00 2001 From: jacquarg Date: Mon, 4 Mar 2024 12:03:42 +0100 Subject: [PATCH 1/2] 1829: fix scroll behaviour in Manage trackers page. --- .../features/trackers/TrackersFragment.kt | 29 +++------- .../trackers/TrackersPeriodFragment.kt | 54 ++++++++----------- .../trackers/TrackersPeriodViewModel.kt | 9 ++++ .../features/trackers/TrackersViewModel.kt | 4 ++ 4 files changed, 42 insertions(+), 54 deletions(-) diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt index 7663c4d8..7d5d157f 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt @@ -28,7 +28,6 @@ import android.text.style.ClickableSpan import android.text.style.ForegroundColorSpan import android.text.style.UnderlineSpan import android.view.View -import android.view.ViewTreeObserver import android.widget.Toast import androidx.core.content.ContextCompat import androidx.lifecycle.Lifecycle @@ -42,12 +41,12 @@ import foundation.e.advancedprivacy.common.NavToolbarFragment import foundation.e.advancedprivacy.common.extensions.findViewHolderForAdapterPosition import foundation.e.advancedprivacy.common.extensions.updatePagerHeightForChild import foundation.e.advancedprivacy.databinding.FragmentTrackersBinding +import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.launch import org.koin.androidx.viewmodel.ext.android.viewModel class TrackersFragment : NavToolbarFragment(R.layout.fragment_trackers) { private val viewModel: TrackersViewModel by viewModel() - private lateinit var binding: FragmentTrackersBinding private lateinit var pagerAdapter: TrackersPeriodAdapter @@ -72,7 +71,6 @@ class TrackersFragment : NavToolbarFragment(R.layout.fragment_trackers) { override fun onPageScrollStateChanged(state: Int) { super.onPageScrollStateChanged(state) if (state == ViewPager2.SCROLL_STATE_IDLE) { - updatePagerHeight() viewModel.onDisplayedItemChanged(binding.trackersPeriodsPager.currentItem) } } @@ -88,6 +86,10 @@ class TrackersFragment : NavToolbarFragment(R.layout.fragment_trackers) { } } + fun refreshUiHeight(): SharedFlow { + return viewModel.refreshUiHeigth + } + private fun listenViewModel() { with(viewLifecycleOwner) { lifecycleScope.launch { @@ -156,32 +158,13 @@ class TrackersFragment : NavToolbarFragment(R.layout.fragment_trackers) { } } - private var oldPosition = -1 - private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener { + fun updatePagerHeight() { binding.trackersPeriodsPager.findViewHolderForAdapterPosition(binding.trackersPeriodsPager.currentItem) .let { currentViewHolder -> currentViewHolder?.itemView?.let { binding.trackersPeriodsPager.updatePagerHeightForChild(it) } } } - private fun updatePagerHeight() { - with(binding.trackersPeriodsPager) { - val position = currentItem - if (position == oldPosition) return - if (oldPosition >= 0) { - val oldItem = findViewHolderForAdapterPosition(oldPosition)?.itemView - oldItem?.viewTreeObserver?.removeOnGlobalLayoutListener(layoutListener) - } - - val newItem = findViewHolderForAdapterPosition(position)?.itemView - newItem?.viewTreeObserver?.addOnGlobalLayoutListener(layoutListener) - - oldPosition = position - - binding.trackersPeriodsPager.requestLayout() - } - } - private fun displayToast(message: String) { Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() } diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodFragment.kt index 995bda36..f051407d 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodFragment.kt @@ -23,7 +23,6 @@ import android.content.ActivityNotFoundException import android.content.Intent import android.os.Bundle import android.view.View -import android.view.ViewTreeObserver import android.widget.Toast import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle @@ -38,6 +37,9 @@ import foundation.e.advancedprivacy.common.extensions.updatePagerHeightForChild import foundation.e.advancedprivacy.databinding.TrackersPeriodFragmentBinding import foundation.e.advancedprivacy.features.trackers.TrackersPeriodViewModel.SingleEvent import foundation.e.advancedprivacy.features.trackers.graph.GraphHolder +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.merge import kotlinx.coroutines.launch import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.core.parameter.parametersOf @@ -62,6 +64,9 @@ class TrackersPeriodFragment : Fragment(R.layout.trackers_period_fragment) { ) } + private val trackersFragment: TrackersFragment? + get() = parentFragment as? TrackersFragment? + private lateinit var binding: TrackersPeriodFragmentBinding private lateinit var tabAdapter: ListsTabPagerAdapter @@ -90,7 +95,7 @@ class TrackersPeriodFragment : Fragment(R.layout.trackers_period_fragment) { override fun onPageScrollStateChanged(state: Int) { super.onPageScrollStateChanged(state) if (state == ViewPager2.SCROLL_STATE_IDLE) { - updatePagerHeight() + viewModel.onDisplayedItemChanged() } } }) @@ -98,6 +103,7 @@ class TrackersPeriodFragment : Fragment(R.layout.trackers_period_fragment) { listenViewModel() } + @OptIn(FlowPreview::class) private fun listenViewModel() { with(viewLifecycleOwner) { lifecycleScope.launch { @@ -113,6 +119,19 @@ class TrackersPeriodFragment : Fragment(R.layout.trackers_period_fragment) { } } + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + trackersFragment?.refreshUiHeight()?.let { parentFlow -> + merge( + parentFlow, + viewModel.refreshUiHeight + ) + .debounce(50) + .collect { updatePagerHeight() } + } + } + } + lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.navigate.collect(findNavController()::navigate) @@ -146,29 +165,13 @@ class TrackersPeriodFragment : Fragment(R.layout.trackers_period_fragment) { } } - private var oldPosition = -1 - private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener { + private fun updatePagerHeight() { binding.listsPager.findViewHolderForAdapterPosition(binding.listsPager.currentItem) .let { currentViewHolder -> currentViewHolder?.itemView?.let { binding.listsPager.updatePagerHeightForChild(it) } } - } - - private fun updatePagerHeight() { - with(binding.listsPager) { - val position = currentItem - if (position == oldPosition) return - if (oldPosition >= 0) { - val oldItem = findViewHolderForAdapterPosition(oldPosition)?.itemView - oldItem?.viewTreeObserver?.removeOnGlobalLayoutListener(layoutListener) - } - val newItem = findViewHolderForAdapterPosition(position)?.itemView - newItem?.viewTreeObserver?.addOnGlobalLayoutListener(layoutListener) - - oldPosition = position - binding.listsPager.requestLayout() - } + trackersFragment?.updatePagerHeight() } private fun displayToast(message: String) { @@ -179,16 +182,5 @@ class TrackersPeriodFragment : Fragment(R.layout.trackers_period_fragment) { private fun render(state: TrackersPeriodState) { graphHolder.onBind(state) tabAdapter.updateDataSet(state) - updatePagerHeight() - } - - override fun onDestroyView() { - super.onDestroyView() - kotlin.runCatching { - if (oldPosition >= 0) { - val oldItem = binding.listsPager.findViewHolderForAdapterPosition(oldPosition) - oldItem?.itemView?.viewTreeObserver?.removeOnGlobalLayoutListener(layoutListener) - } - } } } diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodViewModel.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodViewModel.kt index 8b3887e3..b708b0b0 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodViewModel.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersPeriodViewModel.kt @@ -57,6 +57,9 @@ class TrackersPeriodViewModel( private val _singleEvents = MutableSharedFlow() val singleEvents = _singleEvents.asSharedFlow() + private val _refreshUiHeight = MutableSharedFlow() + val refreshUiHeight = _refreshUiHeight.asSharedFlow() + private val _navigate = MutableSharedFlow() val navigate = _navigate.asSharedFlow() @@ -82,6 +85,7 @@ class TrackersPeriodViewModel( appsWithTrackers = lists.appsWithTrackers ) } + _refreshUiHeight.emit(Unit) } } } @@ -96,6 +100,11 @@ class TrackersPeriodViewModel( fun onToggleHideNoTrackersApps() = viewModelScope.launch { _state.update { it.copy(hideNoTrackersApps = !it.hideNoTrackersApps) } + _refreshUiHeight.emit(Unit) + } + + fun onDisplayedItemChanged() = viewModelScope.launch { + _refreshUiHeight.emit(Unit) } sealed class SingleEvent { diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt index d9b7b8b7..b1d13efe 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt @@ -36,6 +36,9 @@ class TrackersViewModel(private val trackersScreenUseCase: TrackersScreenUseCase private val _navigate = MutableSharedFlow() val navigate = _navigate.asSharedFlow() + private val _refreshUiHeigth = MutableSharedFlow() + val refreshUiHeigth = _refreshUiHeigth.asSharedFlow() + val positionsCount = 3 fun getPeriod(position: Int): Period { return when (position) { @@ -65,6 +68,7 @@ class TrackersViewModel(private val trackersScreenUseCase: TrackersScreenUseCase fun onDisplayedItemChanged(position: Int) = viewModelScope.launch(Dispatchers.IO) { trackersScreenUseCase.savePosition(position) + _refreshUiHeigth.emit(Unit) } fun onClickLearnMore() = viewModelScope.launch { -- GitLab From 79e35c9473a1d3002883c431ac79c56699344876 Mon Sep 17 00:00:00 2001 From: jacquarg Date: Mon, 4 Mar 2024 17:09:16 +0100 Subject: [PATCH 2/2] 1829: MR feedback, fix typo. --- .../e/advancedprivacy/features/trackers/TrackersFragment.kt | 2 +- .../advancedprivacy/features/trackers/TrackersViewModel.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt index 7d5d157f..6518de1f 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersFragment.kt @@ -87,7 +87,7 @@ class TrackersFragment : NavToolbarFragment(R.layout.fragment_trackers) { } fun refreshUiHeight(): SharedFlow { - return viewModel.refreshUiHeigth + return viewModel.refreshUiHeight } private fun listenViewModel() { diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt index b1d13efe..945789e4 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/trackers/TrackersViewModel.kt @@ -36,8 +36,8 @@ class TrackersViewModel(private val trackersScreenUseCase: TrackersScreenUseCase private val _navigate = MutableSharedFlow() val navigate = _navigate.asSharedFlow() - private val _refreshUiHeigth = MutableSharedFlow() - val refreshUiHeigth = _refreshUiHeigth.asSharedFlow() + private val _refreshUiHeight = MutableSharedFlow() + val refreshUiHeight = _refreshUiHeight.asSharedFlow() val positionsCount = 3 fun getPeriod(position: Int): Period { @@ -68,7 +68,7 @@ class TrackersViewModel(private val trackersScreenUseCase: TrackersScreenUseCase fun onDisplayedItemChanged(position: Int) = viewModelScope.launch(Dispatchers.IO) { trackersScreenUseCase.savePosition(position) - _refreshUiHeigth.emit(Unit) + _refreshUiHeight.emit(Unit) } fun onClickLearnMore() = viewModelScope.launch { -- GitLab