better management of collapsing for room controllers

This commit is contained in:
Valere 2021-04-19 10:39:01 +02:00
parent 4d7aeff54a
commit 7921a81b8e
6 changed files with 177 additions and 35 deletions

View file

@ -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
}

View file

@ -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<T>
: 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?)
}

View file

@ -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

View file

@ -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<List<RoomSummary>>() {
) : CollapsableTypedEpoxyController<List<RoomSummary>>() {
var listener: RoomListListener? = null

View file

@ -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<RoomSummary>(
) : PagedListEpoxyController<RoomSummary> (
// 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<EpoxyModel<*>>) {
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(

View file

@ -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)
}
}