From e21f9443d551fbc2c787a67e5745c695b380b9b7 Mon Sep 17 00:00:00 2001 From: SpiritCroc Date: Thu, 31 Mar 2022 09:12:28 +0200 Subject: [PATCH] ViewPager: never react to own space-changes Change-Id: I45a1fd1e9ec6048dffdc4d54e8022d53afc627ff --- .../java/im/vector/app/AppStateHandler.kt | 34 ++++++++++++------- .../app/features/home/HomeDetailFragment.kt | 14 ++------ .../app/features/home/HomeDetailViewModel.kt | 6 ++++ .../app/features/home/HomeDetailViewState.kt | 1 + 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/vector/src/main/java/im/vector/app/AppStateHandler.kt b/vector/src/main/java/im/vector/app/AppStateHandler.kt index 1ff3d97576..b38ae10ad0 100644 --- a/vector/src/main/java/im/vector/app/AppStateHandler.kt +++ b/vector/src/main/java/im/vector/app/AppStateHandler.kt @@ -19,6 +19,7 @@ package im.vector.app import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import arrow.core.Option +import arrow.core.getOrElse import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.utils.BehaviorDataSource import im.vector.app.features.session.coroutineScope @@ -28,7 +29,9 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancelChildren import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import org.matrix.android.sdk.api.extensions.tryOrNull @@ -59,16 +62,21 @@ class AppStateHandler @Inject constructor( ) : DefaultLifecycleObserver { private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main) - private val selectedSpaceDataSource = BehaviorDataSource>(Option.empty()) + ///private val selectedSpaceDataSource = BehaviorDataSource>(Option.empty()) - val selectedRoomGroupingFlow = selectedSpaceDataSource.stream() + // SchildiChat: the boolean means pendingSwipe and defaults to false. Set to true for swiping spaces, so you want to ignore updates which have pendingSwipe = true. + // Call it different then the upstream one so we don't forget adding `first` to upstream's logic. + private val selectedSpaceDataSourceSc = BehaviorDataSource>>(Option.empty()) + + val selectedRoomGroupingFlow = selectedSpaceDataSourceSc.stream().map { it.map { it.first } } + val selectedRoomGroupingFlowIgnoreSwipe = selectedSpaceDataSourceSc.stream().filter { it.getOrElse{ null }?.second != true }.map { it.map { it.first } } fun getCurrentRoomGroupingMethod(): RoomGroupingMethod? { // XXX we should somehow make it live :/ just a work around // For example just after creating a space and switching to it the // name in the app Bar could show Empty Room, and it will not update unless you // switch space - return selectedSpaceDataSource.currentValue?.orNull()?.let { + return selectedSpaceDataSourceSc.currentValue?.orNull()?.first?.let { if (it is RoomGroupingMethod.BySpace) { // try to refresh sum? it.spaceSummary?.roomId?.let { activeSessionHolder.getSafeActiveSession()?.getRoomSummary(it) }?.let { @@ -78,10 +86,10 @@ class AppStateHandler @Inject constructor( } } - fun setCurrentSpace(spaceId: String?, session: Session? = null, persistNow: Boolean = false) { + fun setCurrentSpace(spaceId: String?, session: Session? = null, persistNow: Boolean = false, pendingSwipe: Boolean = false) { val uSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return - if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.BySpace && - spaceId == selectedSpaceDataSource.currentValue?.orNull()?.space()?.roomId) return + if (selectedSpaceDataSourceSc.currentValue?.orNull()?.first is RoomGroupingMethod.BySpace && + spaceId == selectedSpaceDataSourceSc.currentValue?.orNull()?.first?.space()?.roomId) return val spaceSum = spaceId?.let { uSession.getRoomSummary(spaceId) } if (persistNow) { @@ -89,7 +97,7 @@ class AppStateHandler @Inject constructor( uiStateRepository.storeSelectedSpace(spaceSum?.roomId, uSession.sessionId) } - selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.BySpace(spaceSum))) + selectedSpaceDataSourceSc.post(Option.just(Pair(RoomGroupingMethod.BySpace(spaceSum), pendingSwipe))) if (spaceId != null) { uSession.coroutineScope.launch(Dispatchers.IO) { tryOrNull { @@ -101,10 +109,10 @@ class AppStateHandler @Inject constructor( fun setCurrentGroup(groupId: String?, session: Session? = null) { val uSession = session ?: activeSessionHolder.getSafeActiveSession() ?: return - if (selectedSpaceDataSource.currentValue?.orNull() is RoomGroupingMethod.ByLegacyGroup && - groupId == selectedSpaceDataSource.currentValue?.orNull()?.group()?.groupId) return + if (selectedSpaceDataSourceSc.currentValue?.orNull()?.first is RoomGroupingMethod.ByLegacyGroup && + groupId == selectedSpaceDataSourceSc.currentValue?.orNull()?.first?.group()?.groupId) return val activeGroup = groupId?.let { uSession.getGroupSummary(groupId) } - selectedSpaceDataSource.post(Option.just(RoomGroupingMethod.ByLegacyGroup(activeGroup))) + selectedSpaceDataSourceSc.post(Option.just(Pair(RoomGroupingMethod.ByLegacyGroup(activeGroup), false))) if (groupId != null) { uSession.coroutineScope.launch { tryOrNull { @@ -131,11 +139,11 @@ class AppStateHandler @Inject constructor( } fun safeActiveSpaceId(): String? { - return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.BySpace)?.spaceSummary?.roomId + return (selectedSpaceDataSourceSc.currentValue?.orNull()?.first as? RoomGroupingMethod.BySpace)?.spaceSummary?.roomId } fun safeActiveGroupId(): String? { - return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId + return (selectedSpaceDataSourceSc.currentValue?.orNull()?.first as? RoomGroupingMethod.ByLegacyGroup)?.groupSummary?.groupId } override fun onResume(owner: LifecycleOwner) { @@ -145,7 +153,7 @@ class AppStateHandler @Inject constructor( override fun onPause(owner: LifecycleOwner) { coroutineScope.coroutineContext.cancelChildren() val session = activeSessionHolder.getSafeActiveSession() ?: return - when (val currentMethod = selectedSpaceDataSource.currentValue?.orNull() ?: RoomGroupingMethod.BySpace(null)) { + when (val currentMethod = selectedSpaceDataSourceSc.currentValue?.orNull()?.first ?: RoomGroupingMethod.BySpace(null)) { is RoomGroupingMethod.BySpace -> { uiStateRepository.storeGroupingMethod(true, session.sessionId) uiStateRepository.storeSelectedSpace(currentMethod.spaceSummary?.roomId, session.sessionId) diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt index 3c64f6007e..f53c657856 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt @@ -105,7 +105,6 @@ class HomeDetailFragment @Inject constructor( private var pagerSpaces: List? = null private var pagerTab: HomeTab? = null private var pagerPagingEnabled: Boolean = false - private val pendingSpaceIds = mutableListOf() override fun getMenuRes() = R.menu.room_list @@ -163,8 +162,7 @@ class HomeDetailFragment @Inject constructor( } } val selectedId = getSpaceIdForPageIndex(position) - pendingSpaceIds.add(selectedId) - appStateHandler.setCurrentSpace(selectedId) + appStateHandler.setCurrentSpace(selectedId, pendingSwipe = true) } }) @@ -225,7 +223,7 @@ class HomeDetailFragment @Inject constructor( ) } - viewModel.onEach(HomeDetailViewState::roomGroupingMethod, HomeDetailViewState::rootSpacesOrdered, HomeDetailViewState::currentTab) { roomGroupingMethod, rootSpacesOrdered, currentTab -> + viewModel.onEach(HomeDetailViewState::roomGroupingMethodIgnoreSwipe, HomeDetailViewState::rootSpacesOrdered, HomeDetailViewState::currentTab) { roomGroupingMethod, rootSpacesOrdered, currentTab -> setupViewPager(roomGroupingMethod, rootSpacesOrdered, currentTab) } @@ -529,13 +527,6 @@ class HomeDetailFragment @Inject constructor( if (!changed) { if (pagingEnabled) { // No need to re-setup pager, just check for selected page - // Discard state changes that we created ourselves by swiping on the pager - while (pendingSpaceIds.size > 0) { - val pendingSpaceId = pendingSpaceIds.removeAt(0) - if (pendingSpaceId == selectedSpaceId) { - return - } - } if (selectedIndex != null) { if (selectedIndex != views.roomListContainerPager.currentItem) { // post() mitigates a case where we could end up in an endless loop circling around the same few spaces @@ -566,7 +557,6 @@ class HomeDetailFragment @Inject constructor( pagerTab = tab pagerPagingEnabled = pagingEnabled initialPageSelected = false - pendingSpaceIds.clear() // OFFSCREEN_PAGE_LIMIT_DEFAULT: default recyclerview caching mechanism instead of explicit fixed prefetching //views.roomListContainerPager.offscreenPageLimit = 2 diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt index 5ae579edee..e072f6d2f5 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt @@ -212,6 +212,12 @@ class HomeDetailViewModel @AssistedInject constructor( roomGroupingMethod = it.orNull() ?: RoomGroupingMethod.BySpace(null) ) } + appStateHandler.selectedRoomGroupingFlowIgnoreSwipe + .setOnEach { + copy( + roomGroupingMethodIgnoreSwipe = it.orNull() ?: RoomGroupingMethod.BySpace(null) + ) + } } private fun observeRoomSummaries() { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt index 614f52de7a..cc6ad37a71 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewState.kt @@ -29,6 +29,7 @@ import org.matrix.android.sdk.api.util.MatrixItem data class HomeDetailViewState( val roomGroupingMethod: RoomGroupingMethod = RoomGroupingMethod.BySpace(null), + val roomGroupingMethodIgnoreSwipe: RoomGroupingMethod = RoomGroupingMethod.BySpace(null), val myMatrixItem: MatrixItem? = null, val asyncRooms: Async> = Uninitialized, val currentTab: HomeTab = HomeTab.RoomList(RoomListDisplayMode.ALL),