Merge pull request #3241 from element-hq/feature/fga/room_preview_join_button_fallback
Join Room : allow to join by alias (and getPreview)
This commit is contained in:
@@ -33,6 +33,7 @@ import io.element.android.libraries.architecture.runCatchingUpdatingState
|
||||
import io.element.android.libraries.architecture.runUpdatingState
|
||||
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.toRoomIdOrAlias
|
||||
import io.element.android.libraries.matrix.api.room.join.JoinRoom
|
||||
import io.element.android.libraries.push.api.notifications.NotificationCleaner
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -107,7 +108,7 @@ class AcceptDeclineInvitePresenter @Inject constructor(
|
||||
) = launch {
|
||||
acceptedAction.runUpdatingState {
|
||||
joinRoom(
|
||||
roomId = roomId,
|
||||
roomIdOrAlias = roomId.toRoomIdOrAlias(),
|
||||
serverNames = emptyList(),
|
||||
trigger = JoinedRoom.Trigger.Invite,
|
||||
)
|
||||
|
||||
@@ -23,7 +23,9 @@ import io.element.android.features.invite.api.response.InviteData
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
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.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
|
||||
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_SESSION_ID
|
||||
@@ -178,8 +180,8 @@ class AcceptDeclineInvitePresenterTest {
|
||||
|
||||
@Test
|
||||
fun `present - accepting invite error flow`() = runTest {
|
||||
val joinRoomFailure = lambdaRecorder { roomId: RoomId, _: List<String>, _: JoinedRoom.Trigger ->
|
||||
Result.failure<Unit>(RuntimeException("Failed to join room $roomId"))
|
||||
val joinRoomFailure = lambdaRecorder { roomIdOrAlias: RoomIdOrAlias, _: List<String>, _: JoinedRoom.Trigger ->
|
||||
Result.failure<Unit>(RuntimeException("Failed to join room $roomIdOrAlias"))
|
||||
}
|
||||
val presenter = createAcceptDeclineInvitePresenter(joinRoomLambda = joinRoomFailure)
|
||||
presenter.test {
|
||||
@@ -208,7 +210,7 @@ class AcceptDeclineInvitePresenterTest {
|
||||
assert(joinRoomFailure)
|
||||
.isCalledOnce()
|
||||
.with(
|
||||
value(A_ROOM_ID),
|
||||
value(A_ROOM_ID.toRoomIdOrAlias()),
|
||||
value(emptyList<String>()),
|
||||
value(JoinedRoom.Trigger.Invite)
|
||||
)
|
||||
@@ -222,7 +224,7 @@ class AcceptDeclineInvitePresenterTest {
|
||||
val fakeNotificationCleaner = FakeNotificationCleaner(
|
||||
clearMembershipNotificationForRoomLambda = clearMembershipNotificationForRoomLambda
|
||||
)
|
||||
val joinRoomSuccess = lambdaRecorder { _: RoomId, _: List<String>, _: JoinedRoom.Trigger ->
|
||||
val joinRoomSuccess = lambdaRecorder { _: RoomIdOrAlias, _: List<String>, _: JoinedRoom.Trigger ->
|
||||
Result.success(Unit)
|
||||
}
|
||||
val presenter = createAcceptDeclineInvitePresenter(
|
||||
@@ -248,7 +250,7 @@ class AcceptDeclineInvitePresenterTest {
|
||||
assert(joinRoomSuccess)
|
||||
.isCalledOnce()
|
||||
.with(
|
||||
value(A_ROOM_ID),
|
||||
value(A_ROOM_ID.toRoomIdOrAlias()),
|
||||
value(emptyList<String>()),
|
||||
value(JoinedRoom.Trigger.Invite)
|
||||
)
|
||||
@@ -271,7 +273,7 @@ class AcceptDeclineInvitePresenterTest {
|
||||
|
||||
private fun createAcceptDeclineInvitePresenter(
|
||||
client: MatrixClient = FakeMatrixClient(),
|
||||
joinRoomLambda: (RoomId, List<String>, JoinedRoom.Trigger) -> Result<Unit> = { _, _, _ ->
|
||||
joinRoomLambda: (RoomIdOrAlias, List<String>, JoinedRoom.Trigger) -> Result<Unit> = { _, _, _ ->
|
||||
Result.success(Unit)
|
||||
},
|
||||
notificationCleaner: NotificationCleaner = FakeNotificationCleaner(),
|
||||
|
||||
@@ -96,7 +96,7 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||
}
|
||||
else -> {
|
||||
value = ContentState.Loading(roomIdOrAlias)
|
||||
val result = matrixClient.getRoomPreviewFromRoomId(roomId, serverNames)
|
||||
val result = matrixClient.getRoomPreview(roomIdOrAlias, serverNames)
|
||||
value = result.fold(
|
||||
onSuccess = { roomPreview ->
|
||||
roomPreview.toContentState()
|
||||
@@ -153,7 +153,7 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||
private fun CoroutineScope.joinRoom(joinAction: MutableState<AsyncAction<Unit>>) = launch {
|
||||
joinAction.runUpdatingState {
|
||||
joinRoom.invoke(
|
||||
roomId = roomId,
|
||||
roomIdOrAlias = roomIdOrAlias,
|
||||
serverNames = serverNames,
|
||||
trigger = trigger
|
||||
)
|
||||
|
||||
@@ -37,7 +37,11 @@ data class JoinRoomState(
|
||||
val eventSink: (JoinRoomEvents) -> Unit
|
||||
) {
|
||||
val joinAuthorisationStatus = when (contentState) {
|
||||
// Use the join authorisation status from the loaded content state
|
||||
is ContentState.Loaded -> contentState.joinAuthorisationStatus
|
||||
// Assume that if the room is unknown, the user can join it
|
||||
is ContentState.UnknownRoom -> JoinAuthorisationStatus.CanJoin
|
||||
// Otherwise assume that the user can't join the room
|
||||
else -> JoinAuthorisationStatus.Unknown
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
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.room.CurrentUserMembership
|
||||
@@ -180,7 +181,7 @@ class JoinRoomPresenterTest {
|
||||
@Test
|
||||
fun `present - when room is joined with success, all the parameters are provided`() = runTest {
|
||||
val aTrigger = JoinedRoom.Trigger.MobilePermalink
|
||||
val joinRoomLambda = lambdaRecorder { _: RoomId, _: List<String>, _: JoinedRoom.Trigger ->
|
||||
val joinRoomLambda = lambdaRecorder { _: RoomIdOrAlias, _: List<String>, _: JoinedRoom.Trigger ->
|
||||
Result.success(Unit)
|
||||
}
|
||||
val presenter = createJoinRoomPresenter(
|
||||
@@ -201,7 +202,7 @@ class JoinRoomPresenterTest {
|
||||
}
|
||||
joinRoomLambda.assertions()
|
||||
.isCalledOnce()
|
||||
.with(value(A_ROOM_ID), value(A_SERVER_LIST), value(aTrigger))
|
||||
.with(value(A_ROOM_ID.toRoomIdOrAlias()), value(A_SERVER_LIST), value(aTrigger))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,7 +367,7 @@ class JoinRoomPresenterTest {
|
||||
@Test
|
||||
fun `present - when room is not known RoomPreview is loaded`() = runTest {
|
||||
val client = FakeMatrixClient(
|
||||
getRoomPreviewFromRoomIdResult = { _, _ ->
|
||||
getRoomPreviewResult = { _, _ ->
|
||||
Result.success(
|
||||
RoomPreview(
|
||||
roomId = A_ROOM_ID,
|
||||
@@ -411,7 +412,7 @@ class JoinRoomPresenterTest {
|
||||
@Test
|
||||
fun `present - when room is not known RoomPreview is loaded with error`() = runTest {
|
||||
val client = FakeMatrixClient(
|
||||
getRoomPreviewFromRoomIdResult = { _, _ ->
|
||||
getRoomPreviewResult = { _, _ ->
|
||||
Result.failure(AN_EXCEPTION)
|
||||
}
|
||||
)
|
||||
@@ -449,7 +450,7 @@ class JoinRoomPresenterTest {
|
||||
@Test
|
||||
fun `present - when room is not known RoomPreview is loaded with error 403`() = runTest {
|
||||
val client = FakeMatrixClient(
|
||||
getRoomPreviewFromRoomIdResult = { _, _ ->
|
||||
getRoomPreviewResult = { _, _ ->
|
||||
Result.failure(Exception("403"))
|
||||
}
|
||||
)
|
||||
@@ -474,7 +475,7 @@ class JoinRoomPresenterTest {
|
||||
serverNames: List<String> = emptyList(),
|
||||
trigger: JoinedRoom.Trigger = JoinedRoom.Trigger.Invite,
|
||||
matrixClient: MatrixClient = FakeMatrixClient(),
|
||||
joinRoomLambda: (RoomId, List<String>, JoinedRoom.Trigger) -> Result<Unit> = { _, _, _ ->
|
||||
joinRoomLambda: (RoomIdOrAlias, List<String>, JoinedRoom.Trigger) -> Result<Unit> = { _, _, _ ->
|
||||
Result.success(Unit)
|
||||
},
|
||||
knockRoom: KnockRoom = FakeKnockRoom(),
|
||||
|
||||
@@ -19,6 +19,7 @@ package io.element.android.libraries.matrix.api
|
||||
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.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
|
||||
@@ -35,6 +36,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.user.MatrixSearchUserResults
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
@@ -65,8 +67,8 @@ interface MatrixClient : Closeable {
|
||||
suspend fun setDisplayName(displayName: String): Result<Unit>
|
||||
suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result<Unit>
|
||||
suspend fun removeAvatar(): Result<Unit>
|
||||
suspend fun joinRoom(roomId: RoomId): Result<Unit>
|
||||
suspend fun joinRoomByIdOrAlias(roomId: RoomId, serverNames: List<String>): Result<Unit>
|
||||
suspend fun joinRoom(roomId: RoomId): Result<RoomSummary?>
|
||||
suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomSummary?>
|
||||
suspend fun knockRoom(roomId: RoomId): Result<Unit>
|
||||
fun syncService(): SyncService
|
||||
fun sessionVerificationService(): SessionVerificationService
|
||||
@@ -104,7 +106,6 @@ interface MatrixClient : Closeable {
|
||||
suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result<Unit>
|
||||
suspend fun getRecentlyVisitedRooms(): Result<List<RoomId>>
|
||||
suspend fun resolveRoomAlias(roomAlias: RoomAlias): Result<ResolvedRoomAlias>
|
||||
suspend fun getRoomPreviewFromRoomId(roomId: RoomId, serverNames: List<String>): Result<RoomPreview>
|
||||
|
||||
/**
|
||||
* Enables or disables the sending queue, according to the given parameter.
|
||||
@@ -132,4 +133,5 @@ interface MatrixClient : Closeable {
|
||||
* Execute generic GET requests through the SDKs internal HTTP client.
|
||||
*/
|
||||
suspend fun getUrl(url: String): Result<String>
|
||||
suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomPreview>
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
package io.element.android.libraries.matrix.api.room.join
|
||||
|
||||
import im.vector.app.features.analytics.plan.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||
|
||||
interface JoinRoom {
|
||||
suspend operator fun invoke(
|
||||
roomId: RoomId,
|
||||
roomIdOrAlias: RoomIdOrAlias,
|
||||
serverNames: List<String>,
|
||||
trigger: JoinedRoom.Trigger,
|
||||
): Result<Unit>
|
||||
|
||||
@@ -28,6 +28,7 @@ data class RoomSummary(
|
||||
val roomId: RoomId,
|
||||
val name: String?,
|
||||
val canonicalAlias: RoomAlias?,
|
||||
val alternativeAliases: List<RoomAlias>,
|
||||
val isDirect: Boolean,
|
||||
val avatarUrl: String?,
|
||||
val lastMessage: RoomMessage?,
|
||||
@@ -44,4 +45,6 @@ data class RoomSummary(
|
||||
val heroes: List<MatrixUser>,
|
||||
) {
|
||||
val lastMessageTimestamp = lastMessage?.originServerTs
|
||||
val aliases: List<RoomAlias>
|
||||
get() = listOfNotNull(canonicalAlias) + alternativeAliases
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ 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.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.createroom.CreateRoomParameters
|
||||
@@ -36,6 +37,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.user.MatrixSearchUserResults
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||
@@ -80,7 +82,7 @@ class FakeMatrixClient(
|
||||
private val roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService(),
|
||||
private val accountManagementUrlString: Result<String?> = Result.success(null),
|
||||
private val resolveRoomAliasResult: (RoomAlias) -> Result<ResolvedRoomAlias> = { Result.success(ResolvedRoomAlias(A_ROOM_ID, emptyList())) },
|
||||
private val getRoomPreviewFromRoomIdResult: (RoomId, List<String>) -> Result<RoomPreview> = { _, _ -> 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() },
|
||||
@@ -108,11 +110,11 @@ class FakeMatrixClient(
|
||||
private var setDisplayNameResult: Result<Unit> = Result.success(Unit)
|
||||
private var uploadAvatarResult: Result<Unit> = Result.success(Unit)
|
||||
private var removeAvatarResult: Result<Unit> = Result.success(Unit)
|
||||
var joinRoomLambda: (RoomId) -> Result<Unit> = {
|
||||
Result.success(Unit)
|
||||
var joinRoomLambda: (RoomId) -> Result<RoomSummary?> = {
|
||||
Result.success(null)
|
||||
}
|
||||
var joinRoomByIdOrAliasLambda: (RoomId, List<String>) -> Result<Unit> = { _, _ ->
|
||||
Result.success(Unit)
|
||||
var joinRoomByIdOrAliasLambda: (RoomIdOrAlias, List<String>) -> Result<RoomSummary?> = { _, _ ->
|
||||
Result.success(null)
|
||||
}
|
||||
var knockRoomLambda: (RoomId) -> Result<Unit> = {
|
||||
Result.success(Unit)
|
||||
@@ -207,10 +209,10 @@ class FakeMatrixClient(
|
||||
return removeAvatarResult
|
||||
}
|
||||
|
||||
override suspend fun joinRoom(roomId: RoomId): Result<Unit> = joinRoomLambda(roomId)
|
||||
override suspend fun joinRoom(roomId: RoomId): Result<RoomSummary?> = joinRoomLambda(roomId)
|
||||
|
||||
override suspend fun joinRoomByIdOrAlias(roomId: RoomId, serverNames: List<String>): Result<Unit> {
|
||||
return joinRoomByIdOrAliasLambda(roomId, serverNames)
|
||||
override suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomSummary?> {
|
||||
return joinRoomByIdOrAliasLambda(roomIdOrAlias, serverNames)
|
||||
}
|
||||
|
||||
override suspend fun knockRoom(roomId: RoomId): Result<Unit> = knockRoomLambda(roomId)
|
||||
@@ -297,8 +299,8 @@ class FakeMatrixClient(
|
||||
resolveRoomAliasResult(roomAlias)
|
||||
}
|
||||
|
||||
override suspend fun getRoomPreviewFromRoomId(roomId: RoomId, serverNames: List<String>) = simulateLongTask {
|
||||
getRoomPreviewFromRoomIdResult(roomId, serverNames)
|
||||
override suspend fun getRoomPreview(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomPreview> = simulateLongTask {
|
||||
getRoomPreviewResult(roomIdOrAlias, serverNames)
|
||||
}
|
||||
|
||||
override suspend fun getRecentlyVisitedRooms(): Result<List<RoomId>> {
|
||||
|
||||
@@ -68,6 +68,7 @@ fun aRoomSummary(
|
||||
notificationMode: RoomNotificationMode? = null,
|
||||
inviter: RoomMember? = null,
|
||||
canonicalAlias: RoomAlias? = null,
|
||||
alternativeAliases: List<RoomAlias> = emptyList(),
|
||||
hasRoomCall: Boolean = false,
|
||||
isDm: Boolean = false,
|
||||
isFavorite: Boolean = false,
|
||||
@@ -86,6 +87,7 @@ fun aRoomSummary(
|
||||
userDefinedNotificationMode = notificationMode,
|
||||
inviter = inviter,
|
||||
canonicalAlias = canonicalAlias,
|
||||
alternativeAliases = alternativeAliases,
|
||||
hasRoomCall = hasRoomCall,
|
||||
isDm = isDm,
|
||||
isFavorite = isFavorite,
|
||||
|
||||
@@ -17,18 +17,18 @@
|
||||
package io.element.android.libraries.matrix.test.room.join
|
||||
|
||||
import im.vector.app.features.analytics.plan.JoinedRoom
|
||||
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.tests.testutils.simulateLongTask
|
||||
|
||||
class FakeJoinRoom(
|
||||
var lambda: (RoomId, List<String>, JoinedRoom.Trigger) -> Result<Unit>
|
||||
var lambda: (RoomIdOrAlias, List<String>, JoinedRoom.Trigger) -> Result<Unit>
|
||||
) : JoinRoom {
|
||||
override suspend fun invoke(
|
||||
roomId: RoomId,
|
||||
roomIdOrAlias: RoomIdOrAlias,
|
||||
serverNames: List<String>,
|
||||
trigger: JoinedRoom.Trigger,
|
||||
): Result<Unit> = simulateLongTask {
|
||||
lambda(roomId, serverNames, trigger)
|
||||
lambda(roomIdOrAlias, serverNames, trigger)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ fun aRoomSummaryDetails(
|
||||
roomId: RoomId = RoomId("!room:domain"),
|
||||
name: String? = "roomName",
|
||||
canonicalAlias: RoomAlias? = null,
|
||||
alternativeAliases: List<RoomAlias> = emptyList(),
|
||||
isDirect: Boolean = true,
|
||||
avatarUrl: String? = null,
|
||||
lastMessage: RoomMessage? = null,
|
||||
@@ -56,6 +57,7 @@ fun aRoomSummaryDetails(
|
||||
roomId = roomId,
|
||||
name = name,
|
||||
canonicalAlias = canonicalAlias,
|
||||
alternativeAliases = alternativeAliases,
|
||||
isDirect = isDirect,
|
||||
avatarUrl = avatarUrl,
|
||||
lastMessage = lastMessage,
|
||||
|
||||
@@ -25,6 +25,7 @@ import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
import io.element.android.libraries.matrix.api.core.asEventId
|
||||
import io.element.android.libraries.matrix.api.room.Mention
|
||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
||||
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_MESSAGE
|
||||
@@ -261,7 +262,7 @@ class NotificationBroadcastReceiverHandlerTest {
|
||||
|
||||
@Test
|
||||
fun `Test join room`() = runTest {
|
||||
val joinRoom = lambdaRecorder<RoomId, Result<Unit>> { _ -> Result.success(Unit) }
|
||||
val joinRoom = lambdaRecorder<RoomId, Result<RoomSummary?>> { _ -> Result.success(null) }
|
||||
val clearMembershipNotificationForRoomLambda = lambdaRecorder<SessionId, RoomId, Unit> { _, _ -> }
|
||||
val fakeNotificationCleaner = FakeNotificationCleaner(
|
||||
clearMembershipNotificationForRoomLambda = clearMembershipNotificationForRoomLambda,
|
||||
@@ -444,7 +445,7 @@ class NotificationBroadcastReceiverHandlerTest {
|
||||
|
||||
private fun TestScope.createNotificationBroadcastReceiverHandler(
|
||||
matrixRoom: FakeMatrixRoom? = FakeMatrixRoom(),
|
||||
joinRoom: (RoomId) -> Result<Unit> = { lambdaError() },
|
||||
joinRoom: (RoomId) -> Result<RoomSummary?> = { lambdaError() },
|
||||
matrixClient: MatrixClient? = FakeMatrixClient().apply {
|
||||
givenGetRoomResult(A_ROOM_ID, matrixRoom)
|
||||
joinRoomLambda = joinRoom
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user