Make MatrixClient return a RoomPreview instance, not a RoomPreviewInfo one.

This commit is contained in:
Jorge Martín
2025-02-10 16:17:24 +01:00
committed by Jorge Martin Espinosa
parent 19fcd005fc
commit 311fbb84f7
11 changed files with 101 additions and 58 deletions

View File

@@ -77,9 +77,11 @@ class AcceptDeclineInvitePresenterTest {
val declineInviteFailure = lambdaRecorder { ->
Result.failure<Unit>(RuntimeException("Failed to leave room"))
}
val client = FakeMatrixClient().apply {
getRoomPreviewResults[A_ROOM_ID] = FakeRoomPreview(declineInviteResult = declineInviteFailure)
}
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
Result.success(FakeRoomPreview(declineInviteResult = declineInviteFailure))
}
)
val presenter = createAcceptDeclineInvitePresenter(client = client)
presenter.test {
val inviteData = anInviteData()
@@ -120,9 +122,11 @@ class AcceptDeclineInvitePresenterTest {
val declineInviteSuccess = lambdaRecorder { ->
Result.success(Unit)
}
val client = FakeMatrixClient().apply {
getRoomPreviewResults[A_ROOM_ID] = FakeRoomPreview(declineInviteResult = declineInviteSuccess)
}
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
Result.success(FakeRoomPreview(declineInviteResult = declineInviteSuccess))
}
)
val presenter = createAcceptDeclineInvitePresenter(
client = client,
notificationCleaner = fakeNotificationCleaner,

View File

@@ -104,10 +104,12 @@ class JoinRoomPresenter @AssistedInject constructor(
}
else -> {
value = ContentState.Loading
val result = matrixClient.getRoomPreviewInfo(roomIdOrAlias, serverNames)
val result = matrixClient.getRoomPreview(roomIdOrAlias, serverNames)
value = result.fold(
onSuccess = { previewInfo ->
previewInfo.toContentState()
onSuccess = { preview ->
preview.info.toContentState()
},
onFailure = { throwable ->
if (throwable is ClientException.MatrixApi && (throwable.kind == ErrorKind.NotFound || throwable.kind == ErrorKind.Forbidden)) {

View File

@@ -257,6 +257,19 @@ class JoinRoomPresenterTest {
fun `present - when room is banned, then join authorization is equal to IsBanned`() = runTest {
val roomSummary = aRoomSummary(currentUserMembership = CurrentUserMembership.BANNED, joinRule = JoinRule.Public)
val matrixClient = FakeMatrixClient().apply {
val matrixClient = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
Result.success(
aRoomPreview(
info = aRoomPreviewInfo(
roomId = A_ROOM_ID,
joinRule = JoinRule.Public,
currentUserMembership = CurrentUserMembership.BANNED,
),
)
)
}
).apply {
getRoomSummaryFlowLambda = { _ ->
flowOf(Optional.of(roomSummary))
}
@@ -504,19 +517,21 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewInfoResult = { _, _ ->
getRoomPreviewResult = { _, _ ->
Result.success(
aRoomPreviewInfo(
roomId = A_ROOM_ID,
canonicalAlias = RoomAlias("#alias:matrix.org"),
name = "Room name",
topic = "Room topic",
avatarUrl = "avatarUrl",
numberOfJoinedMembers = 2,
isSpace = false,
isHistoryWorldReadable = false,
joinRule = JoinRule.Public,
currentUserMembership = null,
aRoomPreview(
info = aRoomPreviewInfo(
roomId = A_ROOM_ID,
canonicalAlias = RoomAlias("#alias:matrix.org"),
name = "Room name",
topic = "Room topic",
avatarUrl = "avatarUrl",
numberOfJoinedMembers = 2,
isSpace = false,
isHistoryWorldReadable = false,
joinRule = JoinRule.Public,
currentUserMembership = null,
)
)
)
}
@@ -547,9 +562,9 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as Private`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewInfoResult = { _, _ ->
getRoomPreviewResult = { _, _ ->
Result.success(
aRoomPreviewInfo(joinRule = JoinRule.Private)
aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Private))
)
}
)
@@ -567,9 +582,9 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as Custom`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewInfoResult = { _, _ ->
getRoomPreviewResult = { _, _ ->
Result.success(
aRoomPreviewInfo(joinRule = JoinRule.Custom("custom"))
aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Custom("custom")))
)
}
)
@@ -587,9 +602,9 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as Invite`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewInfoResult = { _, _ ->
getRoomPreviewResult = { _, _ ->
Result.success(
aRoomPreviewInfo(joinRule = JoinRule.Invite)
aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Invite))
)
}
)
@@ -607,9 +622,9 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as KnockRestricted`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewInfoResult = { _, _ ->
getRoomPreviewResult = { _, _ ->
Result.success(
aRoomPreviewInfo(joinRule = JoinRule.KnockRestricted(emptyList()))
aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.KnockRestricted(emptyList())))
)
}
)
@@ -627,9 +642,9 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as Restricted`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewInfoResult = { _, _ ->
getRoomPreviewResult = { _, _ ->
Result.success(
aRoomPreviewInfo(joinRule = JoinRule.Restricted(emptyList()))
aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Restricted(emptyList())))
)
}
)
@@ -647,9 +662,9 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as Space`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewInfoResult = { _, _ ->
getRoomPreviewResult = { _, _ ->
Result.success(
aRoomPreviewInfo(isSpace = true)
aRoomPreview(info = aRoomPreviewInfo(isSpace = true))
)
}
)
@@ -667,7 +682,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded with error`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewInfoResult = { _, _ ->
getRoomPreviewResult = { _, _ ->
Result.failure(AN_EXCEPTION)
}
)
@@ -697,7 +712,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded with error Forbidden`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewInfoResult = { _, _ ->
getRoomPreviewResult = { _, _ ->
Result.failure(ClientException.MatrixApi(ErrorKind.Forbidden, "403", "Forbidden"))
}
)

View File

@@ -28,7 +28,6 @@ import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.RoomPreview
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
@@ -146,7 +145,11 @@ interface MatrixClient : Closeable {
* Execute generic GET requests through the SDKs internal HTTP client.
*/
suspend fun getUrl(url: String): Result<String>
suspend fun getRoomPreviewInfo(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomPreviewInfo>
/**
* Get a room preview for a given room ID or alias. This is especially useful for rooms that the user is not a member of, or hasn't joined yet.
*/
suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomPreview>
/**
* Returns the currently used sliding sync version.

View File

@@ -7,13 +7,13 @@
package io.element.android.libraries.matrix.api.room
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
/** A reference to a room either invited, knocked or banned. */
interface RoomPreview : AutoCloseable {
val sessionId: SessionId
val roomId: RoomId
val info: RoomPreviewInfo
/** Leave the room ie.decline invite or cancel knock. */
suspend fun leave(): Result<Unit>

View File

@@ -38,7 +38,6 @@ import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.RoomPreview
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
import io.element.android.libraries.matrix.api.roomlist.RoomListService
@@ -60,9 +59,9 @@ import io.element.android.libraries.matrix.impl.pushers.RustPushersService
import io.element.android.libraries.matrix.impl.room.RoomContentForwarder
import io.element.android.libraries.matrix.impl.room.RoomSyncSubscriber
import io.element.android.libraries.matrix.impl.room.RustRoomFactory
import io.element.android.libraries.matrix.impl.room.RustRoomPreview
import io.element.android.libraries.matrix.impl.room.TimelineEventTypeFilterFactory
import io.element.android.libraries.matrix.impl.room.join.map
import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewInfoMapper
import io.element.android.libraries.matrix.impl.roomdirectory.RustRoomDirectoryService
import io.element.android.libraries.matrix.impl.roomdirectory.map
import io.element.android.libraries.matrix.impl.roomlist.RoomListFactory
@@ -450,14 +449,13 @@ class RustMatrixClient(
}
}
override suspend fun getRoomPreviewInfo(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomPreviewInfo> = withContext(sessionDispatcher) {
override suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomPreview> = withContext(sessionDispatcher) {
runCatching {
when (roomIdOrAlias) {
val roomPreview = when (roomIdOrAlias) {
is RoomIdOrAlias.Alias -> innerClient.getRoomPreviewFromRoomAlias(roomIdOrAlias.roomAlias.value)
is RoomIdOrAlias.Id -> innerClient.getRoomPreviewFromRoomId(roomIdOrAlias.roomId.value, serverNames)
}.use { roomPreview ->
RoomPreviewInfoMapper.map(roomPreview.info())
}
RustRoomPreview(sessionId, roomPreview, roomMembershipObserver)
}.mapFailure { it.mapClientException() }
}

View File

@@ -145,7 +145,6 @@ class RustRoomFactory(
}
RustRoomPreview(
sessionId = sessionId,
roomId = roomId,
inner = innerRoom,
roomMembershipObserver = roomMembershipObserver,
)

View File

@@ -7,27 +7,33 @@
package io.element.android.libraries.matrix.impl.room
import io.element.android.libraries.matrix.api.core.RoomId
import androidx.compose.runtime.Immutable
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.room.RoomMembershipDetails
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.RoomPreview
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
import io.element.android.libraries.matrix.impl.room.preview.RoomPreviewInfoMapper
import org.matrix.rustcomponents.sdk.Membership
import org.matrix.rustcomponents.sdk.RoomPreview as InnerRoomPreview
@Immutable
class RustRoomPreview(
override val sessionId: SessionId,
override val roomId: RoomId,
private val inner: InnerRoomPreview,
private val roomMembershipObserver: RoomMembershipObserver,
private val roomMembershipObserver: RoomMembershipObserver?,
) : RoomPreview {
companion object {
val ALLOWED_MEMBERSHIPS = setOf(Membership.INVITED, Membership.KNOCKED, Membership.BANNED)
}
override val info: RoomPreviewInfo = RoomPreviewInfoMapper.map(inner.info())
override suspend fun leave(): Result<Unit> = runCatching {
inner.leave()
}.onSuccess {
roomMembershipObserver.notifyUserLeftRoom(roomId)
roomMembershipObserver?.notifyUserLeftRoom(info.roomId)
}
override suspend fun forget(): Result<Unit> = runCatching {

View File

@@ -26,7 +26,6 @@ import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.RoomPreview
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
import io.element.android.libraries.matrix.api.roomdirectory.RoomDirectoryService
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
@@ -79,7 +78,7 @@ class FakeMatrixClient(
Optional.of(ResolvedRoomAlias(A_ROOM_ID, emptyList()))
)
},
private val getRoomPreviewInfoResult: (RoomIdOrAlias, List<String>) -> Result<RoomPreviewInfo> = { _, _ -> Result.failure(AN_EXCEPTION) },
private val getRoomPreviewResult: (RoomIdOrAlias, List<String>) -> Result<RoomPreview> = { _, _ -> Result.failure(AN_EXCEPTION) },
private val clearCacheLambda: () -> Unit = { lambdaError() },
private val userIdServerNameLambda: () -> String = { lambdaError() },
private val getUrlLambda: (String) -> Result<String> = { lambdaError() },
@@ -105,7 +104,6 @@ class FakeMatrixClient(
private var createDmResult: Result<RoomId> = Result.success(A_ROOM_ID)
private var findDmResult: RoomId? = A_ROOM_ID
private val getRoomResults = mutableMapOf<RoomId, MatrixRoom>()
val getRoomPreviewResults = mutableMapOf<RoomId, RoomPreview>()
private val searchUserResults = mutableMapOf<String, Result<MatrixSearchUserResults>>()
private val getProfileResults = mutableMapOf<UserId, Result<MatrixUser>>()
private var uploadMediaResult: Result<String> = Result.success(AN_AVATAR_URL)
@@ -132,8 +130,8 @@ class FakeMatrixClient(
return getRoomResults[roomId]
}
override suspend fun getPendingRoom(roomId: RoomId): RoomPreview? {
return getRoomPreviewResults[roomId]
override suspend fun getPendingRoom(roomId: RoomId): RoomPreview? = simulateLongTask {
getRoomPreviewResult(RoomIdOrAlias.Id(roomId), emptyList()).getOrNull()
}
override suspend fun findDM(userId: UserId): RoomId? {
@@ -313,8 +311,8 @@ class FakeMatrixClient(
resolveRoomAliasResult(roomAlias)
}
override suspend fun getRoomPreviewInfo(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomPreviewInfo> = simulateLongTask {
getRoomPreviewInfoResult(roomIdOrAlias, serverNames)
override suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomPreview> = simulateLongTask {
getRoomPreviewResult(roomIdOrAlias, serverNames)
}
override suspend fun getRecentlyVisitedRooms(): Result<List<RoomId>> {

View File

@@ -7,17 +7,19 @@
package io.element.android.libraries.matrix.test.room
import io.element.android.libraries.matrix.api.core.RoomId
import androidx.compose.runtime.Immutable
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.room.RoomMembershipDetails
import io.element.android.libraries.matrix.api.room.RoomPreview
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.simulateLongTask
@Immutable
class FakeRoomPreview(
override val sessionId: SessionId = A_SESSION_ID,
override val roomId: RoomId = A_ROOM_ID,
override val info: RoomPreviewInfo = aRoomPreviewInfo(),
private val declineInviteResult: () -> Result<Unit> = { lambdaError() },
private val forgetRoomResult: () -> Result<Unit> = { lambdaError() },
) : RoomPreview {

View File

@@ -9,7 +9,9 @@ package io.element.android.libraries.matrix.test.room
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomMembershipDetails
import io.element.android.libraries.matrix.api.room.RoomType
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
@@ -17,6 +19,20 @@ import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_ROOM_NAME
import io.element.android.libraries.matrix.test.A_ROOM_TOPIC
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.tests.testutils.lambda.lambdaError
fun aRoomPreview(
sessionId: SessionId = A_SESSION_ID,
info: RoomPreviewInfo = aRoomPreviewInfo(),
declineInviteResult: () -> Result<Unit> = { lambdaError() },
forgetRoomResult: () -> Result<Unit> = { lambdaError() },
) = FakeRoomPreview(
sessionId = sessionId,
info = info,
declineInviteResult = declineInviteResult,
forgetRoomResult = forgetRoomResult,
)
fun aRoomPreviewInfo(
roomId: RoomId = A_ROOM_ID,