Join Room : makes sure we can join by alias
This commit is contained in:
parent
a888b4d43c
commit
aebcc52309
16 changed files with 158 additions and 77 deletions
|
|
@ -24,7 +24,9 @@ import io.element.android.libraries.matrix.api.MatrixClient
|
|||
import io.element.android.libraries.matrix.api.core.ProgressCallback
|
||||
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.RoomIdOrAlias
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
|
||||
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
|
||||
import io.element.android.libraries.matrix.api.createroom.RoomPreset
|
||||
import io.element.android.libraries.matrix.api.createroom.RoomVisibility
|
||||
|
|
@ -41,6 +43,7 @@ import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
|||
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
|
||||
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
|
||||
import io.element.android.libraries.matrix.api.sync.SyncService
|
||||
import io.element.android.libraries.matrix.api.sync.SyncState
|
||||
import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
|
||||
|
|
@ -175,7 +178,7 @@ class RustMatrixClient(
|
|||
val (anonymizedAccessToken, anonymizedRefreshToken) = existingData.anonymizedTokens()
|
||||
clientLog.d(
|
||||
"Removing session data with access token '$anonymizedAccessToken' " +
|
||||
"and refresh token '$anonymizedRefreshToken'."
|
||||
"and refresh token '$anonymizedRefreshToken'."
|
||||
)
|
||||
if (existingData != null) {
|
||||
// Set isTokenValid to false
|
||||
|
|
@ -320,16 +323,23 @@ class RustMatrixClient(
|
|||
|
||||
/**
|
||||
* Wait for the room to be available in the room list.
|
||||
* @param roomId the room id to wait for
|
||||
* @param roomIdOrAlias the room id or alias to wait for
|
||||
* @param timeout the timeout to wait for the room to be available
|
||||
* @throws TimeoutCancellationException if the room is not available after the timeout
|
||||
*/
|
||||
private suspend fun awaitRoom(roomId: RoomId, timeout: Duration) {
|
||||
withTimeout(timeout) {
|
||||
private suspend fun awaitRoom(roomIdOrAlias: RoomIdOrAlias, timeout: Duration): RoomSummary {
|
||||
val predicate: (List<RoomSummary>) -> Boolean = when (roomIdOrAlias) {
|
||||
is RoomIdOrAlias.Alias -> { roomSummaries: List<RoomSummary> ->
|
||||
roomSummaries.flatMap { it.aliases }.contains(roomIdOrAlias.roomAlias)
|
||||
}
|
||||
is RoomIdOrAlias.Id -> { roomSummaries: List<RoomSummary> ->
|
||||
roomSummaries.map { it.roomId }.contains(roomIdOrAlias.roomId)
|
||||
}
|
||||
}
|
||||
return withTimeout(timeout) {
|
||||
roomListService.allRooms.summaries
|
||||
.filter { roomSummaries ->
|
||||
roomSummaries.map { it.roomId }.contains(roomId)
|
||||
}
|
||||
.filter(predicate)
|
||||
.first()
|
||||
.first()
|
||||
}
|
||||
}
|
||||
|
|
@ -373,7 +383,7 @@ class RustMatrixClient(
|
|||
val roomId = RoomId(client.createRoom(rustParams))
|
||||
// Wait to receive the room back from the sync but do not returns failure if it fails.
|
||||
try {
|
||||
awaitRoom(roomId, 30.seconds)
|
||||
awaitRoom(roomId.toRoomIdOrAlias(), 30.seconds)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Timeout waiting for the room to be available in the room list")
|
||||
}
|
||||
|
|
@ -424,30 +434,29 @@ class RustMatrixClient(
|
|||
runCatching { client.removeAvatar() }
|
||||
}
|
||||
|
||||
override suspend fun joinRoom(roomId: RoomId): Result<Unit> = withContext(sessionDispatcher) {
|
||||
override suspend fun joinRoom(roomId: RoomId): Result<RoomSummary?> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
client.joinRoomById(roomId.value).destroy()
|
||||
try {
|
||||
awaitRoom(roomId, 10.seconds)
|
||||
awaitRoom(roomId.toRoomIdOrAlias(), 10.seconds)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Timeout waiting for the room to be available in the room list")
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun joinRoomByIdOrAlias(
|
||||
roomId: RoomId,
|
||||
serverNames: List<String>,
|
||||
): Result<Unit> = withContext(sessionDispatcher) {
|
||||
override suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomSummary?> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
client.joinRoomByIdOrAlias(
|
||||
roomIdOrAlias = roomId.value,
|
||||
roomIdOrAlias = roomIdOrAlias.identifier,
|
||||
serverNames = serverNames,
|
||||
).destroy()
|
||||
try {
|
||||
awaitRoom(roomId, 10.seconds)
|
||||
awaitRoom(roomIdOrAlias, 10.seconds)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Timeout waiting for the room to be available in the room list")
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -478,12 +487,12 @@ class RustMatrixClient(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getRoomPreviewFromRoomId(roomId: RoomId, serverNames: List<String>): Result<RoomPreview> = withContext(sessionDispatcher) {
|
||||
override suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomPreview> = withContext(sessionDispatcher) {
|
||||
runCatching {
|
||||
client.getRoomPreviewFromRoomId(
|
||||
roomId = roomId.value,
|
||||
viaServers = serverNames,
|
||||
).let(RoomPreviewMapper::map)
|
||||
when (roomIdOrAlias) {
|
||||
is RoomIdOrAlias.Alias -> client.getRoomPreviewFromRoomAlias(roomIdOrAlias.roomAlias.value)
|
||||
is RoomIdOrAlias.Id -> client.getRoomPreviewFromRoomId(roomIdOrAlias.roomId.value, serverNames)
|
||||
}.let(RoomPreviewMapper::map)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -581,7 +590,7 @@ class RustMatrixClient(
|
|||
var room = getRoom(roomId)
|
||||
if (room == null) {
|
||||
emit(Optional.empty())
|
||||
awaitRoom(roomId, INFINITE)
|
||||
awaitRoom(roomId.toRoomIdOrAlias(), INFINITE)
|
||||
room = getRoom(roomId)
|
||||
}
|
||||
room?.use {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ import com.squareup.anvil.annotations.ContributesBinding
|
|||
import im.vector.app.features.analytics.plan.JoinedRoom
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||
import io.element.android.libraries.matrix.api.room.join.JoinRoom
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
||||
import io.element.android.libraries.matrix.impl.analytics.toAnalyticsJoinedRoom
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import javax.inject.Inject
|
||||
|
|
@ -32,18 +33,30 @@ class DefaultJoinRoom @Inject constructor(
|
|||
private val analyticsService: AnalyticsService,
|
||||
) : JoinRoom {
|
||||
override suspend fun invoke(
|
||||
roomId: RoomId,
|
||||
roomIdOrAlias: RoomIdOrAlias,
|
||||
serverNames: List<String>,
|
||||
trigger: JoinedRoom.Trigger,
|
||||
trigger: JoinedRoom.Trigger
|
||||
): Result<Unit> {
|
||||
return if (serverNames.isEmpty()) {
|
||||
client.joinRoom(roomId)
|
||||
} else {
|
||||
client.joinRoomByIdOrAlias(roomId, serverNames)
|
||||
}.onSuccess {
|
||||
client.getRoom(roomId)?.use { room ->
|
||||
analyticsService.capture(room.toAnalyticsJoinedRoom(trigger))
|
||||
return when (roomIdOrAlias) {
|
||||
is RoomIdOrAlias.Id -> {
|
||||
if (serverNames.isEmpty()) {
|
||||
client.joinRoom(roomIdOrAlias.roomId)
|
||||
} else {
|
||||
client.joinRoomByIdOrAlias(roomIdOrAlias, serverNames)
|
||||
}
|
||||
}
|
||||
is RoomIdOrAlias.Alias -> {
|
||||
client.joinRoomByIdOrAlias(roomIdOrAlias, serverNames = emptyList())
|
||||
}
|
||||
}.onSuccess { roomSummary ->
|
||||
client.captureJoinedRoomAnalytics(roomSummary, trigger)
|
||||
}.map { }
|
||||
}
|
||||
|
||||
private suspend fun MatrixClient.captureJoinedRoomAnalytics(roomSummary: RoomSummary?, trigger: JoinedRoom.Trigger) {
|
||||
if (roomSummary == null) return
|
||||
getRoom(roomSummary.roomId)?.use { room ->
|
||||
analyticsService.capture(room.toAnalyticsJoinedRoom(trigger))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto
|
|||
roomId = RoomId(roomInfo.id),
|
||||
name = roomInfo.displayName,
|
||||
canonicalAlias = roomInfo.canonicalAlias?.let(::RoomAlias),
|
||||
alternativeAliases = roomInfo.alternativeAliases.map(::RoomAlias),
|
||||
isDirect = roomInfo.isDirect,
|
||||
avatarUrl = roomInfo.avatarUrl,
|
||||
numUnreadMentions = roomInfo.numUnreadMentions.toInt(),
|
||||
|
|
|
|||
|
|
@ -20,11 +20,15 @@ import com.google.common.truth.Truth.assertThat
|
|||
import im.vector.app.features.analytics.plan.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
|
||||
import io.element.android.libraries.matrix.impl.analytics.toAnalyticsJoinedRoom
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_SERVER_LIST
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
|
|
@ -33,9 +37,10 @@ import org.junit.Test
|
|||
|
||||
class DefaultJoinRoomTest {
|
||||
@Test
|
||||
fun `when there is no server names, the classic join room API is used`() = runTest {
|
||||
val joinRoomLambda = lambdaRecorder { _: RoomId -> Result.success(Unit) }
|
||||
val joinRoomByIdOrAliasLambda = lambdaRecorder { _: RoomId, _: List<String> -> Result.success(Unit) }
|
||||
fun `when using roomId and there is no server names, the classic join room API is used`() = runTest {
|
||||
val roomSummary = aRoomSummaryFilled()
|
||||
val joinRoomLambda = lambdaRecorder { _: RoomId -> Result.success(roomSummary) }
|
||||
val joinRoomByIdOrAliasLambda = lambdaRecorder { _: RoomIdOrAlias, _: List<String> -> Result.success(roomSummary) }
|
||||
val roomResult = FakeMatrixRoom()
|
||||
val aTrigger = JoinedRoom.Trigger.MobilePermalink
|
||||
val client: MatrixClient = FakeMatrixClient().also {
|
||||
|
|
@ -51,7 +56,7 @@ class DefaultJoinRoomTest {
|
|||
client = client,
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
sut.invoke(A_ROOM_ID, emptyList(), aTrigger)
|
||||
sut.invoke(A_ROOM_ID.toRoomIdOrAlias(), emptyList(), aTrigger)
|
||||
joinRoomByIdOrAliasLambda
|
||||
.assertions()
|
||||
.isNeverCalled()
|
||||
|
|
@ -67,9 +72,10 @@ class DefaultJoinRoomTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `when server names are available, joinRoomByIdOrAlias API is used`() = runTest {
|
||||
val joinRoomLambda = lambdaRecorder { _: RoomId -> Result.success(Unit) }
|
||||
val joinRoomByIdOrAliasLambda = lambdaRecorder { _: RoomId, _: List<String> -> Result.success(Unit) }
|
||||
fun `when using roomId and server names are available, joinRoomByIdOrAlias API is used`() = runTest {
|
||||
val roomSummary = aRoomSummaryFilled()
|
||||
val joinRoomLambda = lambdaRecorder { _: RoomId -> Result.success(roomSummary) }
|
||||
val joinRoomByIdOrAliasLambda = lambdaRecorder { _: RoomIdOrAlias, _: List<String> -> Result.success(roomSummary) }
|
||||
val roomResult = FakeMatrixRoom()
|
||||
val aTrigger = JoinedRoom.Trigger.MobilePermalink
|
||||
val client: MatrixClient = FakeMatrixClient().also {
|
||||
|
|
@ -85,12 +91,12 @@ class DefaultJoinRoomTest {
|
|||
client = client,
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
sut.invoke(A_ROOM_ID, A_SERVER_LIST, aTrigger)
|
||||
sut.invoke(A_ROOM_ID.toRoomIdOrAlias(), A_SERVER_LIST, aTrigger)
|
||||
joinRoomByIdOrAliasLambda
|
||||
.assertions()
|
||||
.isCalledOnce()
|
||||
.with(
|
||||
value(A_ROOM_ID),
|
||||
value(A_ROOM_ID.toRoomIdOrAlias()),
|
||||
value(A_SERVER_LIST)
|
||||
)
|
||||
joinRoomLambda
|
||||
|
|
@ -100,4 +106,40 @@ class DefaultJoinRoomTest {
|
|||
roomResult.toAnalyticsJoinedRoom(aTrigger)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when using roomAlias, joinRoomByIdOrAlias API is used`() = runTest {
|
||||
val roomSummary = aRoomSummaryFilled()
|
||||
val joinRoomLambda = lambdaRecorder { _: RoomId -> Result.success(roomSummary) }
|
||||
val joinRoomByIdOrAliasLambda = lambdaRecorder { _: RoomIdOrAlias, _: List<String> -> Result.success(roomSummary) }
|
||||
val roomResult = FakeMatrixRoom()
|
||||
val aTrigger = JoinedRoom.Trigger.MobilePermalink
|
||||
val client: MatrixClient = FakeMatrixClient().also {
|
||||
it.joinRoomLambda = joinRoomLambda
|
||||
it.joinRoomByIdOrAliasLambda = joinRoomByIdOrAliasLambda
|
||||
it.givenGetRoomResult(
|
||||
roomId = A_ROOM_ID,
|
||||
result = roomResult
|
||||
)
|
||||
}
|
||||
val analyticsService = FakeAnalyticsService()
|
||||
val sut = DefaultJoinRoom(
|
||||
client = client,
|
||||
analyticsService = analyticsService,
|
||||
)
|
||||
sut.invoke(A_ROOM_ALIAS.toRoomIdOrAlias(), A_SERVER_LIST, aTrigger)
|
||||
joinRoomByIdOrAliasLambda
|
||||
.assertions()
|
||||
.isCalledOnce()
|
||||
.with(
|
||||
value(A_ROOM_ALIAS.toRoomIdOrAlias()),
|
||||
value(emptyList<String>())
|
||||
)
|
||||
joinRoomLambda
|
||||
.assertions()
|
||||
.isNeverCalled()
|
||||
assertThat(analyticsService.capturedEvents).containsExactly(
|
||||
roomResult.toAnalyticsJoinedRoom(aTrigger)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue