From 7921a81b8e17329da4fccdd27306043825784d1b Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 19 Apr 2021 10:39:01 +0200 Subject: [PATCH] better management of collapsing for room controllers --- .../list/CollapsableControllerExtension.kt | 32 +++++++ .../list/CollapsableTypedEpoxyController.kt | 83 +++++++++++++++++++ .../home/room/list/RoomListFragment.kt | 20 ++--- .../room/list/RoomSummaryListController.kt | 3 +- .../room/list/RoomSummaryPagedController.kt | 38 ++++----- .../list/RoomSummaryPagedControllerFactory.kt | 36 ++++++++ 6 files changed, 177 insertions(+), 35 deletions(-) create mode 100644 vector/src/main/java/im/vector/app/features/home/room/list/CollapsableControllerExtension.kt create mode 100644 vector/src/main/java/im/vector/app/features/home/room/list/CollapsableTypedEpoxyController.kt create mode 100644 vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/CollapsableControllerExtension.kt b/vector/src/main/java/im/vector/app/features/home/room/list/CollapsableControllerExtension.kt new file mode 100644 index 0000000000..bd622faae1 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/list/CollapsableControllerExtension.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.list + +import com.airbnb.epoxy.EpoxyController +import timber.log.Timber + +fun EpoxyController.setCollapsed(collapsed: Boolean) { + if (this is CollapsableControllerExtension) { + this.collapsed = collapsed + } else { + Timber.w("Try to collapse a controller that do not support collapse state") + } +} + +interface CollapsableControllerExtension { + var collapsed: Boolean +} diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/CollapsableTypedEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/CollapsableTypedEpoxyController.kt new file mode 100644 index 0000000000..19d718a3c7 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/list/CollapsableTypedEpoxyController.kt @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.list + +import com.airbnb.epoxy.EpoxyController + +abstract class CollapsableTypedEpoxyController + : EpoxyController(), CollapsableControllerExtension { + + private var currentData: T? = null + private var allowModelBuildRequests = false + + override var collapsed: Boolean = false + set(value) { + if (field != value) { + field = value + allowModelBuildRequests = true + requestModelBuild() + allowModelBuildRequests = false + } + } + + fun setData(data: T?) { + currentData = data + allowModelBuildRequests = true + requestModelBuild() + allowModelBuildRequests = false + } + + override fun requestModelBuild() { + check(allowModelBuildRequests) { + ("You cannot call `requestModelBuild` directly. Call `setData` instead to trigger a " + + "model refresh with new data.") + } + super.requestModelBuild() + } + + override fun moveModel(fromPosition: Int, toPosition: Int) { + allowModelBuildRequests = true + super.moveModel(fromPosition, toPosition) + allowModelBuildRequests = false + } + + override fun requestDelayedModelBuild(delayMs: Int) { + check(allowModelBuildRequests) { + ("You cannot call `requestModelBuild` directly. Call `setData` instead to trigger a " + + "model refresh with new data.") + } + super.requestDelayedModelBuild(delayMs) + } + + fun getCurrentData(): T? { + return currentData + } + + override fun buildModels() { + check(isBuildingModels()) { + ("You cannot call `buildModels` directly. Call `setData` instead to trigger a model " + + "refresh with new data.") + } + if (collapsed) { + buildModels(null) + } else { + buildModels(currentData) + } + } + + protected abstract fun buildModels(data: T?) +} diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt index 6147be462a..eb931f9e9c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt @@ -108,10 +108,10 @@ class RoomListFragment @Inject constructor( sharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java) roomListViewModel.observeViewEvents { when (it) { - is RoomListViewEvents.Loading -> showLoading(it.message) - is RoomListViewEvents.Failure -> showFailure(it.throwable) + is RoomListViewEvents.Loading -> showLoading(it.message) + is RoomListViewEvents.Failure -> showFailure(it.throwable) is RoomListViewEvents.SelectRoom -> handleSelectRoom(it) - is RoomListViewEvents.Done -> Unit + is RoomListViewEvents.Done -> Unit }.exhaustive } @@ -132,21 +132,15 @@ class RoomListFragment @Inject constructor( } private fun refreshCollapseStates() { - var contentInsertIndex = 1 roomListViewModel.sections.forEachIndexed { index, roomsSection -> val actualBlock = adapterInfosList[index] val isRoomSectionExpanded = roomsSection.isExpanded.value.orTrue() if (actualBlock.section.isExpanded && !isRoomSectionExpanded) { - // we have to remove the content adapter - concatAdapter?.removeAdapter(actualBlock.contentAdapter.adapter) + // mark controller as collapsed + actualBlock.contentAdapter.setCollapsed(true) } else if (!actualBlock.section.isExpanded && isRoomSectionExpanded) { - // we must add it back! - concatAdapter?.addAdapter(contentInsertIndex, actualBlock.contentAdapter.adapter) - } - contentInsertIndex = if (isRoomSectionExpanded) { - contentInsertIndex + 2 - } else { - contentInsertIndex + 1 + // we must expand! + actualBlock.contentAdapter.setCollapsed(false) } actualBlock.section = actualBlock.section.copy( isExpanded = isRoomSectionExpanded diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt index 330dffcced..75aaee45cb 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryListController.kt @@ -16,12 +16,11 @@ package im.vector.app.features.home.room.list -import com.airbnb.epoxy.TypedEpoxyController import org.matrix.android.sdk.api.session.room.model.RoomSummary class RoomSummaryListController( private val roomSummaryItemFactory: RoomSummaryItemFactory -) : TypedEpoxyController>() { +) : CollapsableTypedEpoxyController>() { var listener: RoomListListener? = null diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt index 57ee83141f..aae548c1e7 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedController.kt @@ -21,31 +21,13 @@ import com.airbnb.epoxy.paging.PagedListEpoxyController import im.vector.app.core.utils.createUIHandler import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.RoomSummary -import javax.inject.Inject - -class RoomSummaryPagedControllerFactory @Inject constructor( - private val roomSummaryItemFactory: RoomSummaryItemFactory -) { - - fun createRoomSummaryPagedController(): RoomSummaryPagedController { - return RoomSummaryPagedController(roomSummaryItemFactory) - } - - fun createRoomSummaryListController(): RoomSummaryListController { - return RoomSummaryListController(roomSummaryItemFactory) - } - - fun createSuggestedRoomListController(): SuggestedRoomListController { - return SuggestedRoomListController(roomSummaryItemFactory) - } -} class RoomSummaryPagedController( private val roomSummaryItemFactory: RoomSummaryItemFactory -) : PagedListEpoxyController( +) : PagedListEpoxyController ( // Important it must match the PageList builder notify Looper modelBuildingHandler = createUIHandler() -) { +), CollapsableControllerExtension { var listener: RoomListListener? = null @@ -56,6 +38,22 @@ class RoomSummaryPagedController( requestForcedModelBuild() } + override var collapsed = false + set(value) { + if (field != value) { + field = value + requestForcedModelBuild() + } + } + + override fun addModels(models: List>) { + if (collapsed) { + super.addModels(emptyList()) + } else { + super.addModels(models) + } + } + override fun buildItemModel(currentPosition: Int, item: RoomSummary?): EpoxyModel<*> { // for place holder if enabled item ?: return roomSummaryItemFactory.createRoomItem( diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt new file mode 100644 index 0000000000..c86d8ab243 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryPagedControllerFactory.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.home.room.list + +import javax.inject.Inject + +class RoomSummaryPagedControllerFactory @Inject constructor( + private val roomSummaryItemFactory: RoomSummaryItemFactory +) { + + fun createRoomSummaryPagedController(): RoomSummaryPagedController { + return RoomSummaryPagedController(roomSummaryItemFactory) + } + + fun createRoomSummaryListController(): RoomSummaryListController { + return RoomSummaryListController(roomSummaryItemFactory) + } + + fun createSuggestedRoomListController(): SuggestedRoomListController { + return SuggestedRoomListController(roomSummaryItemFactory) + } +}