Space list (#5320)

* feature(spaces) : introduce SpaceRoomList matrix api

* feature (space) : extract SpaceRoomItemView

* feature(spaces) : start introducing SpaceScreen

* feature (space) : iterate on space list (and space screen)

* feature (space) : add space cache and navigation to sub space/room

* feature (space) : display top bar title

* Code cleanup, remove dead code and fix compilation issue

* More compilation fixes.

* Update screenshots

* Fix test compilation issues.

* Introduce MatrixClient.rememberHideInvitesAvatar() extension to reduce code duplication.

* Add test on SpacePresenter

* Add test on SpaceRoomCache and fix implementation

* Iterate on SpaceRoomCache thanks to SpaceRoomCacheTest

* Add UT on SpaceListUpdateProcessor

* Fix quality issue.

* Add tests on RustSpaceRoomList

---------

Co-authored-by: ganfra <francoisg@matrix.org>
Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Benoit Marty 2025-09-11 17:29:15 +02:00 committed by GitHub
commit 3af4405ee3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
65 changed files with 1840 additions and 286 deletions

View file

@ -0,0 +1,49 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.test.spaces
import io.element.android.libraries.matrix.api.spaces.SpaceRoom
import io.element.android.libraries.matrix.api.spaces.SpaceRoomList
import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.simulateLongTask
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class FakeSpaceRoomList(
initialSpaceFlowValue: SpaceRoom? = null,
initialSpaceRoomsValue: List<SpaceRoom> = emptyList(),
initialSpaceRoomList: SpaceRoomList.PaginationStatus = SpaceRoomList.PaginationStatus.Loading,
private val paginateResult: () -> Result<Unit> = { lambdaError() },
) : SpaceRoomList {
private val currentSpaceMutableStateFlow: MutableStateFlow<SpaceRoom?> = MutableStateFlow(initialSpaceFlowValue)
override fun currentSpaceFlow(): Flow<SpaceRoom?> = currentSpaceMutableStateFlow.asStateFlow()
fun emitCurrentSpace(value: SpaceRoom?) {
currentSpaceMutableStateFlow.value = value
}
private val _spaceRoomsFlow: MutableStateFlow<List<SpaceRoom>> = MutableStateFlow(initialSpaceRoomsValue)
override val spaceRoomsFlow: Flow<List<SpaceRoom>> = _spaceRoomsFlow.asStateFlow()
fun emitSpaceRooms(value: List<SpaceRoom>) {
_spaceRoomsFlow.value = value
}
private val _paginationStatusFlow: MutableStateFlow<SpaceRoomList.PaginationStatus> = MutableStateFlow(initialSpaceRoomList)
override val paginationStatusFlow: StateFlow<SpaceRoomList.PaginationStatus> = _paginationStatusFlow.asStateFlow()
fun emitPaginationStatus(value: SpaceRoomList.PaginationStatus) {
_paginationStatusFlow.value = value
}
override suspend fun paginate(): Result<Unit> = simulateLongTask {
paginateResult()
}
}

View file

@ -7,7 +7,9 @@
package io.element.android.libraries.matrix.test.spaces
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.spaces.SpaceRoom
import io.element.android.libraries.matrix.api.spaces.SpaceRoomList
import io.element.android.libraries.matrix.api.spaces.SpaceService
import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.simulateLongTask
@ -16,17 +18,22 @@ import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow
class FakeSpaceService(
private val joinedSpacesResult: () -> Result<List<SpaceRoom>> = { lambdaError() }
private val joinedSpacesResult: () -> Result<List<SpaceRoom>> = { lambdaError() },
private val spaceRoomListResult: (RoomId) -> SpaceRoomList = { lambdaError() },
) : SpaceService {
private val _spaceRooms = MutableSharedFlow<List<SpaceRoom>>()
override val spaceRooms: SharedFlow<List<SpaceRoom>>
get() = _spaceRooms.asSharedFlow()
private val _spaceRoomsFlow = MutableSharedFlow<List<SpaceRoom>>()
override val spaceRoomsFlow: SharedFlow<List<SpaceRoom>>
get() = _spaceRoomsFlow.asSharedFlow()
suspend fun emitSpaceRoomList(value: List<SpaceRoom>) {
_spaceRooms.emit(value)
_spaceRoomsFlow.emit(value)
}
override suspend fun joinedSpaces(): Result<List<SpaceRoom>> = simulateLongTask {
return joinedSpacesResult()
}
override fun spaceRoomList(id: RoomId): SpaceRoomList {
return spaceRoomListResult(id)
}
}