Split MatrixRoom into BaseRoom and JoinedRoom (#4561)

`JoinedRoom` will now contain both a mandatory live timeline reference and all the functionality associated to it.

`BaseRoom` on the other hand will contain only functionality that's shared for both joined and not joined rooms.

`NotJoinedRoom` is a wrapper around `RoomPreviewInfo` data and a possible local `BaseRoom`, if it exists.

The `RustRoomFactory` cache is now gone since the persistent event cache should have the same effect.
This commit is contained in:
Jorge Martin Espinosa 2025-04-23 15:53:40 +02:00 committed by GitHub
parent 91cb84ce8d
commit 619aa6f2de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
193 changed files with 2921 additions and 2567 deletions

View file

@ -241,7 +241,7 @@ class CallScreenPresenter @AssistedInject constructor(
private suspend fun MatrixClient.notifyCallStartIfNeeded(roomId: RoomId) {
if (!notifiedCallStart) {
getRoom(roomId)?.sendCallNotificationIfNeeded()
getJoinedRoom(roomId)?.sendCallNotificationIfNeeded()
?.onSuccess { notifiedCallStart = true }
}
}

View file

@ -33,7 +33,7 @@ class DefaultCallWidgetProvider @Inject constructor(
theme: String?,
): Result<CallWidgetProvider.GetWidgetResult> = runCatching {
val matrixClient = matrixClientsProvider.getOrRestore(sessionId).getOrThrow()
val room = matrixClient.getRoom(roomId) ?: error("Room not found")
val room = matrixClient.getJoinedRoom(roomId) ?: error("Room not found")
val customBaseUrl = appPreferencesStore.getCustomElementCallBaseUrlFlow().firstOrNull()
val baseUrl = customBaseUrl ?: EMBEDDED_CALL_WIDGET_BASE_URL

View file

@ -26,7 +26,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.sync.FakeSyncService
import io.element.android.libraries.matrix.test.widget.FakeMatrixWidgetDriver
import io.element.android.libraries.network.useragent.UserAgentProvider
@ -84,7 +84,7 @@ import kotlin.time.Duration.Companion.seconds
fun `present - with CallType RoomCall sets call as active, loads URL, runs WidgetDriver and notifies the other clients a call started`() = runTest {
val sendCallNotificationIfNeededLambda = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
val syncService = FakeSyncService(SyncState.Running)
val fakeRoom = FakeMatrixRoom(sendCallNotificationIfNeededResult = sendCallNotificationIfNeededLambda)
val fakeRoom = FakeJoinedRoom(sendCallNotificationIfNeededResult = sendCallNotificationIfNeededLambda)
val client = FakeMatrixClient(syncService = syncService).apply {
givenGetRoomResult(A_ROOM_ID, fakeRoom)
}

View file

@ -28,7 +28,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID_2
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.push.api.notifications.ForegroundServiceType
import io.element.android.libraries.push.api.notifications.NotificationIdProvider
@ -227,7 +227,7 @@ class DefaultActiveCallManagerTest {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `observeRingingCalls - will cancel the active ringing call if the call is cancelled`() = runTest {
val room = FakeMatrixRoom().apply {
val room = FakeBaseRoom().apply {
givenRoomInfo(aRoomInfo())
}
val client = FakeMatrixClient().apply {
@ -254,7 +254,7 @@ class DefaultActiveCallManagerTest {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `observeRingingCalls - will do nothing if either the session or the room are not found`() = runTest {
val room = FakeMatrixRoom().apply {
val room = FakeBaseRoom().apply {
givenRoomInfo(aRoomInfo())
}
val client = FakeMatrixClient().apply {

View file

@ -15,7 +15,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.widget.FakeCallWidgetSettingsProvider
import io.element.android.libraries.matrix.test.widget.FakeMatrixWidgetDriver
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
@ -41,7 +41,7 @@ class DefaultCallWidgetProviderTest {
@Test
fun `getWidget - fails if it can't generate the URL for the widget`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
generateWidgetWebViewUrlResult = { _, _, _, _ -> Result.failure(Exception("Can't generate URL for widget")) }
)
val client = FakeMatrixClient().apply {
@ -53,7 +53,7 @@ class DefaultCallWidgetProviderTest {
@Test
fun `getWidget - fails if it can't get the widget driver`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
generateWidgetWebViewUrlResult = { _, _, _, _ -> Result.success("url") },
getWidgetDriverResult = { Result.failure(Exception("Can't get a widget driver")) }
)
@ -66,7 +66,7 @@ class DefaultCallWidgetProviderTest {
@Test
fun `getWidget - returns a widget driver when all steps are successful`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
generateWidgetWebViewUrlResult = { _, _, _, _ -> Result.success("url") },
getWidgetDriverResult = { Result.success(FakeMatrixWidgetDriver()) },
)
@ -79,7 +79,7 @@ class DefaultCallWidgetProviderTest {
@Test
fun `getWidget - will use a custom base url if it exists`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
generateWidgetWebViewUrlResult = { _, _, _, _ -> Result.success("url") },
getWidgetDriverResult = { Result.success(FakeMatrixWidgetDriver()) },
)

View file

@ -66,7 +66,7 @@ private const val AN_URI_FROM_CAMERA_2 = "content://uri_from_camera_2"
private const val AN_URI_FROM_GALLERY = "content://uri_from_gallery"
@RunWith(RobolectricTestRunner::class)
class ConfigureRoomPresenterTest {
class ConfigureBaseRoomPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()

View file

@ -21,7 +21,7 @@ import io.element.android.tests.testutils.test
import kotlinx.coroutines.test.runTest
import org.junit.Test
class JoinRoomByAddressPresenterTest {
class JoinBaseRoomByAddressPresenterTest {
@Test
fun `present - initial state`() = runTest {
val presenter = createJoinRoomByAddressPresenter()

View file

@ -23,7 +23,7 @@ import org.junit.rules.TestRule
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class JoinRoomByAddressViewTest {
class JoinBaseRoomByAddressViewTest {
@get:Rule
val rule = createAndroidComposeRule<ComponentActivity>()

View file

@ -36,7 +36,7 @@ import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
class CreateRoomRootPresenterTest {
class CreateBaseRoomRootPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()

View file

@ -33,7 +33,7 @@ import org.junit.runner.RunWith
import org.robolectric.annotation.Config
@RunWith(AndroidJUnit4::class)
class CreateRoomRootViewTest {
class CreateBaseRoomRootViewTest {
@get:Rule
val rule = createAndroidComposeRule<ComponentActivity>()

View file

@ -121,7 +121,7 @@ class AcceptDeclineInvitePresenter @Inject constructor(
declinedAction: MutableState<AsyncAction<RoomId>>,
) = launch {
suspend {
client.getPendingRoom(inviteData.roomId)?.use {
client.getRoom(inviteData.roomId)?.use {
it.leave().getOrThrow()
}
if (blockUser) {

View file

@ -28,7 +28,7 @@ import io.element.android.libraries.matrix.test.A_ROOM_NAME
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.room.FakeRoomPreview
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.join.FakeJoinRoom
import io.element.android.libraries.push.api.notifications.NotificationCleaner
import io.element.android.libraries.push.test.notifications.FakeNotificationCleaner
@ -88,11 +88,9 @@ class AcceptDeclineInvitePresenterTest {
val declineInviteFailure = lambdaRecorder { ->
Result.failure<Unit>(RuntimeException("Failed to leave room"))
}
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
Result.success(FakeRoomPreview(declineInviteResult = declineInviteFailure))
}
)
val client = FakeMatrixClient().apply {
givenGetRoomResult(A_ROOM_ID, FakeBaseRoom(leaveRoomLambda = declineInviteFailure))
}
val seenInvitesStore = InMemorySeenInvitesStore(setOf(A_ROOM_ID, A_ROOM_ID_2, A_ROOM_ID_3))
val presenter = createAcceptDeclineInvitePresenter(
client = client,
@ -138,11 +136,9 @@ class AcceptDeclineInvitePresenterTest {
val declineInviteSuccess = lambdaRecorder { ->
Result.success(Unit)
}
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
Result.success(FakeRoomPreview(declineInviteResult = declineInviteSuccess))
}
)
val client = FakeMatrixClient().apply {
givenGetRoomResult(A_ROOM_ID, FakeBaseRoom(leaveRoomLambda = declineInviteSuccess))
}
val seenInvitesStore = InMemorySeenInvitesStore(setOf(A_ROOM_ID, A_ROOM_ID_2, A_ROOM_ID_3))
val presenter = createAcceptDeclineInvitePresenter(
client = client,
@ -186,11 +182,10 @@ class AcceptDeclineInvitePresenterTest {
val declineInviteSuccess = lambdaRecorder { -> Result.success(Unit) }
val ignoreUserSuccess = lambdaRecorder { _: UserId -> Result.success(Unit) }
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
Result.success(FakeRoomPreview(declineInviteResult = declineInviteSuccess))
},
ignoreUserResult = ignoreUserSuccess
)
).apply {
givenGetRoomResult(A_ROOM_ID, FakeBaseRoom(leaveRoomLambda = declineInviteSuccess))
}
val seenInvitesStore = InMemorySeenInvitesStore(setOf(A_ROOM_ID, A_ROOM_ID_2, A_ROOM_ID_3))
val presenter = createAcceptDeclineInvitePresenter(
client = client,
@ -229,11 +224,9 @@ class AcceptDeclineInvitePresenterTest {
val declineInviteFailure = lambdaRecorder { ->
Result.failure<Unit>(RuntimeException("Failed to leave room"))
}
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
Result.success(FakeRoomPreview(declineInviteResult = declineInviteFailure))
}
)
val client = FakeMatrixClient().apply {
givenGetRoomResult(A_ROOM_ID, FakeBaseRoom(leaveRoomLambda = declineInviteFailure))
}
val seenInvitesStore = InMemorySeenInvitesStore(setOf(A_ROOM_ID, A_ROOM_ID_2, A_ROOM_ID_3))
val presenter = createAcceptDeclineInvitePresenter(
client = client,

View file

@ -44,7 +44,7 @@ import io.element.android.libraries.matrix.api.exception.ClientException
import io.element.android.libraries.matrix.api.exception.ErrorKind
import io.element.android.libraries.matrix.api.getRoomInfoFlow
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomType
import io.element.android.libraries.matrix.api.room.isDm
@ -131,7 +131,7 @@ class JoinRoomPresenter @AssistedInject constructor(
val result = matrixClient.getRoomPreview(roomIdOrAlias, serverNames)
value = result.fold(
onSuccess = { preview ->
val membershipInfo = when (preview.info.membership) {
val membershipInfo = when (preview.previewInfo.membership) {
CurrentUserMembership.INVITED,
CurrentUserMembership.BANNED,
CurrentUserMembership.KNOCKED -> {
@ -139,7 +139,7 @@ class JoinRoomPresenter @AssistedInject constructor(
}
else -> null
}
preview.info.toContentState(
preview.previewInfo.toContentState(
senderMember = membershipInfo?.senderMember,
reason = membershipInfo?.currentUserMember?.membershipChangeReason,
)
@ -296,7 +296,7 @@ internal fun RoomDescription.toContentState(): ContentState {
}
@VisibleForTesting
internal fun MatrixRoomInfo.toContentState(membershipSender: RoomMember?, reason: String?): ContentState {
internal fun RoomInfo.toContentState(membershipSender: RoomMember?, reason: String?): ContentState {
return ContentState.Loaded(
roomId = id,
name = name,

View file

@ -21,8 +21,8 @@ interface CancelKnockRoom {
class DefaultCancelKnockRoom @Inject constructor(private val client: MatrixClient) : CancelKnockRoom {
override suspend fun invoke(roomId: RoomId): Result<Unit> {
return client
.getPendingRoom(roomId)
?.leave()
.getRoom(roomId)
?.use { it.leave() }
?: Result.failure(IllegalStateException("No pending room found"))
}
}

View file

@ -20,9 +20,7 @@ interface ForgetRoom {
@ContributesBinding(SessionScope::class)
class DefaultForgetRoom @Inject constructor(private val client: MatrixClient) : ForgetRoom {
override suspend fun invoke(roomId: RoomId): Result<Unit> {
return client
.getPendingRoom(roomId)
?.forget()
?: Result.failure(IllegalStateException("No pending room found"))
return client.getRoom(roomId)?.use { it.forget() }
?: Result.failure(IllegalStateException("Room not found"))
}
}

View file

@ -64,7 +64,7 @@ import org.junit.Test
import java.util.Optional
@Suppress("LargeClass")
class JoinRoomPresenterTest {
class JoinBaseRoomPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()
@ -273,7 +273,7 @@ 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(
getRoomPreviewResult = { _, _ ->
getNotJoinedRoomResult = { _, _ ->
Result.success(
aRoomPreview(
info = aRoomPreviewInfo(
@ -546,7 +546,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
getNotJoinedRoomResult = { _, _ ->
Result.success(
aRoomPreview(
info = aRoomPreviewInfo(
@ -591,7 +591,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as Private`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
getNotJoinedRoomResult = { _, _ ->
Result.success(
aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Private))
)
@ -611,7 +611,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as Custom`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
getNotJoinedRoomResult = { _, _ ->
Result.success(
aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Custom("custom")))
)
@ -631,7 +631,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as Invite`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
getNotJoinedRoomResult = { _, _ ->
Result.success(
aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Invite))
)
@ -651,7 +651,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as KnockRestricted`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
getNotJoinedRoomResult = { _, _ ->
Result.success(
aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.KnockRestricted(emptyList())))
)
@ -671,7 +671,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as Restricted`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
getNotJoinedRoomResult = { _, _ ->
Result.success(
aRoomPreview(info = aRoomPreviewInfo(joinRule = JoinRule.Restricted(emptyList())))
)
@ -691,7 +691,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded as Space`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
getNotJoinedRoomResult = { _, _ ->
Result.success(
aRoomPreview(info = aRoomPreviewInfo(isSpace = true))
)
@ -711,7 +711,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded with error`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
getNotJoinedRoomResult = { _, _ ->
Result.failure(AN_EXCEPTION)
}
)
@ -741,7 +741,7 @@ class JoinRoomPresenterTest {
@Test
fun `present - when room is not known RoomPreview is loaded with error Forbidden`() = runTest {
val client = FakeMatrixClient(
getRoomPreviewResult = { _, _ ->
getNotJoinedRoomResult = { _, _ ->
Result.failure(ClientException.MatrixApi(ErrorKind.Forbidden, "403", "Forbidden", null))
}
)

View file

@ -25,7 +25,7 @@ import org.junit.rules.TestRule
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class JoinRoomViewTest {
class JoinBaseRoomViewTest {
@get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
@Test

View file

@ -7,7 +7,7 @@
package io.element.android.features.knockrequests.impl.data
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.powerlevels.canBan
import io.element.android.libraries.matrix.api.room.powerlevels.canInvite
import io.element.android.libraries.matrix.api.room.powerlevels.canKick
@ -22,7 +22,7 @@ data class KnockRequestPermissions(
val canHandle = canAccept || canDecline || canBan
}
fun MatrixRoom.knockRequestPermissionsFlow(): Flow<KnockRequestPermissions> {
fun JoinedRoom.knockRequestPermissionsFlow(): Flow<KnockRequestPermissions> {
return syncUpdateFlow.map {
val canAccept = canInvite().getOrDefault(false)
val canDecline = canKick().getOrDefault(false)

View file

@ -14,14 +14,14 @@ import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
@Module
@ContributesTo(RoomScope::class)
object KnockRequestsModule {
@Provides
@SingleIn(RoomScope::class)
fun knockRequestsService(room: MatrixRoom, featureFlagService: FeatureFlagService): KnockRequestsService {
fun knockRequestsService(room: JoinedRoom, featureFlagService: FeatureFlagService): KnockRequestsService {
return KnockRequestsService(
knockRequestsFlow = room.knockRequestsFlow,
permissionsFlow = room.knockRequestPermissionsFlow(),

View file

@ -16,7 +16,7 @@ import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.test.A_ROOM_ID
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.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.lambda.assert
@ -30,7 +30,7 @@ import org.junit.Rule
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class LeaveRoomPresenterTest {
class LeaveBaseRoomPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()
@ -53,7 +53,7 @@ class LeaveRoomPresenterTest {
client = FakeMatrixClient().apply {
givenGetRoomResult(
roomId = A_ROOM_ID,
result = FakeMatrixRoom().apply {
result = FakeBaseRoom().apply {
givenRoomInfo(aRoomInfo(isDirect = false, isPublic = true, joinedMembersCount = 10))
}
)
@ -75,7 +75,7 @@ class LeaveRoomPresenterTest {
client = FakeMatrixClient().apply {
givenGetRoomResult(
roomId = A_ROOM_ID,
result = FakeMatrixRoom().apply {
result = FakeBaseRoom().apply {
givenRoomInfo(aRoomInfo(isPublic = false))
},
)
@ -97,7 +97,7 @@ class LeaveRoomPresenterTest {
client = FakeMatrixClient().apply {
givenGetRoomResult(
roomId = A_ROOM_ID,
result = FakeMatrixRoom().apply {
result = FakeBaseRoom().apply {
givenRoomInfo(aRoomInfo(joinedMembersCount = 1))
},
)
@ -119,7 +119,7 @@ class LeaveRoomPresenterTest {
client = FakeMatrixClient().apply {
givenGetRoomResult(
roomId = A_ROOM_ID,
result = FakeMatrixRoom().apply {
result = FakeBaseRoom().apply {
givenRoomInfo(aRoomInfo(isDirect = true, activeMembersCount = 2))
},
)
@ -142,7 +142,7 @@ class LeaveRoomPresenterTest {
client = FakeMatrixClient().apply {
givenGetRoomResult(
roomId = A_ROOM_ID,
result = FakeMatrixRoom(
result = FakeBaseRoom(
leaveRoomLambda = leaveRoomLambda
),
)
@ -167,7 +167,7 @@ class LeaveRoomPresenterTest {
client = FakeMatrixClient().apply {
givenGetRoomResult(
roomId = A_ROOM_ID,
result = FakeMatrixRoom(
result = FakeBaseRoom(
leaveRoomLambda = { Result.failure(RuntimeException("Blimey!")) }
),
)
@ -191,7 +191,7 @@ class LeaveRoomPresenterTest {
client = FakeMatrixClient().apply {
givenGetRoomResult(
roomId = A_ROOM_ID,
result = FakeMatrixRoom(
result = FakeBaseRoom(
leaveRoomLambda = { Result.success(Unit) }
),
)
@ -215,7 +215,7 @@ class LeaveRoomPresenterTest {
client = FakeMatrixClient().apply {
givenGetRoomResult(
roomId = A_ROOM_ID,
result = FakeMatrixRoom(
result = FakeBaseRoom(
leaveRoomLambda = { Result.failure(RuntimeException("Blimey!")) }
),
)

View file

@ -24,7 +24,7 @@ import io.element.android.features.location.impl.common.permissions.PermissionsS
import io.element.android.features.messages.api.MessageComposerContext
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.coroutines.launch
@ -32,7 +32,7 @@ import javax.inject.Inject
class SendLocationPresenter @Inject constructor(
permissionsPresenterFactory: PermissionsPresenter.Factory,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val analyticsService: AnalyticsService,
private val messageComposerContext: MessageComposerContext,
private val locationActions: LocationActions,

View file

@ -20,12 +20,12 @@ import io.element.android.features.location.impl.common.permissions.PermissionsE
import io.element.android.features.location.impl.common.permissions.PermissionsPresenter
import io.element.android.features.location.impl.common.permissions.PermissionsState
import io.element.android.features.messages.test.FakeMessageComposerContext
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.location.AssetType
import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.textcomposer.model.MessageComposerMode
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.WarmUpRule
@ -47,12 +47,12 @@ class SendLocationPresenterTest {
private val fakeBuildMeta = aBuildMeta(applicationName = "app name")
private fun createSendLocationPresenter(
matrixRoom: MatrixRoom = FakeMatrixRoom(),
joinedRoom: JoinedRoom = FakeJoinedRoom(),
): SendLocationPresenter = SendLocationPresenter(
permissionsPresenterFactory = object : PermissionsPresenter.Factory {
override fun create(permissions: List<String>): PermissionsPresenter = fakePermissionsPresenter
},
room = matrixRoom,
room = joinedRoom,
analyticsService = fakeAnalyticsService,
messageComposerContext = fakeMessageComposerContext,
locationActions = fakeLocationActions,
@ -265,10 +265,10 @@ class SendLocationPresenterTest {
val sendLocationResult = lambdaRecorder<String, String, String?, Int?, AssetType?, Result<Unit>> { _, _, _, _, _ ->
Result.success(Unit)
}
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
sendLocationResult = sendLocationResult,
)
val sendLocationPresenter = createSendLocationPresenter(matrixRoom)
val sendLocationPresenter = createSendLocationPresenter(joinedRoom)
fakePermissionsPresenter.givenState(
aPermissionsState(
permissions = PermissionsState.Permissions.AllGranted,
@ -326,10 +326,10 @@ class SendLocationPresenterTest {
val sendLocationResult = lambdaRecorder<String, String, String?, Int?, AssetType?, Result<Unit>> { _, _, _, _, _ ->
Result.success(Unit)
}
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
sendLocationResult = sendLocationResult,
)
val sendLocationPresenter = createSendLocationPresenter(matrixRoom)
val sendLocationPresenter = createSendLocationPresenter(joinedRoom)
fakePermissionsPresenter.givenState(
aPermissionsState(
permissions = PermissionsState.Permissions.NoneGranted,
@ -387,10 +387,10 @@ class SendLocationPresenterTest {
val sendLocationResult = lambdaRecorder<String, String, String?, Int?, AssetType?, Result<Unit>> { _, _, _, _, _ ->
Result.success(Unit)
}
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
sendLocationResult = sendLocationResult,
)
val sendLocationPresenter = createSendLocationPresenter(matrixRoom)
val sendLocationPresenter = createSendLocationPresenter(joinedRoom)
fakePermissionsPresenter.givenState(
aPermissionsState(
permissions = PermissionsState.Permissions.NoneGranted,

View file

@ -69,7 +69,7 @@ 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.media.MediaSource
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.alias.matches
import io.element.android.libraries.matrix.api.room.joinedRoomMembers
import io.element.android.libraries.matrix.api.timeline.Timeline
@ -101,7 +101,7 @@ class MessagesFlowNode @AssistedInject constructor(
private val mediaViewerEntryPoint: MediaViewerEntryPoint,
private val analyticsService: AnalyticsService,
private val locationService: LocationService,
private val room: MatrixRoom,
private val room: BaseRoom,
private val roomMemberProfilesCache: RoomMemberProfilesCache,
private val roomNamesCache: RoomNamesCache,
private val mentionSpanUpdater: MentionSpanUpdater,

View file

@ -53,7 +53,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.alias.matches
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.mediaplayer.api.MediaPlayer
@ -67,7 +67,7 @@ class MessagesNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val coroutineScope: CoroutineScope,
private val room: MatrixRoom,
private val room: BaseRoom,
private val analyticsService: AnalyticsService,
messageComposerPresenterFactory: MessageComposerPresenter.Factory,
timelinePresenterFactory: TimelinePresenter.Factory,

View file

@ -65,10 +65,10 @@ import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.room.powerlevels.canPinUnpin
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther
@ -90,7 +90,7 @@ import timber.log.Timber
class MessagesPresenter @AssistedInject constructor(
@Assisted private val navigator: MessagesNavigator,
private val room: MatrixRoom,
private val room: JoinedRoom,
@Assisted private val composerPresenter: Presenter<MessageComposerState>,
private val voiceMessageComposerPresenter: Presenter<VoiceMessageComposerState>,
@Assisted private val timelinePresenter: Presenter<TimelineState>,
@ -279,7 +279,7 @@ class MessagesPresenter @AssistedInject constructor(
}
}
private fun MatrixRoomInfo.avatarData(): AvatarData {
private fun RoomInfo.avatarData(): AvatarData {
return AvatarData(
id = id.value,
name = name,
@ -288,7 +288,7 @@ class MessagesPresenter @AssistedInject constructor(
)
}
private fun MatrixRoomInfo.heroes(): List<AvatarData> {
private fun RoomInfo.heroes(): List<AvatarData> {
return heroes.map { user ->
user.getAvatarData(size = AvatarSize.TimelineRoom)
}
@ -382,8 +382,8 @@ class MessagesPresenter @AssistedInject constructor(
inviteProgress.value = AsyncData.Loading()
runCatching {
val memberList = when (val memberState = room.membersStateFlow.value) {
is MatrixRoomMembersState.Ready -> memberState.roomMembers
is MatrixRoomMembersState.Error -> memberState.prevRoomMembers.orEmpty()
is RoomMembersState.Ready -> memberState.roomMembers
is RoomMembersState.Error -> memberState.prevRoomMembers.orEmpty()
else -> emptyList()
}

View file

@ -43,7 +43,7 @@ import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@ -63,7 +63,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
private val postProcessor: TimelineItemActionPostProcessor,
private val appPreferencesStore: AppPreferencesStore,
private val isPinnedMessagesFeatureEnabled: IsPinnedMessagesFeatureEnabled,
private val room: MatrixRoom,
private val room: BaseRoom,
private val userSendFailureFactory: VerifiedUserSendFailureFactory,
private val featureFlagService: FeatureFlagService,
private val dateFormatter: DateFormatter,

View file

@ -14,7 +14,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.ui.room.observeRoomMemberIdentityStateChange
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.CoroutineScope
@ -23,7 +23,7 @@ import timber.log.Timber
import javax.inject.Inject
class IdentityChangeStatePresenter @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val encryptionService: EncryptionService,
) : Presenter<IdentityChangeState> {
@Composable

View file

@ -7,12 +7,12 @@
package io.element.android.features.messages.impl.crypto.sendfailure
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import javax.inject.Inject
class VerifiedUserSendFailureFactory @Inject constructor(
private val room: MatrixRoom,
private val room: BaseRoom,
) {
suspend fun create(
sendState: LocalEventSendState?,

View file

@ -19,13 +19,13 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runUpdatingState
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import kotlinx.coroutines.launch
import javax.inject.Inject
class ResolveVerifiedUserSendFailurePresenter @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val verifiedUserSendFailureFactory: VerifiedUserSendFailureFactory,
) : Presenter<ResolveVerifiedUserSendFailureState> {
@Composable

View file

@ -10,7 +10,7 @@ package io.element.android.features.messages.impl.crypto.sendfailure.resolve
import androidx.compose.runtime.mutableStateOf
import io.element.android.libraries.matrix.api.core.SendHandle
import io.element.android.libraries.matrix.api.core.TransactionId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import timber.log.Timber
@ -21,7 +21,7 @@ import timber.log.Timber
* This way, the user can resolve and resend the message for each user concerned, one by one.
*/
class VerifiedUserSendFailureResolver(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val transactionId: TransactionId,
private val sendHandle: SendHandle,
private val iterator: VerifiedUserSendFailureIterator,

View file

@ -21,7 +21,7 @@ class MatrixComposerDraftStore @Inject constructor(
private val client: MatrixClient,
) : ComposerDraftStore {
override suspend fun loadDraft(roomId: RoomId): ComposerDraft? {
return client.getRoom(roomId)?.let { room ->
return client.getRoom(roomId)?.use { room ->
room.loadComposerDraft()
.onFailure {
Timber.e(it, "Failed to load composer draft for room $roomId")
@ -35,7 +35,7 @@ class MatrixComposerDraftStore @Inject constructor(
}
override suspend fun updateDraft(roomId: RoomId, draft: ComposerDraft?) {
client.getRoom(roomId)?.let { room ->
client.getRoom(roomId)?.use { room ->
val updateDraftResult = if (draft == null) {
room.clearComposerDraft()
} else {

View file

@ -49,7 +49,7 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.IntentionalMention
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType
import io.element.android.libraries.matrix.api.room.isDm
@ -98,7 +98,7 @@ import io.element.android.libraries.core.mimetype.MimeTypes.Any as AnyMimeTypes
class MessageComposerPresenter @AssistedInject constructor(
@Assisted private val navigator: MessagesNavigator,
private val appCoroutineScope: CoroutineScope,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val mediaPickerProvider: PickerProvider,
private val featureFlagService: FeatureFlagService,
private val sessionPreferencesStore: SessionPreferencesStore,

View file

@ -9,8 +9,8 @@ package io.element.android.features.messages.impl.messagecomposer.suggestions
import io.element.android.libraries.core.data.filterUpTo
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.room.roomMembers
import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion
@ -33,7 +33,7 @@ class SuggestionsProcessor @Inject constructor() {
*/
suspend fun process(
suggestion: Suggestion?,
roomMembersState: MatrixRoomMembersState,
roomMembersState: RoomMembersState,
roomAliasSuggestions: List<RoomAliasSuggestion>,
currentUserId: UserId,
canSendRoomMention: suspend () -> Boolean,

View file

@ -15,7 +15,7 @@ import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.room.CreateTimelineParams
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
@ -33,7 +33,7 @@ import javax.inject.Inject
@SingleIn(RoomScope::class)
class PinnedEventsTimelineProvider @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val syncService: SyncService,
private val featureFlagService: FeatureFlagService,
private val dispatchers: CoroutineDispatchers,
@ -62,6 +62,7 @@ class PinnedEventsTimelineProvider @Inject constructor(
}
}
.launchIn(scope)
.invokeOnCompletion { timelineStateFlow.value.dataOrNull()?.close() }
}
private suspend fun onActive() = coroutineScope {

View file

@ -20,7 +20,7 @@ import androidx.compose.runtime.setValue
import io.element.android.features.messages.impl.pinned.PinnedEventsTimelineProvider
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -32,7 +32,7 @@ import kotlinx.coroutines.flow.onEach
import javax.inject.Inject
class PinnedMessagesBannerPresenter @Inject constructor(
private val room: MatrixRoom,
private val room: BaseRoom,
private val itemFactory: PinnedMessagesBannerItemFactory,
private val pinnedEventsTimelineProvider: PinnedEventsTimelineProvider,
) : Presenter<PinnedMessagesBannerState> {

View file

@ -38,7 +38,7 @@ import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.powerlevels.canPinUnpin
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOther
import io.element.android.libraries.matrix.api.room.powerlevels.canRedactOwn
@ -60,7 +60,7 @@ import timber.log.Timber
class PinnedMessagesListPresenter @AssistedInject constructor(
@Assisted private val navigator: PinnedMessagesListNavigator,
private val room: MatrixRoom,
private val room: JoinedRoom,
timelineItemsFactoryCreator: TimelineItemsFactory.Creator,
private val timelineProvider: PinnedEventsTimelineProvider,
private val timelineProtectionPresenter: Presenter<TimelineProtectionState>,

View file

@ -25,13 +25,13 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatch
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
class ReportMessagePresenter @AssistedInject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
@Assisted private val inputs: Inputs,
private val snackbarDispatcher: SnackbarDispatcher,
) : Presenter<ReportMessageState> {

View file

@ -12,7 +12,7 @@ import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.CreateTimelineParams
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
@ -42,7 +42,7 @@ import javax.inject.Inject
@SingleIn(RoomScope::class)
@ContributesBinding(RoomScope::class, boundType = TimelineProvider::class)
class TimelineController @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
) : Closeable, TimelineProvider {
private val coroutineScope = CoroutineScope(SupervisorJob())

View file

@ -38,7 +38,7 @@ import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.isDm
import io.element.android.libraries.matrix.api.room.roomMembers
@ -62,7 +62,7 @@ const val FOCUS_ON_PINNED_EVENT_DEBOUNCE_DURATION_IN_MILLIS = 200L
class TimelinePresenter @AssistedInject constructor(
timelineItemsFactoryCreator: TimelineItemsFactory.Creator,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val dispatchers: CoroutineDispatchers,
private val appScope: CoroutineScope,
@Assisted private val navigator: MessagesNavigator,

View file

@ -15,7 +15,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.roomMembers
import io.element.android.libraries.matrix.api.user.MatrixUser
@ -24,7 +24,7 @@ import kotlinx.collections.immutable.toImmutableList
import javax.inject.Inject
class ReactionSummaryPresenter @Inject constructor(
private val room: MatrixRoom,
private val room: BaseRoom,
) : Presenter<ReactionSummaryState> {
@Composable
override fun present(): ReactionSummaryState {

View file

@ -13,19 +13,18 @@ import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
import io.element.android.libraries.matrix.api.media.isPreviewEnabled
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import kotlinx.collections.immutable.toImmutableSet
import javax.inject.Inject
class TimelineProtectionPresenter @Inject constructor(
private val appPreferencesStore: AppPreferencesStore,
private val room: MatrixRoom,
private val room: BaseRoom,
) : Presenter<TimelineProtectionState> {
private val allowedEvents = mutableStateOf<Set<EventId>>(setOf())

View file

@ -18,7 +18,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.roomMembers
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
@ -32,7 +32,7 @@ import kotlinx.coroutines.flow.onEach
import javax.inject.Inject
class TypingNotificationPresenter @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val sessionPreferencesStore: SessionPreferencesStore,
) : Presenter<TypingNotificationState> {
@Composable

View file

@ -51,9 +51,8 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.MessageEventType
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
@ -70,7 +69,8 @@ import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.matrix.test.sync.FakeSyncService
@ -128,19 +128,21 @@ class MessagesPresenterTest {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `present - check that the room's unread flag is removed`() = runTest {
val room = FakeMatrixRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
assertThat(room.markAsReadCalls).isEmpty()
val presenter = createMessagesPresenter(matrixRoom = room)
assertThat(room.baseRoom.markAsReadCalls).isEmpty()
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
runCurrent()
assertThat(room.setUnreadFlagCalls).isEqualTo(listOf(false))
assertThat(room.baseRoom.setUnreadFlagCalls).isEqualTo(listOf(false))
cancelAndIgnoreRemainingEvents()
}
}
@ -155,16 +157,18 @@ class MessagesPresenterTest {
val timeline = FakeTimeline().apply {
this.toggleReactionLambda = toggleReactionSuccess
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = timeline,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers)
val presenter = createMessagesPresenter(joinedRoom = room, coroutineDispatchers = coroutineDispatchers)
presenter.testWithLifecycleOwner {
skipItems(1)
val initialState = awaitItem()
@ -189,16 +193,18 @@ class MessagesPresenterTest {
val timeline = FakeTimeline().apply {
this.toggleReactionLambda = toggleReactionSuccess
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = timeline,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers)
val presenter = createMessagesPresenter(joinedRoom = room, coroutineDispatchers = coroutineDispatchers)
presenter.testWithLifecycleOwner {
val initialState = awaitItem()
initialState.eventSink(MessagesEvents.ToggleReaction("👍", AN_EVENT_ID.toEventOrTransactionId()))
@ -245,18 +251,20 @@ class MessagesPresenterTest {
fun `present - handle action copy link`() = runTest {
val clipboardHelper = FakeClipboardHelper()
val event = aMessageEvent()
val matrixRoom = FakeMatrixRoom(
eventPermalinkResult = { Result.success("a link") },
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
eventPermalinkResult = { Result.success("a link") },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(
clipboardHelper = clipboardHelper,
matrixRoom = matrixRoom,
joinedRoom = room,
)
presenter.testWithLifecycleOwner {
val initialState = awaitItem()
@ -466,20 +474,22 @@ class MessagesPresenterTest {
val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
val liveTimeline = FakeTimeline()
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = liveTimeline,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val redactEventLambda = lambdaRecorder { _: EventOrTransactionId, _: String? -> Result.success(Unit) }
liveTimeline.redactEventLambda = redactEventLambda
val presenter = createMessagesPresenter(
matrixRoom = matrixRoom,
joinedRoom = joinedRoom,
coroutineDispatchers = coroutineDispatchers,
)
presenter.testWithLifecycleOwner {
@ -535,18 +545,19 @@ class MessagesPresenterTest {
@Test
fun `present - shows prompt to reinvite users in DM`() = runTest {
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 1, activeMembersCount = 1))
},
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 1, activeMembersCount = 1))
}
val presenter = createMessagesPresenter(matrixRoom = room)
)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = awaitItem()
// Initially the composer doesn't have focus, so we don't show the alert
@ -567,18 +578,19 @@ class MessagesPresenterTest {
@Test
fun `present - doesn't show reinvite prompt in non-direct room`() = runTest {
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = false, joinedMembersCount = 1, activeMembersCount = 1))
},
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = false, joinedMembersCount = 1, activeMembersCount = 1))
}
val presenter = createMessagesPresenter(matrixRoom = room)
)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = awaitItem()
assertThat(initialState.showReinvitePrompt).isFalse()
@ -592,18 +604,19 @@ class MessagesPresenterTest {
@Test
fun `present - doesn't show reinvite prompt if other party is present`() = runTest {
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 2, activeMembersCount = 2))
},
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(isDirect = true, joinedMembersCount = 2, activeMembersCount = 2))
}
val presenter = createMessagesPresenter(matrixRoom = room)
)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = awaitItem()
assertThat(initialState.showReinvitePrompt).isFalse()
@ -618,25 +631,26 @@ class MessagesPresenterTest {
@Test
fun `present - handle reinviting other user when memberlist is ready`() = runTest {
val inviteUserResult = lambdaRecorder { _: UserId -> Result.success(Unit) }
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
inviteUserResult = inviteUserResult,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
inviteUserResult = inviteUserResult,
)
room.givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(
aRoomMember(userId = A_SESSION_ID, membership = RoomMembershipState.JOIN),
aRoomMember(userId = A_SESSION_ID_2, membership = RoomMembershipState.LEAVE),
)
)
)
val presenter = createMessagesPresenter(matrixRoom = room)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilTimeout().last()
initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
@ -652,18 +666,19 @@ class MessagesPresenterTest {
@Test
fun `present - handle reinviting other user when memberlist is error`() = runTest {
val inviteUserResult = lambdaRecorder { _: UserId -> Result.success(Unit) }
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
inviteUserResult = inviteUserResult,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
inviteUserResult = inviteUserResult,
)
room.givenRoomMembersState(
MatrixRoomMembersState.Error(
RoomMembersState.Error(
failure = Throwable(),
prevRoomMembers = persistentListOf(
aRoomMember(userId = A_SESSION_ID, membership = RoomMembershipState.JOIN),
@ -671,7 +686,7 @@ class MessagesPresenterTest {
)
)
)
val presenter = createMessagesPresenter(matrixRoom = room)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilTimeout().last()
initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
@ -688,17 +703,18 @@ class MessagesPresenterTest {
@Test
fun `present - handle reinviting other user when memberlist is not ready`() = runTest {
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
room.givenRoomMembersState(MatrixRoomMembersState.Unknown)
val presenter = createMessagesPresenter(matrixRoom = room)
room.givenRoomMembersState(RoomMembersState.Unknown)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilTimeout().last()
initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
@ -712,25 +728,26 @@ class MessagesPresenterTest {
@Test
fun `present - handle reinviting other user when inviting fails`() = runTest {
val room = FakeMatrixRoom(
sessionId = A_SESSION_ID,
inviteUserResult = { Result.failure(Throwable("Oops!")) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
inviteUserResult = { Result.failure(Throwable("Oops!")) },
)
room.givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(
aRoomMember(userId = A_SESSION_ID, membership = RoomMembershipState.JOIN),
aRoomMember(userId = A_SESSION_ID_2, membership = RoomMembershipState.LEAVE),
)
)
)
val presenter = createMessagesPresenter(matrixRoom = room)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilTimeout().last()
initialState.eventSink(MessagesEvents.InviteDialogDismissed(InviteDialogAction.Invite))
@ -749,21 +766,23 @@ class MessagesPresenterTest {
@Test
fun `present - permission to post`() = runTest {
val matrixRoom = FakeMatrixRoom(
canUserSendMessageResult = { _, messageEventType ->
when (messageEventType) {
MessageEventType.ROOM_MESSAGE -> Result.success(true)
MessageEventType.REACTION -> Result.success(true)
else -> lambdaError()
}
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
canUserSendMessageResult = { _, messageEventType ->
when (messageEventType) {
MessageEventType.ROOM_MESSAGE -> Result.success(true)
MessageEventType.REACTION -> Result.success(true)
else -> lambdaError()
}
},
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
skipItems(1)
val state = awaitItem()
@ -773,21 +792,23 @@ class MessagesPresenterTest {
@Test
fun `present - no permission to post`() = runTest {
val matrixRoom = FakeMatrixRoom(
canUserSendMessageResult = { _, messageEventType ->
when (messageEventType) {
MessageEventType.ROOM_MESSAGE -> Result.success(false)
MessageEventType.REACTION -> Result.success(false)
else -> lambdaError()
}
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
canUserSendMessageResult = { _, messageEventType ->
when (messageEventType) {
MessageEventType.ROOM_MESSAGE -> Result.success(false)
MessageEventType.REACTION -> Result.success(false)
else -> lambdaError()
}
},
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
val presenter = createMessagesPresenter(joinedRoom = room)
presenter.testWithLifecycleOwner {
// Default value
assertThat(awaitItem().userEventPermissions.canSendMessage).isTrue()
@ -797,15 +818,17 @@ class MessagesPresenterTest {
@Test
fun `present - permission to redact own`() = runTest {
val matrixRoom = FakeMatrixRoom(
canRedactOwnResult = { Result.success(true) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOtherResult = { Result.success(false) },
canUserJoinCallResult = { Result.success(true) },
val joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOtherResult = { Result.success(false) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
)
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
val presenter = createMessagesPresenter(joinedRoom = joinedRoom)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilPredicate { it.userEventPermissions.canRedactOwn }.last()
assertThat(initialState.userEventPermissions.canRedactOwn).isTrue()
@ -816,15 +839,17 @@ class MessagesPresenterTest {
@Test
fun `present - permission to redact other`() = runTest {
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOtherResult = { Result.success(true) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(false) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
),
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createMessagesPresenter(matrixRoom = matrixRoom)
val presenter = createMessagesPresenter(joinedRoom = joinedRoom)
presenter.testWithLifecycleOwner {
val initialState = consumeItemsUntilPredicate { it.userEventPermissions.canRedactOther }.last()
assertThat(initialState.userEventPermissions.canRedactOwn).isFalse()
@ -863,16 +888,18 @@ class MessagesPresenterTest {
val failurePinEventLambda = lambdaRecorder { _: EventId -> Result.failure<Boolean>(A_THROWABLE) }
val analyticsService = FakeAnalyticsService()
val timeline = FakeTimeline()
val room = FakeMatrixRoom(
liveTimeline = timeline,
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createMessagesPresenter(matrixRoom = room, analyticsService = analyticsService)
val presenter = createMessagesPresenter(joinedRoom = room, analyticsService = analyticsService)
presenter.testWithLifecycleOwner {
val messageEvent = aMessageEvent(
content = aTimelineItemTextContent()
@ -901,16 +928,18 @@ class MessagesPresenterTest {
val failureUnpinEventLambda = lambdaRecorder { _: EventId -> Result.failure<Boolean>(A_THROWABLE) }
val timeline = FakeTimeline()
val analyticsService = FakeAnalyticsService()
val room = FakeMatrixRoom(
liveTimeline = timeline,
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createMessagesPresenter(matrixRoom = room, analyticsService = analyticsService)
val presenter = createMessagesPresenter(joinedRoom = room, analyticsService = analyticsService)
presenter.testWithLifecycleOwner {
val messageEvent = aMessageEvent(
content = aTimelineItemTextContent()
@ -1058,17 +1087,19 @@ class MessagesPresenterTest {
val timeline = FakeTimeline().apply {
this.editCaptionLambda = editCaptionLambda
}
val room = FakeMatrixRoom(
liveTimeline = timeline,
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
),
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createMessagesPresenter(
matrixRoom = room,
joinedRoom = room,
)
presenter.testWithLifecycleOwner {
skipItems(1)
@ -1094,21 +1125,23 @@ class MessagesPresenterTest {
@Test
fun `present - when room is encrypted and a DM, the DM user's identity state is fetched onResume`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
sessionId = A_SESSION_ID,
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
initialRoomInfo = aRoomInfo(isDirect = true, isEncrypted = true)
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(aRoomMember(userId = A_SESSION_ID), aRoomMember(userId = A_USER_ID_2))))
}
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(aRoomMember(userId = A_SESSION_ID), aRoomMember(userId = A_USER_ID_2))))
},
typingNoticeResult = { Result.success(Unit) },
)
val encryptionService = FakeEncryptionService(getUserIdentityResult = { Result.success(IdentityState.Verified) })
val presenter = createMessagesPresenter(matrixRoom = room, encryptionService = encryptionService)
val presenter = createMessagesPresenter(joinedRoom = room, encryptionService = encryptionService)
val lifecycleOwner = FakeLifecycleOwner()
presenter.testWithLifecycleOwner(lifecycleOwner) {
val initialState = awaitItem()
@ -1124,16 +1157,19 @@ class MessagesPresenterTest {
private fun TestScope.createMessagesPresenter(
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
matrixRoom: MatrixRoom = FakeMatrixRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
joinedRoom: FakeJoinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserSendMessageResult = { _, _ -> Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(id = roomId, name = ""))
},
liveTimeline = FakeTimeline(),
typingNoticeResult = { Result.success(Unit) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(id = roomId, name = ""))
},
),
navigator: FakeMessagesNavigator = FakeMessagesNavigator(),
featureFlagService: FeatureFlagService = FakeFeatureFlagService(),
clipboardHelper: FakeClipboardHelper = FakeClipboardHelper(),
@ -1150,7 +1186,7 @@ class MessagesPresenterTest {
actionListEventSink: (ActionListEvents) -> Unit = {},
): MessagesPresenter {
return MessagesPresenter(
room = matrixRoom,
room = joinedRoom,
composerPresenter = messageComposerPresenter,
voiceMessageComposerPresenter = { aVoiceMessageComposerState() },
timelinePresenter = { aTimelineState(eventSink = timelineEventSink) },
@ -1171,7 +1207,7 @@ class MessagesPresenterTest {
buildMeta = aBuildMeta(),
dispatchers = coroutineDispatchers,
htmlConverterProvider = FakeHtmlConverterProvider(),
timelineController = TimelineController(matrixRoom),
timelineController = TimelineController(joinedRoom),
permalinkParser = permalinkParser,
encryptionService = encryptionService,
analyticsService = analyticsService,

View file

@ -29,13 +29,13 @@ import io.element.android.features.poll.api.pollcontent.aPollAnswerItemList
import io.element.android.libraries.dateformatter.test.FakeDateFormatter
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_CAPTION
import io.element.android.libraries.matrix.test.A_MESSAGE
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
import io.element.android.tests.testutils.WarmUpRule
@ -893,7 +893,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute message when event is already pinned`() = runTest {
val room = FakeMatrixRoom().apply {
val room = FakeBaseRoom().apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
val presenter = createActionListPresenter(
@ -1251,7 +1251,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for verified user send failure`() = runTest {
val room = FakeMatrixRoom(
val room = FakeBaseRoom(
userDisplayNameResult = { Result.success("Alice") }
)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = false, room = room)
@ -1279,7 +1279,7 @@ class ActionListPresenterTest {
private fun createActionListPresenter(
isDeveloperModeEnabled: Boolean,
isPinFeatureEnabled: Boolean,
room: MatrixRoom = FakeMatrixRoom(),
room: BaseRoom = FakeBaseRoom(),
allowCaption: Boolean = true,
): ActionListPresenter {
val preferencesStore = InMemoryAppPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled)

View file

@ -29,12 +29,12 @@ import io.element.android.libraries.matrix.api.media.FileInfo
import io.element.android.libraries.matrix.api.media.ImageInfo
import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.message.ReplyParameters
import io.element.android.libraries.matrix.test.A_CAPTION
import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler
import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.mediaupload.api.MediaPreProcessor
import io.element.android.libraries.mediaupload.api.MediaSender
import io.element.android.libraries.mediaupload.api.MediaUploadInfo
@ -110,7 +110,7 @@ class AttachmentsPreviewPresenterTest {
lambdaRecorder<File, FileInfo, String?, String?, ProgressCallback?, ReplyParameters?, Result<FakeMediaUploadHandler>> { _, _, _, _, _, _ ->
Result.success(FakeMediaUploadHandler())
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
progressCallbackValues = listOf(
Pair(0, 10),
Pair(5, 10),
@ -148,7 +148,7 @@ class AttachmentsPreviewPresenterTest {
lambdaRecorder<File, FileInfo, String?, String?, ProgressCallback?, ReplyParameters?, Result<FakeMediaUploadHandler>> { _, _, _, _, _, _ ->
Result.success(FakeMediaUploadHandler())
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendFileResult = sendFileResult,
)
val onDoneListener = lambdaRecorder<Unit> { }
@ -184,7 +184,7 @@ class AttachmentsPreviewPresenterTest {
lambdaRecorder<File, FileInfo, String?, String?, ProgressCallback?, ReplyParameters?, Result<FakeMediaUploadHandler>> { _, _, _, _, _, _ ->
Result.success(FakeMediaUploadHandler())
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendFileResult = sendFileResult,
)
val onDoneListener = lambdaRecorder<Unit> { }
@ -216,7 +216,7 @@ class AttachmentsPreviewPresenterTest {
@Test
fun `present - send media with pre-processing failure after user sends media`() = runTest {
val room = FakeMatrixRoom()
val room = FakeJoinedRoom()
val onDoneListener = lambdaRecorder<Unit> { }
val processLatch = CompletableDeferred<Unit>()
val presenter = createAttachmentsPreviewPresenter(
@ -242,7 +242,7 @@ class AttachmentsPreviewPresenterTest {
@Test
fun `present - send media with pre-processing failure before user sends media`() = runTest {
val room = FakeMatrixRoom()
val room = FakeJoinedRoom()
val onDoneListener = lambdaRecorder<Unit> { }
val processLatch = CompletableDeferred<Unit>()
val presenter = createAttachmentsPreviewPresenter(
@ -297,7 +297,7 @@ class AttachmentsPreviewPresenterTest {
val mediaPreProcessor = FakeMediaPreProcessor().apply {
givenImageResult()
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendImageResult = sendImageResult,
)
val onDoneListener = lambdaRecorder<Unit> { }
@ -339,7 +339,7 @@ class AttachmentsPreviewPresenterTest {
val mediaPreProcessor = FakeMediaPreProcessor().apply {
givenVideoResult()
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendVideoResult = sendVideoResult,
)
val onDoneListener = lambdaRecorder<Unit> { }
@ -381,7 +381,7 @@ class AttachmentsPreviewPresenterTest {
val mediaPreProcessor = FakeMediaPreProcessor().apply {
givenAudioResult()
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendAudioResult = sendAudioResult,
)
val onDoneListener = lambdaRecorder<Unit> { }
@ -418,7 +418,7 @@ class AttachmentsPreviewPresenterTest {
lambdaRecorder<File, FileInfo, String?, String?, ProgressCallback?, ReplyParameters?, Result<FakeMediaUploadHandler>> { _, _, _, _, _, _ ->
Result.failure(failure)
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendFileResult = sendFileResult,
)
val presenter = createAttachmentsPreviewPresenter(room = room, mediaUploadOnSendQueueEnabled = false)
@ -448,7 +448,7 @@ class AttachmentsPreviewPresenterTest {
Result.failure(failure)
}
val onDoneListenerResult = lambdaRecorder<Unit> {}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
sendFileResult = sendFileResult,
)
val presenter = createAttachmentsPreviewPresenter(room = room, mediaUploadOnSendQueueEnabled = true, onDoneListener = onDoneListenerResult)
@ -518,7 +518,7 @@ class AttachmentsPreviewPresenterTest {
localMedia: LocalMedia = aLocalMedia(
uri = mockMediaUrl,
),
room: MatrixRoom = FakeMatrixRoom(),
room: JoinedRoom = FakeJoinedRoom(),
permalinkBuilder: PermalinkBuilder = FakePermalinkBuilder(),
mediaPreProcessor: MediaPreProcessor = FakeMediaPreProcessor(),
temporaryUriDeleter: TemporaryUriDeleter = FakeTemporaryUriDeleter(),

View file

@ -13,12 +13,12 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.encryption.identity.IdentityStateChange
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.tests.testutils.WarmUpRule
@ -26,6 +26,7 @@ import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value
import io.element.android.tests.testutils.test
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@ -45,14 +46,15 @@ class IdentityChangeStatePresenterTest {
@Test
fun `present - when the room emits identity change, the presenter emits new state`() = runTest {
val room = FakeMatrixRoom().apply {
val identityStateChanges = MutableStateFlow(emptyList<IdentityStateChange>())
val room = FakeJoinedRoom(identityStateChangesFlow = identityStateChanges).apply {
givenRoomInfo(aRoomInfo(isEncrypted = true))
}
val presenter = createIdentityChangeStatePresenter(room)
presenter.test {
val initialState = awaitItem()
assertThat(initialState.roomMemberIdentityStateChanges).isEmpty()
room.emitIdentityStateChanges(
identityStateChanges.emit(
listOf(
IdentityStateChange(
userId = A_USER_ID_2,
@ -70,12 +72,16 @@ class IdentityChangeStatePresenterTest {
@Test
fun `present - when the clear room emits identity change, the presenter does not emit new state`() = runTest {
val room = FakeMatrixRoom(enableEncryptionResult = { Result.success(Unit) })
val identityStateChanges = MutableStateFlow(emptyList<IdentityStateChange>())
val room = FakeJoinedRoom(
identityStateChangesFlow = identityStateChanges,
enableEncryptionResult = { Result.success(Unit) }
)
val presenter = createIdentityChangeStatePresenter(room)
presenter.test {
val initialState = awaitItem()
assertThat(initialState.roomMemberIdentityStateChanges).isEmpty()
room.emitIdentityStateChanges(
identityStateChanges.emit(
listOf(
IdentityStateChange(
userId = A_USER_ID_2,
@ -100,9 +106,10 @@ class IdentityChangeStatePresenterTest {
@Test
fun `present - when the room emits identity change, the presenter emits new state with member details`() =
runTest {
val room = FakeMatrixRoom().apply {
val identityStateChanges = MutableStateFlow(emptyList<IdentityStateChange>())
val room = FakeJoinedRoom(identityStateChangesFlow = identityStateChanges).apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
listOf(
aRoomMember(
A_USER_ID_2,
@ -117,7 +124,7 @@ class IdentityChangeStatePresenterTest {
presenter.test {
val initialState = awaitItem()
assertThat(initialState.roomMemberIdentityStateChanges).isEmpty()
room.emitIdentityStateChanges(
identityStateChanges.emit(
listOf(
IdentityStateChange(
userId = A_USER_ID_2,
@ -166,7 +173,7 @@ class IdentityChangeStatePresenterTest {
}
private fun createIdentityChangeStatePresenter(
room: MatrixRoom = FakeMatrixRoom(),
room: JoinedRoom = FakeJoinedRoom(),
encryptionService: EncryptionService = FakeEncryptionService(),
): IdentityChangeStatePresenter {
return IdentityChangeStatePresenter(

View file

@ -13,13 +13,13 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser
import io.element.android.features.messages.impl.fixtures.aMessageEvent
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_TRANSACTION_ID
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.test
import kotlinx.coroutines.test.runTest
@ -81,11 +81,13 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user unsigned device failure dismiss scenario`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
)
)
val presenter = createResolveVerifiedUserSendFailurePresenter(room)
presenter.test {
val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage()
@ -107,11 +109,13 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user unsigned device failure retry scenario`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
)
)
val presenter = createResolveVerifiedUserSendFailurePresenter(room)
presenter.test {
val failedMessage = aVerifiedUserHasUnsignedDeviceFailedMessage()
@ -138,10 +142,12 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user unsigned device failure resolve and resend scenario`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
),
ignoreDeviceTrustAndResendResult = { _, _ ->
Result.success(Unit)
},
@ -179,10 +185,12 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user unsigned device failure resolve and resend scenario with error`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
),
ignoreDeviceTrustAndResendResult = { _, _ ->
Result.failure(Exception())
},
@ -212,11 +220,13 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user changed identity failure retry scenario`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
)
)
val presenter = createResolveVerifiedUserSendFailurePresenter(room)
presenter.test {
val failedMessage = aVerifiedUserChangedIdentityMessage()
@ -243,10 +253,12 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user changed identity failure resolve and resend scenario`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
),
withdrawVerificationAndResendResult = { _, _ ->
Result.success(Unit)
},
@ -284,10 +296,12 @@ class ResolveVerifiedUserSendFailurePresenterTest {
@Test
fun `present - verified user changed identity failure resolve and resend scenario with error`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
userDisplayNameResult = { userId ->
Result.success(userId.value)
},
),
withdrawVerificationAndResendResult = { _, _ ->
Result.failure(Exception())
},
@ -337,7 +351,7 @@ class ResolveVerifiedUserSendFailurePresenterTest {
}
private fun createResolveVerifiedUserSendFailurePresenter(
room: MatrixRoom = FakeMatrixRoom(),
room: FakeJoinedRoom = FakeJoinedRoom(),
): ResolveVerifiedUserSendFailurePresenter {
return ResolveVerifiedUserSendFailurePresenter(
room = room,

View file

@ -15,7 +15,7 @@ import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.libraries.matrix.test.timeline.LiveTimelineProvider
@ -49,8 +49,8 @@ class ForwardMessagesPresenterTest {
val timeline = FakeTimeline().apply {
this.forwardEventLambda = forwardEventLambda
}
val room = FakeMatrixRoom(liveTimeline = timeline)
val presenter = aForwardMessagesPresenter(fakeMatrixRoom = room)
val room = FakeJoinedRoom(liveTimeline = timeline)
val presenter = aForwardMessagesPresenter(fakeRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -73,8 +73,8 @@ class ForwardMessagesPresenterTest {
val timeline = FakeTimeline().apply {
this.forwardEventLambda = forwardEventLambda
}
val room = FakeMatrixRoom(liveTimeline = timeline)
val presenter = aForwardMessagesPresenter(fakeMatrixRoom = room)
val room = FakeJoinedRoom(liveTimeline = timeline)
val presenter = aForwardMessagesPresenter(fakeRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -93,11 +93,11 @@ class ForwardMessagesPresenterTest {
private fun CoroutineScope.aForwardMessagesPresenter(
eventId: EventId = AN_EVENT_ID,
fakeMatrixRoom: FakeMatrixRoom = FakeMatrixRoom(),
fakeRoom: FakeJoinedRoom = FakeJoinedRoom(),
coroutineScope: CoroutineScope = this,
) = ForwardMessagesPresenter(
eventId = eventId.value,
timelineProvider = LiveTimelineProvider(fakeMatrixRoom),
timelineProvider = LiveTimelineProvider(fakeRoom),
appCoroutineScope = coroutineScope,
)
}

View file

@ -42,8 +42,8 @@ import io.element.android.libraries.matrix.api.media.VideoInfo
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
import io.element.android.libraries.matrix.api.room.IntentionalMention
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.room.draft.ComposerDraft
import io.element.android.libraries.matrix.api.room.draft.ComposerDraftType
@ -65,7 +65,8 @@ import io.element.android.libraries.matrix.test.A_USER_ID_3
import io.element.android.libraries.matrix.test.A_USER_ID_4
import io.element.android.libraries.matrix.test.permalink.FakePermalinkBuilder
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
@ -267,13 +268,13 @@ class MessageComposerPresenterTest {
val timeline = FakeTimeline().apply {
this.editCaptionLambda = editCaptionLambda
}
val fakeMatrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) }
)
val presenter = createPresenter(
coroutineScope = this,
room = fakeMatrixRoom,
room = joinedRoom,
isRichTextEditorEnabled = false,
)
val permalinkBuilder = FakePermalinkBuilder(permalinkForUserLambda = { Result.success("") })
@ -382,7 +383,7 @@ class MessageComposerPresenterTest {
fun `present - send message with rich text enabled`() = runTest {
val presenter = createPresenter(
coroutineScope = this,
room = FakeMatrixRoom(
room = FakeJoinedRoom(
sendMessageResult = { _, _, _ -> Result.success(Unit) },
typingNoticeResult = { Result.success(Unit) }
),
@ -416,7 +417,7 @@ class MessageComposerPresenterTest {
val presenter = createPresenter(
coroutineScope = this,
isRichTextEditorEnabled = false,
room = FakeMatrixRoom(
room = FakeJoinedRoom(
sendMessageResult = { _, _, _ -> Result.success(Unit) },
typingNoticeResult = { Result.success(Unit) }
),
@ -454,13 +455,13 @@ class MessageComposerPresenterTest {
val timeline = FakeTimeline().apply {
this.editMessageLambda = editMessageLambda
}
val fakeMatrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) }
)
val presenter = createPresenter(
this,
fakeMatrixRoom,
joinedRoom,
)
moleculeFlow(RecompositionMode.Immediate) {
val state = presenter.present()
@ -509,14 +510,14 @@ class MessageComposerPresenterTest {
val roomEditMessageLambda = lambdaRecorder { _: EventId?, _: String, _: String?, _: List<IntentionalMention> ->
Result.success(Unit)
}
val fakeMatrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
editMessageLambda = roomEditMessageLambda,
)
val presenter = createPresenter(
this,
fakeMatrixRoom,
joinedRoom,
)
moleculeFlow(RecompositionMode.Immediate) {
val state = presenter.present()
@ -566,13 +567,13 @@ class MessageComposerPresenterTest {
val timeline = FakeTimeline().apply {
this.editMessageLambda = editMessageLambda
}
val fakeMatrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
)
val presenter = createPresenter(
this,
fakeMatrixRoom,
joinedRoom,
)
moleculeFlow(RecompositionMode.Immediate) {
val state = presenter.present()
@ -618,13 +619,13 @@ class MessageComposerPresenterTest {
val timeline = FakeTimeline().apply {
this.replyMessageLambda = replyMessageLambda
}
val fakeMatrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) }
)
val presenter = createPresenter(
this,
fakeMatrixRoom,
joinedRoom,
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
@ -689,7 +690,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Pick image from gallery`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val onPreviewAttachmentLambda = lambdaRecorder { _: ImmutableList<Attachment> -> }
@ -730,7 +731,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Pick video from gallery`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val onPreviewAttachmentLambda = lambdaRecorder { _: ImmutableList<Attachment> -> }
@ -788,7 +789,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Pick file from storage will open the preview`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val onPreviewAttachmentLambda = lambdaRecorder { _: ImmutableList<Attachment> -> }
@ -811,7 +812,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - create poll`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val presenter = createPresenter(this, room = room)
@ -830,7 +831,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - share location`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val presenter = createPresenter(this, room = room)
@ -849,7 +850,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Take photo`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val permissionPresenter = FakePermissionsPresenter().apply { setPermissionGranted() }
@ -874,7 +875,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Take photo with permission request`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val permissionPresenter = FakePermissionsPresenter()
@ -901,7 +902,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Record video`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val permissionPresenter = FakePermissionsPresenter().apply { setPermissionGranted() }
@ -926,7 +927,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - Record video with permission request`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
)
val permissionPresenter = FakePermissionsPresenter()
@ -1001,12 +1002,12 @@ class MessageComposerPresenterTest {
val bob = aRoomMember(userId = A_USER_ID_2, membership = RoomMembershipState.JOIN)
val david = aRoomMember(userId = A_USER_ID_4, displayName = "Dave", membership = RoomMembershipState.JOIN)
var canUserTriggerRoomNotificationResult = true
val room = FakeMatrixRoom(
canUserTriggerRoomNotificationResult = { Result.success(canUserTriggerRoomNotificationResult) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(canUserTriggerRoomNotificationResult = { Result.success(canUserTriggerRoomNotificationResult) }),
typingNoticeResult = { Result.success(Unit) }
).apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(currentUser, invitedUser, bob, david),
)
)
@ -1057,12 +1058,12 @@ class MessageComposerPresenterTest {
val invitedUser = aRoomMember(userId = A_USER_ID_3, membership = RoomMembershipState.INVITE)
val bob = aRoomMember(userId = A_USER_ID_2, membership = RoomMembershipState.JOIN)
val david = aRoomMember(userId = A_USER_ID_4, displayName = "Dave", membership = RoomMembershipState.JOIN)
val room = FakeMatrixRoom(
canUserTriggerRoomNotificationResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(canUserTriggerRoomNotificationResult = { Result.success(true) }),
typingNoticeResult = { Result.success(Unit) }
).apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(currentUser, invitedUser, bob, david),
)
)
@ -1124,7 +1125,7 @@ class MessageComposerPresenterTest {
val sendMessageResult = lambdaRecorder { _: String, _: String?, _: List<IntentionalMention> ->
Result.success(Unit)
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = timeline,
sendMessageResult = sendMessageResult,
typingNoticeResult = { Result.success(Unit) }
@ -1206,8 +1207,8 @@ class MessageComposerPresenterTest {
@Test
fun `present - handle typing notice event`() = runTest {
val typingNoticeResult = lambdaRecorder<Boolean, Result<Unit>> { Result.success(Unit) }
val room = FakeMatrixRoom(
typingNoticeResult = typingNoticeResult
val room = FakeJoinedRoom(
typingNoticeResult = typingNoticeResult,
)
val presenter = createPresenter(room = room, coroutineScope = this)
moleculeFlow(RecompositionMode.Immediate) {
@ -1217,6 +1218,7 @@ class MessageComposerPresenterTest {
typingNoticeResult.assertions().isNeverCalled()
initialState.eventSink.invoke(MessageComposerEvents.TypingNotice(true))
initialState.eventSink.invoke(MessageComposerEvents.TypingNotice(false))
advanceUntilIdle()
typingNoticeResult.assertions().isCalledExactly(2)
.withSequence(
listOf(value(true)),
@ -1228,7 +1230,7 @@ class MessageComposerPresenterTest {
@Test
fun `present - handle typing notice event when sending typing notice is disabled`() = runTest {
val typingNoticeResult = lambdaRecorder<Boolean, Result<Unit>> { Result.success(Unit) }
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
typingNoticeResult = typingNoticeResult
)
val store = InMemorySessionPreferencesStore(
@ -1383,7 +1385,7 @@ class MessageComposerPresenterTest {
val timeline = FakeTimeline().apply {
this.loadReplyDetailsLambda = loadReplyDetailsLambda
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = timeline,
typingNoticeResult = { Result.success(Unit) },
)
@ -1524,7 +1526,7 @@ class MessageComposerPresenterTest {
private fun createPresenter(
coroutineScope: CoroutineScope,
room: MatrixRoom = FakeMatrixRoom(
room: JoinedRoom = FakeJoinedRoom(
typingNoticeResult = { Result.success(Unit) }
),
navigator: MessagesNavigator = FakeMessagesNavigator(),

View file

@ -9,7 +9,7 @@ package io.element.android.features.messages.impl.messagecomposer.suggestions
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
import io.element.android.libraries.matrix.test.A_USER_ID
@ -35,7 +35,7 @@ class SuggestionsProcessorTest {
fun `processing null suggestion will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = null,
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember())),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -47,7 +47,7 @@ class SuggestionsProcessorTest {
fun `processing Command will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = aCommandSuggestion,
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember())),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -59,7 +59,7 @@ class SuggestionsProcessorTest {
fun `processing Custom will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = aCustomSuggestion,
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember())),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember())),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -71,7 +71,7 @@ class SuggestionsProcessorTest {
fun `processing Mention suggestion with not loaded members will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion(""),
roomMembersState = MatrixRoomMembersState.Unknown,
roomMembersState = RoomMembersState.Unknown,
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -83,7 +83,7 @@ class SuggestionsProcessorTest {
fun `processing Mention suggestion with no members will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion(""),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -95,7 +95,7 @@ class SuggestionsProcessorTest {
fun `processing Room suggestion with no aliases will return empty suggestion`() = runTest {
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion(""),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID,
canSendRoomMention = { true },
@ -108,7 +108,7 @@ class SuggestionsProcessorTest {
val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS)
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion("ALI"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
@ -137,7 +137,7 @@ class SuggestionsProcessorTest {
val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS)
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion("ali"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
@ -166,7 +166,7 @@ class SuggestionsProcessorTest {
val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS)
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion("tot"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
@ -186,7 +186,7 @@ class SuggestionsProcessorTest {
val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS)
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion("lement"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
@ -215,7 +215,7 @@ class SuggestionsProcessorTest {
val aRoomSummary = aRoomSummary(canonicalAlias = A_ROOM_ALIAS)
val result = suggestionsProcessor.process(
suggestion = aRoomSuggestion("lement"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf()),
roomMembersState = RoomMembersState.Ready(persistentListOf()),
roomAliasSuggestions = listOf(
RoomAliasSuggestion(
roomAlias = A_ROOM_ALIAS,
@ -235,7 +235,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = null)
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("ali"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { true },
@ -252,7 +252,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = null)
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("ali"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = UserId("@alice:server.org"),
canSendRoomMention = { true },
@ -265,7 +265,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "alice")
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("bo"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { true },
@ -278,7 +278,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), membership = RoomMembershipState.INVITE)
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("ali"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { true },
@ -291,7 +291,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "bob")
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("bo"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { true },
@ -308,7 +308,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "ro")
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("ro"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { true },
@ -326,7 +326,7 @@ class SuggestionsProcessorTest {
val aRoomMember = aRoomMember(userId = UserId("@alice:server.org"), displayName = "ro")
val result = suggestionsProcessor.process(
suggestion = aMentionSuggestion("ro"),
roomMembersState = MatrixRoomMembersState.Ready(persistentListOf(aRoomMember)),
roomMembersState = RoomMembersState.Ready(persistentListOf(aRoomMember)),
roomAliasSuggestions = emptyList(),
currentUserId = A_USER_ID_2,
canSendRoomMention = { false },

View file

@ -12,14 +12,14 @@ import io.element.android.features.messages.impl.pinned.PinnedEventsTimelineProv
import io.element.android.libraries.eventformatter.test.FakePinnedMessagesBannerFormatter
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.AN_EVENT_ID_2
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.sync.FakeSyncService
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
@ -54,7 +54,7 @@ class PinnedMessagesBannerPresenterTest {
@Test
fun `present - loading state`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
createTimelineResult = { Result.success(FakeTimeline()) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
@ -85,7 +85,7 @@ class PinnedMessagesBannerPresenterTest {
)
)
)
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID, AN_EVENT_ID_2)))
@ -124,7 +124,7 @@ class PinnedMessagesBannerPresenterTest {
)
)
)
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID, AN_EVENT_ID_2)))
@ -159,7 +159,7 @@ class PinnedMessagesBannerPresenterTest {
@Test
fun `present - timeline failed`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
createTimelineResult = { Result.failure(Exception()) }
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
@ -179,7 +179,7 @@ class PinnedMessagesBannerPresenterTest {
}
private fun TestScope.createPinnedMessagesBannerPresenter(
room: MatrixRoom = FakeMatrixRoom(),
room: JoinedRoom = FakeJoinedRoom(),
itemFactory: PinnedMessagesBannerItemFactory = PinnedMessagesBannerItemFactory(
coroutineDispatchers = testCoroutineDispatchers(),
formatter = FakePinnedMessagesBannerFormatter(

View file

@ -20,14 +20,15 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatch
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.sync.FakeSyncService
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
@ -51,11 +52,13 @@ import org.junit.Test
class PinnedMessagesListPresenterTest {
@Test
fun `present - initial state feature disabled`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
)
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = false)
presenter.test {
val initialState = awaitItem()
@ -66,13 +69,15 @@ class PinnedMessagesListPresenterTest {
@Test
fun `present - initial state feature enabled`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
presenter.test {
val initialState = awaitItem()
@ -83,14 +88,16 @@ class PinnedMessagesListPresenterTest {
@Test
fun `present - timeline failure state`() = runTest {
val room = FakeMatrixRoom(
createTimelineResult = { Result.failure(RuntimeException()) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.failure(RuntimeException()) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -102,14 +109,16 @@ class PinnedMessagesListPresenterTest {
@Test
fun `present - empty state`() = runTest {
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(FakeTimeline()) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf()))
}
},
createTimelineResult = { Result.success(FakeTimeline()) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -122,14 +131,16 @@ class PinnedMessagesListPresenterTest {
@Test
fun `present - filled state`() = runTest {
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -149,14 +160,16 @@ class PinnedMessagesListPresenterTest {
val failureUnpinEventLambda = lambdaRecorder { _: EventId? -> Result.failure<Boolean>(A_THROWABLE) }
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val analyticsService = FakeAnalyticsService()
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true, analyticsService = analyticsService)
presenter.test {
skipItems(3)
@ -195,14 +208,16 @@ class PinnedMessagesListPresenterTest {
this.onViewInTimelineClickLambda = onViewInTimelineClickLambda
}
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -224,14 +239,16 @@ class PinnedMessagesListPresenterTest {
this.onShowEventDebugInfoClickLambda = onShowEventDebugInfoClickLambda
}
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -253,14 +270,16 @@ class PinnedMessagesListPresenterTest {
this.onForwardEventClickLambda = onForwardEventClickLambda
}
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeMatrixRoom(
createTimelineResult = { Result.success(pinnedEventsTimeline) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true)
presenter.test {
skipItems(3)
@ -294,7 +313,7 @@ class PinnedMessagesListPresenterTest {
private fun TestScope.createPinnedMessagesListPresenter(
navigator: PinnedMessagesListNavigator = FakePinnedMessagesListNavigator(),
room: MatrixRoom = FakeMatrixRoom(),
room: JoinedRoom = FakeJoinedRoom(),
syncService: SyncService = FakeSyncService(),
isFeatureEnabled: Boolean = true,
analyticsService: AnalyticsService = FakeAnalyticsService(),

View file

@ -15,10 +15,10 @@ import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.lambda.lambdaRecorder
import kotlinx.coroutines.test.runTest
@ -78,10 +78,10 @@ class ReportMessagePresenterTest {
val reportContentResult = lambdaRecorder<EventId, String, UserId?, Result<Unit>> { _, _, _ ->
Result.success(Unit)
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
reportContentResult = reportContentResult
)
val presenter = createReportMessagePresenter(matrixRoom = room)
val presenter = createReportMessagePresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -100,10 +100,10 @@ class ReportMessagePresenterTest {
val reportContentResult = lambdaRecorder<EventId, String, UserId?, Result<Unit>> { _, _, _ ->
Result.success(Unit)
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
reportContentResult = reportContentResult
)
val presenter = createReportMessagePresenter(matrixRoom = room)
val presenter = createReportMessagePresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -120,10 +120,10 @@ class ReportMessagePresenterTest {
val reportContentResult = lambdaRecorder<EventId, String, UserId?, Result<Unit>> { _, _, _ ->
Result.failure(Exception("Failed to report content"))
}
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
reportContentResult = reportContentResult
)
val presenter = createReportMessagePresenter(matrixRoom = room)
val presenter = createReportMessagePresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -141,11 +141,11 @@ class ReportMessagePresenterTest {
private fun createReportMessagePresenter(
inputs: ReportMessagePresenter.Inputs = ReportMessagePresenter.Inputs(AN_EVENT_ID, A_USER_ID),
matrixRoom: MatrixRoom = FakeMatrixRoom(),
joinedRoom: JoinedRoom = FakeJoinedRoom(),
snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(),
) = ReportMessagePresenter(
inputs = inputs,
room = matrixRoom,
room = joinedRoom,
snackbarDispatcher = snackbarDispatcher,
)
}

View file

@ -14,7 +14,7 @@ import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
import io.element.android.tests.testutils.lambda.lambdaError
@ -29,11 +29,11 @@ class TimelineControllerTest {
fun `test switching between live and detached timeline`() = runTest {
val liveTimeline = FakeTimeline(name = "live")
val detachedTimeline = FakeTimeline(name = "detached")
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = { Result.success(detachedTimeline) }
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
awaitItem().also { state ->
@ -61,7 +61,7 @@ class TimelineControllerTest {
val detachedTimeline1 = FakeTimeline(name = "detached 1")
val detachedTimeline2 = FakeTimeline(name = "detached 2")
var callNumber = 0
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = {
callNumber++
@ -72,7 +72,7 @@ class TimelineControllerTest {
}
}
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
awaitItem().also { state ->
@ -97,10 +97,10 @@ class TimelineControllerTest {
@Test
fun `test switching to live when already in live should have no effect`() = runTest {
val liveTimeline = FakeTimeline(name = "live")
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
awaitItem().also { state ->
assertThat(state).isEqualTo(liveTimeline)
@ -115,11 +115,11 @@ class TimelineControllerTest {
fun `test closing the TimelineController should close the detached timeline`() = runTest {
val liveTimeline = FakeTimeline(name = "live")
val detachedTimeline = FakeTimeline(name = "detached")
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = { Result.success(detachedTimeline) }
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
awaitItem().also { state ->
assertThat(state).isEqualTo(liveTimeline)
@ -144,10 +144,10 @@ class TimelineControllerTest {
)
)
)
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
assertThat(sut.timelineItems().first()).hasSize(1)
}
@ -165,11 +165,11 @@ class TimelineControllerTest {
val detachedTimeline = FakeTimeline(name = "detached").apply {
sendMessageLambda = lambdaForDetached
}
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = { Result.success(detachedTimeline) }
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
sut.focusOnEvent(AN_EVENT_ID)
awaitItem().also { state ->
@ -190,11 +190,11 @@ class TimelineControllerTest {
fun `test last forward pagination on a detached timeline should switch to live timeline`() = runTest {
val liveTimeline = FakeTimeline(name = "live")
val detachedTimeline = FakeTimeline(name = "detached")
val matrixRoom = FakeMatrixRoom(
val joinedRoom = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = { Result.success(detachedTimeline) }
)
val sut = TimelineController(matrixRoom)
val sut = TimelineController(joinedRoom)
sut.activeTimelineFlow().test {
awaitItem().also { state ->

View file

@ -30,7 +30,7 @@ import io.element.android.features.poll.test.actions.FakeSendPollResponseAction
import io.element.android.features.roomcall.api.aStandByCallState
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UniqueId
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.ReceiptType
import io.element.android.libraries.matrix.api.timeline.Timeline
@ -43,7 +43,8 @@ import io.element.android.libraries.matrix.test.AN_EVENT_ID_2
import io.element.android.libraries.matrix.test.A_UNIQUE_ID
import io.element.android.libraries.matrix.test.A_UNIQUE_ID_2
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.libraries.matrix.test.timeline.aMessageContent
@ -128,9 +129,9 @@ import kotlin.time.Duration.Companion.seconds
)
)
)
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = timeline,
canUserSendMessageResult = { _, _ -> Result.success(true) },
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) })
)
val sessionPreferencesStore = InMemorySessionPreferencesStore(isSendPublicReadReceiptsEnabled = false)
val presenter = createTimelinePresenter(
@ -144,7 +145,7 @@ import kotlin.time.Duration.Companion.seconds
val initialState = awaitFirstItem()
initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(0))
runCurrent()
assertThat(room.markAsReadCalls).isNotEmpty()
assertThat(room.baseRoom.markAsReadCalls).isNotEmpty()
cancelAndIgnoreRemainingEvents()
}
}
@ -481,10 +482,10 @@ import kotlin.time.Duration.Companion.seconds
val liveTimeline = FakeTimeline(
timelineItems = flowOf(emptyList())
)
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = liveTimeline,
createTimelineResult = { Result.success(detachedTimeline) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
)
val presenter = createTimelinePresenter(
room = room,
@ -523,7 +524,7 @@ import kotlin.time.Duration.Companion.seconds
process(listOf(aMessageEvent(eventId = AN_EVENT_ID)))
}
val presenter = createTimelinePresenter(
room = FakeMatrixRoom(
room = FakeJoinedRoom(
liveTimeline = FakeTimeline(
timelineItems = flowOf(
listOf(
@ -534,7 +535,7 @@ import kotlin.time.Duration.Companion.seconds
)
)
),
canUserSendMessageResult = { _, _ -> Result.success(true) },
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
),
timelineItemIndexer = timelineItemIndexer,
)
@ -557,12 +558,12 @@ import kotlin.time.Duration.Companion.seconds
@Test
fun `present - focus on event error case`() = runTest {
val presenter = createTimelinePresenter(
room = FakeMatrixRoom(
room = FakeJoinedRoom(
liveTimeline = FakeTimeline(
timelineItems = flowOf(emptyList()),
),
createTimelineResult = { Result.failure(Throwable("An error")) },
canUserSendMessageResult = { _, _ -> Result.success(true) },
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -628,11 +629,11 @@ import kotlin.time.Duration.Companion.seconds
)
)
)
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = timeline,
canUserSendMessageResult = { _, _ -> Result.success(true) },
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
).apply {
givenRoomMembersState(MatrixRoomMembersState.Unknown)
givenRoomMembersState(RoomMembersState.Unknown)
}
val avatarUrl = "https://domain.com/avatar.jpg"
@ -647,7 +648,7 @@ import kotlin.time.Duration.Companion.seconds
assertThat(event.readReceiptState.receipts.first().avatarData.url).isNull()
room.givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(aRoomMember(userId = A_USER_ID, avatarUrl = avatarUrl))
)
)
@ -663,9 +664,9 @@ import kotlin.time.Duration.Companion.seconds
private fun TestScope.createTimelinePresenter(
timeline: Timeline = FakeTimeline(),
room: FakeMatrixRoom = FakeMatrixRoom(
room: FakeJoinedRoom = FakeJoinedRoom(
liveTimeline = timeline,
canUserSendMessageResult = { _, _ -> Result.success(true) }
baseRoom = FakeBaseRoom(canUserSendMessageResult = { _, _ -> Result.success(true) }),
),
redactedVoiceMessageManager: RedactedVoiceMessageManager = FakeRedactedVoiceMessageManager(),
messagesNavigator: FakeMessagesNavigator = FakeMessagesNavigator(),

View file

@ -12,12 +12,12 @@ import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.messages.impl.timeline.model.anAggregatedReaction
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_NAME
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.collections.immutable.persistentListOf
@ -32,8 +32,8 @@ class ReactionSummaryPresenterTest {
private val aggregatedReaction = anAggregatedReaction(userId = A_USER_ID, key = "👍", isHighlighted = true)
private val roomMember = aRoomMember(userId = A_USER_ID, avatarUrl = AN_AVATAR_URL, displayName = A_USER_NAME)
private val summaryEvent = ReactionSummaryEvents.ShowReactionSummary(AN_EVENT_ID, listOf(aggregatedReaction), aggregatedReaction.key)
private val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
private val room = FakeBaseRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(roomMember)))
}
private val presenter = ReactionSummaryPresenter(room)

View file

@ -9,10 +9,10 @@ package io.element.android.features.messages.impl.timeline.protection
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
@ -55,7 +55,7 @@ class TimelineProtectionPresenterTest {
@Test
fun `present - media preview value private in public room`() = runTest {
val appPreferencesStore = InMemoryAppPreferencesStore(timelineMediaPreviewValue = MediaPreviewValue.Private)
val room = FakeMatrixRoom(initialRoomInfo = aRoomInfo(joinRule = JoinRule.Public))
val room = FakeBaseRoom(initialRoomInfo = aRoomInfo(joinRule = JoinRule.Public))
val presenter = createPresenter(appPreferencesStore, room)
presenter.test {
skipItems(1)
@ -72,7 +72,7 @@ class TimelineProtectionPresenterTest {
@Test
fun `present - media preview value private in non public room`() = runTest {
val appPreferencesStore = InMemoryAppPreferencesStore(timelineMediaPreviewValue = MediaPreviewValue.Private)
val room = FakeMatrixRoom(initialRoomInfo = aRoomInfo(joinRule = JoinRule.Invite))
val room = FakeBaseRoom(initialRoomInfo = aRoomInfo(joinRule = JoinRule.Invite))
val presenter = createPresenter(appPreferencesStore, room)
presenter.test {
val initialState = awaitItem()
@ -85,7 +85,7 @@ class TimelineProtectionPresenterTest {
private fun createPresenter(
appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(),
room: MatrixRoom = FakeMatrixRoom(),
room: BaseRoom = FakeBaseRoom(),
) = TimelineProtectionPresenter(
appPreferencesStore = appPreferencesStore,
room = room,

View file

@ -13,19 +13,20 @@ import app.cash.turbine.Event
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.A_USER_ID_3
import io.element.android.libraries.matrix.test.A_USER_ID_4
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@ -50,12 +51,13 @@ class TypingNotificationPresenterTest {
@Test
fun `present - typing notification disabled`() = runTest {
val room = FakeMatrixRoom()
val typingMembersFlow = MutableStateFlow<List<UserId>>(emptyList())
val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow)
val sessionPreferencesStore = InMemorySessionPreferencesStore(
isRenderTypingNotificationsEnabled = false
isRenderTypingNotificationsEnabled = false,
)
val presenter = createPresenter(
matrixRoom = room,
joinedRoom = room,
sessionPreferencesStore = sessionPreferencesStore,
)
moleculeFlow(RecompositionMode.Immediate) {
@ -65,7 +67,7 @@ class TypingNotificationPresenterTest {
val initialState = awaitItem()
assertThat(initialState.renderTypingNotifications).isFalse()
assertThat(initialState.typingMembers).isEmpty()
room.givenRoomTypingMembers(listOf(A_USER_ID_2))
typingMembersFlow.emit(listOf(A_USER_ID_2))
expectNoEvents()
// Preferences changes
sessionPreferencesStore.setRenderTypingNotifications(true)
@ -89,14 +91,15 @@ class TypingNotificationPresenterTest {
@Test
fun `present - state is updated when a member is typing, member is not known`() = runTest {
val room = FakeMatrixRoom()
val presenter = createPresenter(matrixRoom = room)
val typingMembersFlow = MutableStateFlow<List<UserId>>(emptyList())
val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow)
val presenter = createPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.typingMembers).isEmpty()
room.givenRoomTypingMembers(listOf(A_USER_ID_2))
typingMembersFlow.emit(listOf(A_USER_ID_2))
val oneMemberTypingState = awaitItem()
assertThat(oneMemberTypingState.typingMembers.size).isEqualTo(1)
assertThat(oneMemberTypingState.typingMembers.first()).isEqualTo(
@ -105,7 +108,7 @@ class TypingNotificationPresenterTest {
)
)
// User stops typing
room.givenRoomTypingMembers(emptyList())
typingMembersFlow.emit(emptyList())
skipItems(1)
val finalState = awaitItem()
assertThat(finalState.typingMembers).isEmpty()
@ -115,9 +118,10 @@ class TypingNotificationPresenterTest {
@Test
fun `present - state is updated when a member is typing, member is known`() = runTest {
val aKnownRoomMember = createKnownRoomMember(userId = A_USER_ID_2)
val room = FakeMatrixRoom().apply {
val typingMembersFlow = MutableStateFlow<List<UserId>>(emptyList())
val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow).apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
listOf(
createKnownRoomMember(A_USER_ID),
aKnownRoomMember,
@ -127,13 +131,13 @@ class TypingNotificationPresenterTest {
)
)
}
val presenter = createPresenter(matrixRoom = room)
val presenter = createPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.typingMembers).isEmpty()
room.givenRoomTypingMembers(listOf(A_USER_ID_2))
typingMembersFlow.emit(listOf(A_USER_ID_2))
val oneMemberTypingState = awaitItem()
assertThat(oneMemberTypingState.typingMembers.size).isEqualTo(1)
assertThat(oneMemberTypingState.typingMembers.first()).isEqualTo(
@ -142,7 +146,7 @@ class TypingNotificationPresenterTest {
)
)
// User stops typing
room.givenRoomTypingMembers(emptyList())
typingMembersFlow.emit(emptyList())
skipItems(1)
val finalState = awaitItem()
assertThat(finalState.typingMembers).isEmpty()
@ -152,14 +156,15 @@ class TypingNotificationPresenterTest {
@Test
fun `present - state is updated when a member is typing, member is not known, then known`() = runTest {
val aKnownRoomMember = createKnownRoomMember(A_USER_ID_2)
val room = FakeMatrixRoom()
val presenter = createPresenter(matrixRoom = room)
val typingMembersFlow = MutableStateFlow<List<UserId>>(emptyList())
val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow)
val presenter = createPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.typingMembers).isEmpty()
room.givenRoomTypingMembers(listOf(A_USER_ID_2))
typingMembersFlow.emit(listOf(A_USER_ID_2))
val oneMemberTypingState = awaitItem()
assertThat(oneMemberTypingState.typingMembers.size).isEqualTo(1)
assertThat(oneMemberTypingState.typingMembers.first()).isEqualTo(
@ -169,7 +174,7 @@ class TypingNotificationPresenterTest {
)
// User is getting known
room.givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
listOf(aKnownRoomMember).toImmutableList()
)
)
@ -185,19 +190,20 @@ class TypingNotificationPresenterTest {
@Test
fun `present - reserveSpace becomes true once we get the first typing notification with room members`() = runTest {
val room = FakeMatrixRoom()
val presenter = createPresenter(matrixRoom = room)
val typingMembersFlow = MutableStateFlow<List<UserId>>(emptyList())
val room = FakeJoinedRoom(roomTypingMembersFlow = typingMembersFlow)
val presenter = createPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
assertThat(initialState.typingMembers).isEmpty()
room.givenRoomTypingMembers(listOf(A_USER_ID_2))
typingMembersFlow.emit(listOf(A_USER_ID_2))
skipItems(1)
val updatedTypingState = awaitItem()
assertThat(updatedTypingState.reserveSpace).isTrue()
// User stops typing
room.givenRoomTypingMembers(emptyList())
typingMembersFlow.emit(emptyList())
// Is still true for all future events
val futureEvents = cancelAndConsumeRemainingEvents()
for (event in futureEvents) {
@ -209,14 +215,14 @@ class TypingNotificationPresenterTest {
}
private fun createPresenter(
matrixRoom: MatrixRoom = FakeMatrixRoom().apply {
joinedRoom: JoinedRoom = FakeJoinedRoom().apply {
givenRoomInfo(aRoomInfo(id = roomId, name = ""))
},
sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(
isRenderTypingNotificationsEnabled = true
),
) = TypingNotificationPresenter(
room = matrixRoom,
room = joinedRoom,
sessionPreferencesStore = sessionPreferencesStore,
)

View file

@ -23,7 +23,7 @@ import io.element.android.libraries.matrix.api.core.ProgressCallback
import io.element.android.libraries.matrix.api.media.AudioInfo
import io.element.android.libraries.matrix.api.room.message.ReplyParameters
import io.element.android.libraries.matrix.test.media.FakeMediaUploadHandler
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer
import io.element.android.libraries.mediaupload.api.MediaSender
import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor
@ -64,11 +64,11 @@ class VoiceMessageComposerPresenterTest {
lambdaRecorder<File, AudioInfo, List<Float>, ProgressCallback?, ReplyParameters?, Result<FakeMediaUploadHandler>> { _, _, _, _, _ ->
Result.success(FakeMediaUploadHandler())
}
private val matrixRoom = FakeMatrixRoom(
private val joinedRoom = FakeJoinedRoom(
sendVoiceMessageResult = sendVoiceMessageResult
)
private val mediaPreProcessor = FakeMediaPreProcessor().apply { givenAudioResult() }
private val mediaSender = MediaSender(mediaPreProcessor, matrixRoom, InMemorySessionPreferencesStore())
private val mediaSender = MediaSender(mediaPreProcessor, joinedRoom, InMemorySessionPreferencesStore())
private val messageComposerContext = FakeMessageComposerContext()
companion object {

View file

@ -12,13 +12,13 @@ import im.vector.app.features.analytics.plan.PollEnd
import io.element.android.features.poll.api.actions.EndPollAction
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.services.analytics.api.AnalyticsService
import javax.inject.Inject
@ContributesBinding(RoomScope::class)
class DefaultEndPollAction @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val analyticsService: AnalyticsService,
) : EndPollAction {
override suspend fun execute(pollStartId: EventId): Result<Unit> {

View file

@ -12,13 +12,13 @@ import im.vector.app.features.analytics.plan.PollVote
import io.element.android.features.poll.api.actions.SendPollResponseAction
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.services.analytics.api.AnalyticsService
import javax.inject.Inject
@ContributesBinding(RoomScope::class)
class DefaultSendPollResponseAction @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val analyticsService: AnalyticsService,
) : SendPollResponseAction {
override suspend fun execute(pollStartId: EventId, answerId: String): Result<Unit> {

View file

@ -9,7 +9,7 @@ package io.element.android.features.poll.impl.data
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
import io.element.android.libraries.matrix.api.timeline.getActiveTimeline
@ -19,7 +19,7 @@ import kotlinx.coroutines.flow.first
import javax.inject.Inject
class PollRepository @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val timelineProvider: TimelineProvider,
) {
suspend fun getPoll(eventId: EventId): Result<PollContent> = runCatching {

View file

@ -23,7 +23,7 @@ import io.element.android.features.poll.impl.history.model.PollHistoryFilter
import io.element.android.features.poll.impl.history.model.PollHistoryItems
import io.element.android.features.poll.impl.history.model.PollHistoryItemsFactory
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.timeline.Timeline
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.map
@ -35,7 +35,7 @@ class PollHistoryPresenter @Inject constructor(
private val sendPollResponseAction: SendPollResponseAction,
private val endPollAction: EndPollAction,
private val pollHistoryItemFactory: PollHistoryItemsFactory,
private val room: MatrixRoom,
private val room: JoinedRoom,
) : Presenter<PollHistoryState> {
@Composable
override fun present(): PollHistoryState {

View file

@ -21,12 +21,11 @@ import io.element.android.features.poll.impl.anOngoingPollContent
import io.element.android.features.poll.impl.data.PollRepository
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.poll.PollKind
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
import io.element.android.libraries.matrix.api.timeline.item.event.toEventOrTransactionId
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.libraries.matrix.test.timeline.LiveTimelineProvider
import io.element.android.services.analytics.test.FakeAnalyticsService
@ -52,7 +51,7 @@ class CreatePollPresenterTest {
private val timeline = FakeTimeline(
timelineItems = aPollTimelineItems(mapOf(pollEventId to existingPoll))
)
private val fakeMatrixRoom = FakeMatrixRoom(
private val fakeJoinedRoom = FakeJoinedRoom(
liveTimeline = timeline
)
private val fakeAnalyticsService = FakeAnalyticsService()
@ -81,7 +80,7 @@ class CreatePollPresenterTest {
@Test
fun `in edit mode, if poll doesn't exist, error is tracked and screen is closed`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
liveTimeline = FakeTimeline()
)
val presenter = createCreatePollPresenter(mode = CreatePollMode.EditPoll(AN_EVENT_ID), room = room)
@ -121,7 +120,7 @@ class CreatePollPresenterTest {
fun `create poll sends a poll start event`() = runTest {
val createPollResult = lambdaRecorder<String, List<String>, Int, PollKind, Result<Unit>> { _, _, _, _ -> Result.success(Unit) }
val presenter = createCreatePollPresenter(
room = FakeMatrixRoom(
room = FakeJoinedRoom(
createPollResult = createPollResult
),
mode = CreatePollMode.NewPoll,
@ -169,7 +168,7 @@ class CreatePollPresenterTest {
Result.failure(error)
}
val presenter = createCreatePollPresenter(
room = FakeMatrixRoom(
room = FakeJoinedRoom(
createPollResult = createPollResult
),
mode = CreatePollMode.NewPoll,
@ -258,7 +257,7 @@ class CreatePollPresenterTest {
Result.failure<Unit>(error)
}
val presenter = createCreatePollPresenter(
room = FakeMatrixRoom(
room = FakeJoinedRoom(
editPollResult = editPollResult,
liveTimeline = timeline,
),
@ -551,7 +550,7 @@ class CreatePollPresenterTest {
private fun createCreatePollPresenter(
mode: CreatePollMode = CreatePollMode.NewPoll,
room: MatrixRoom = fakeMatrixRoom,
room: FakeJoinedRoom = fakeJoinedRoom,
): CreatePollPresenter = CreatePollPresenter(
repository = PollRepository(room, LiveTimelineProvider(room)),
analyticsService = fakeAnalyticsService,

View file

@ -22,12 +22,11 @@ import io.element.android.features.poll.impl.model.DefaultPollContentStateFactor
import io.element.android.features.poll.test.actions.FakeEndPollAction
import io.element.android.features.poll.test.actions.FakeSendPollResponseAction
import io.element.android.libraries.dateformatter.test.FakeDateFormatter
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.AN_EVENT_ID_2
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.FakeJoinedRoom
import io.element.android.libraries.matrix.test.timeline.FakeTimeline
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.lambda.assert
@ -57,7 +56,7 @@ class PollHistoryPresenterTest {
),
backwardPaginationStatus = backwardPaginationStatus
)
private val room = FakeMatrixRoom(
private val room = FakeJoinedRoom(
liveTimeline = timeline
)
@ -155,7 +154,7 @@ class PollHistoryPresenterTest {
}
private fun TestScope.createPollHistoryPresenter(
room: MatrixRoom = FakeMatrixRoom(),
room: FakeJoinedRoom = FakeJoinedRoom(),
appCoroutineScope: CoroutineScope = this,
endPollAction: EndPollAction = FakeEndPollAction(),
sendPollResponseAction: SendPollResponseAction = FakeSendPollResponseAction(),

View file

@ -16,12 +16,12 @@ import io.element.android.features.call.api.CurrentCall
import io.element.android.features.call.api.CurrentCallService
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.ui.room.canCall
import javax.inject.Inject
class RoomCallStatePresenter @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val currentCallService: CurrentCallService,
) : Presenter<RoomCallState> {
@Composable

View file

@ -12,8 +12,9 @@ import io.element.android.features.call.api.CurrentCall
import io.element.android.features.call.api.CurrentCallService
import io.element.android.features.call.test.FakeCurrentCallService
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.tests.testutils.test
import kotlinx.coroutines.flow.MutableStateFlow
@ -23,10 +24,12 @@ import org.junit.Test
class RoomCallStatePresenterTest {
@Test
fun `present - initial state`() = runTest {
val room = FakeMatrixRoom(
canUserJoinCallResult = { Result.success(false) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserJoinCallResult = { Result.success(false) },
)
)
val presenter = createRoomCallStatePresenter(matrixRoom = room)
val presenter = createRoomCallStatePresenter(joinedRoom = room)
presenter.test {
val initialState = awaitItem()
assertThat(initialState).isEqualTo(
@ -39,10 +42,12 @@ class RoomCallStatePresenterTest {
@Test
fun `present - initial state - user can join call`() = runTest {
val room = FakeMatrixRoom(
canUserJoinCallResult = { Result.success(true) },
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserJoinCallResult = { Result.success(true) },
)
)
val presenter = createRoomCallStatePresenter(matrixRoom = room)
val presenter = createRoomCallStatePresenter(joinedRoom = room)
presenter.test {
skipItems(1)
val initialState = awaitItem()
@ -56,11 +61,13 @@ class RoomCallStatePresenterTest {
@Test
fun `present - call is disabled if user cannot join it even if there is an ongoing call`() = runTest {
val room = FakeMatrixRoom(
canUserJoinCallResult = { Result.success(false) },
initialRoomInfo = aRoomInfo(hasRoomCall = true),
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserJoinCallResult = { Result.success(false) },
initialRoomInfo = aRoomInfo(hasRoomCall = true),
)
)
val presenter = createRoomCallStatePresenter(matrixRoom = room)
val presenter = createRoomCallStatePresenter(joinedRoom = room)
presenter.test {
assertThat(awaitItem()).isEqualTo(
RoomCallState.OnGoing(
@ -74,7 +81,8 @@ class RoomCallStatePresenterTest {
@Test
fun `present - user has joined the call on another session`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserJoinCallResult = { Result.success(true) },
).apply {
givenRoomInfo(
@ -84,7 +92,8 @@ class RoomCallStatePresenterTest {
)
)
}
val presenter = createRoomCallStatePresenter(matrixRoom = room)
)
val presenter = createRoomCallStatePresenter(joinedRoom = room)
presenter.test {
skipItems(1)
assertThat(awaitItem()).isEqualTo(
@ -99,7 +108,8 @@ class RoomCallStatePresenterTest {
@Test
fun `present - user has joined the call locally`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserJoinCallResult = { Result.success(true) },
).apply {
givenRoomInfo(
@ -109,8 +119,9 @@ class RoomCallStatePresenterTest {
)
)
}
)
val presenter = createRoomCallStatePresenter(
matrixRoom = room,
joinedRoom = room,
currentCallService = FakeCurrentCallService(MutableStateFlow(CurrentCall.RoomCall(room.roomId))),
)
presenter.test {
@ -127,7 +138,8 @@ class RoomCallStatePresenterTest {
@Test
fun `present - user leaves the call`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canUserJoinCallResult = { Result.success(true) },
).apply {
givenRoomInfo(
@ -137,10 +149,11 @@ class RoomCallStatePresenterTest {
)
)
}
)
val currentCall = MutableStateFlow<CurrentCall>(CurrentCall.RoomCall(room.roomId))
val currentCallService = FakeCurrentCallService(currentCall = currentCall)
val presenter = createRoomCallStatePresenter(
matrixRoom = room,
joinedRoom = room,
currentCallService = currentCallService
)
presenter.test {
@ -188,11 +201,11 @@ class RoomCallStatePresenterTest {
}
private fun createRoomCallStatePresenter(
matrixRoom: MatrixRoom,
joinedRoom: JoinedRoom,
currentCallService: CurrentCallService = FakeCurrentCallService(),
): RoomCallStatePresenter {
return RoomCallStatePresenter(
room = matrixRoom,
room = joinedRoom,
currentCallService = currentCallService,
)
}

View file

@ -50,7 +50,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
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.permalink.PermalinkData
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.verification.VerificationRequest
import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint
import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
@ -64,7 +64,7 @@ class RoomDetailsFlowNode @AssistedInject constructor(
@Assisted plugins: List<Plugin>,
private val pollHistoryEntryPoint: PollHistoryEntryPoint,
private val elementCallEntryPoint: ElementCallEntryPoint,
private val room: MatrixRoom,
private val room: BaseRoom,
private val analyticsService: AnalyticsService,
private val messagesEntryPoint: MessagesEntryPoint,
private val knockRequestsListEntryPoint: KnockRequestsListEntryPoint,

View file

@ -24,7 +24,7 @@ import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.androidutils.system.startSharePlainTextIntent
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ -36,7 +36,7 @@ class RoomDetailsNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val presenter: RoomDetailsPresenter,
private val room: MatrixRoom,
private val room: BaseRoom,
private val analyticsService: AnalyticsService,
) : Node(buildContext, plugins = plugins) {
interface Callback : Plugin {

View file

@ -35,9 +35,9 @@ import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.powerlevels.canInvite
@ -61,7 +61,7 @@ import javax.inject.Inject
class RoomDetailsPresenter @Inject constructor(
private val client: MatrixClient,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val featureFlagService: FeatureFlagService,
private val notificationSettingsService: NotificationSettingsService,
private val roomMembersDetailsPresenterFactory: RoomMemberDetailsPresenter.Factory,
@ -235,12 +235,12 @@ class RoomDetailsPresenter @Inject constructor(
}
@Composable
private fun getCanInvite(membersState: MatrixRoomMembersState) = produceState(false, membersState) {
private fun getCanInvite(membersState: RoomMembersState) = produceState(false, membersState) {
value = room.canInvite().getOrElse { false }
}
@Composable
private fun getCanSendState(membersState: MatrixRoomMembersState, type: StateEventType) = produceState(false, membersState) {
private fun getCanSendState(membersState: RoomMembersState, type: StateEventType) = produceState(false, membersState) {
value = room.canSendState(type).getOrElse { false }
}

View file

@ -9,7 +9,7 @@ package io.element.android.features.roomdetails.impl.analytics
import im.vector.app.features.analytics.plan.RoomModeration
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels
import io.element.android.services.analytics.api.AnalyticsService
internal fun RoomMember.Role.toAnalyticsMemberRole(): RoomModeration.Role = when (this) {
@ -22,7 +22,7 @@ internal fun analyticsMemberRoleForPowerLevel(powerLevel: Long): RoomModeration.
return RoomMember.Role.forPowerLevel(powerLevel).toAnalyticsMemberRole()
}
internal fun AnalyticsService.trackPermissionChangeAnalytics(initial: MatrixRoomPowerLevels?, updated: MatrixRoomPowerLevels) {
internal fun AnalyticsService.trackPermissionChangeAnalytics(initial: RoomPowerLevels?, updated: RoomPowerLevels) {
if (updated.ban != initial?.ban) {
capture(RoomModeration(RoomModeration.Action.ChangePermissionsBanMembers, analyticsMemberRoleForPowerLevel(updated.ban)))
}

View file

@ -16,14 +16,14 @@ import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
@Module
@ContributesTo(RoomScope::class)
object RoomMemberModule {
@Provides
fun provideRoomMemberDetailsPresenterFactory(
room: MatrixRoom,
room: JoinedRoom,
userProfilePresenterFactory: UserProfilePresenterFactory,
encryptionService: EncryptionService,
clipboardHelper: ClipboardHelper,

View file

@ -25,7 +25,7 @@ import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.powerlevels.canSendState
import io.element.android.libraries.matrix.ui.media.AvatarAction
@ -43,7 +43,7 @@ import timber.log.Timber
import javax.inject.Inject
class RoomDetailsEditPresenter @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val mediaPickerProvider: PickerProvider,
private val mediaPreProcessor: MediaPreProcessor,
private val temporaryUriDeleter: TemporaryUriDeleter,

View file

@ -20,7 +20,7 @@ import im.vector.app.features.analytics.plan.MobileScreen
import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.apperror.api.AppErrorStateService
@ -33,7 +33,7 @@ class RoomInviteMembersNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
coroutineDispatchers: CoroutineDispatchers,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val presenter: RoomInviteMembersPresenter,
private val appErrorStateService: AppErrorStateService,
private val analyticsService: AnalyticsService,

View file

@ -9,14 +9,14 @@ package io.element.android.features.roomdetails.impl.members
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.roomMembers
import kotlinx.coroutines.withContext
import javax.inject.Inject
class RoomMemberListDataSource @Inject constructor(
private val room: MatrixRoom,
private val room: BaseRoom,
private val coroutineDispatchers: CoroutineDispatchers,
) {
suspend fun search(query: String): List<RoomMember> = withContext(coroutineDispatchers.io) {

View file

@ -28,9 +28,9 @@ import io.element.android.libraries.designsystem.theme.components.SearchBarResul
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.room.roomMembers
import io.element.android.libraries.matrix.ui.room.canInviteAsState
@ -45,7 +45,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.withContext
class RoomMemberListPresenter @AssistedInject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val roomMemberListDataSource: RoomMemberListDataSource,
private val coroutineDispatchers: CoroutineDispatchers,
private val roomMembersModerationPresenter: Presenter<RoomMembersModerationState>,
@ -86,11 +86,11 @@ class RoomMemberListPresenter @AssistedInject constructor(
}
LaunchedEffect(membersState, roomMemberIdentityStates) {
if (membersState is MatrixRoomMembersState.Unknown) {
if (membersState is RoomMembersState.Unknown) {
return@LaunchedEffect
}
val finalMembersState = membersState
if (finalMembersState is MatrixRoomMembersState.Error && finalMembersState.roomMembers().orEmpty().isEmpty()) {
if (finalMembersState is RoomMembersState.Error && finalMembersState.roomMembers().orEmpty().isEmpty()) {
// Cannot fetch members and no cached members, display the error
roomMembers = AsyncData.Failure(finalMembersState.failure)
return@LaunchedEffect
@ -116,7 +116,7 @@ class RoomMemberListPresenter @AssistedInject constructor(
.map { it.withIdentityState(roomMemberIdentityStates) }
.toImmutableList(),
)
roomMembers = if (membersState is MatrixRoomMembersState.Pending) {
roomMembers = if (membersState is RoomMembersState.Pending) {
AsyncData.Loading(result)
} else {
AsyncData.Success(result)
@ -147,7 +147,7 @@ class RoomMemberListPresenter @AssistedInject constructor(
.toImmutableList(),
)
SearchBarResultState.Results(
if (membersState is MatrixRoomMembersState.Pending) {
if (membersState is RoomMembersState.Pending) {
AsyncData.Loading(result)
} else {
AsyncData.Success(result)

View file

@ -28,7 +28,7 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.encryption.identity.IdentityStateChange
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.ui.room.getRoomMemberAsState
import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange
import io.element.android.libraries.ui.strings.CommonStrings
@ -45,7 +45,7 @@ import kotlinx.coroutines.launch
*/
class RoomMemberDetailsPresenter @AssistedInject constructor(
@Assisted private val roomMemberId: UserId,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val encryptionService: EncryptionService,
private val clipboardHelper: ClipboardHelper,
userProfilePresenterFactory: UserProfilePresenterFactory,

View file

@ -22,7 +22,7 @@ import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runUpdatingState
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.ui.room.canBanAsState
@ -38,7 +38,7 @@ import kotlinx.coroutines.launch
import javax.inject.Inject
class RoomMembersModerationPresenter @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val dispatchers: CoroutineDispatchers,
private val analyticsService: AnalyticsService,
) : Presenter<RoomMembersModerationState> {

View file

@ -26,7 +26,7 @@ import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.core.coroutine.suspendWithMinimumDuration
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
import kotlinx.coroutines.CoroutineScope
@ -38,7 +38,7 @@ import kotlinx.coroutines.launch
import kotlin.time.Duration.Companion.seconds
class RoomNotificationSettingsPresenter @AssistedInject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val notificationSettingsService: NotificationSettingsService,
@Assisted private val showUserDefinedSettingStyle: Boolean,
) : Presenter<RoomNotificationSettingsState> {

View file

@ -19,7 +19,7 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
@ -32,7 +32,7 @@ class RolesAndPermissionsNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val presenter: RolesAndPermissionsPresenter,
private val room: MatrixRoom,
private val room: BaseRoom,
) : Node(buildContext, plugins = plugins), RolesAndPermissionsNavigator {
interface Callback : Plugin, RolesAndPermissionsNavigator {
override fun openAdminList()

View file

@ -21,8 +21,8 @@ import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runUpdatingState
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.activeRoomMembers
import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange
@ -32,7 +32,7 @@ import kotlinx.coroutines.launch
import javax.inject.Inject
class RolesAndPermissionsPresenter @Inject constructor(
private val room: MatrixRoom,
private val room: JoinedRoom,
private val dispatchers: CoroutineDispatchers,
private val analyticsService: AnalyticsService,
) : Presenter<RolesAndPermissionsState> {
@ -109,7 +109,7 @@ class RolesAndPermissionsPresenter @Inject constructor(
}
}
private fun MatrixRoomInfo.userCountWithRole(userIds: List<UserId>, role: RoomMember.Role): Int {
private fun RoomInfo.userCountWithRole(userIds: List<UserId>, role: RoomMember.Role): Int {
return this.userPowerLevels.count { (userId, level) ->
RoomMember.Role.forPowerLevel(level) == role && userId in userIds
}

View file

@ -30,7 +30,7 @@ import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.powerlevels.UserRoleChange
import io.element.android.libraries.matrix.api.room.powerlevels.usersWithRole
@ -50,7 +50,7 @@ import kotlinx.coroutines.launch
class ChangeRolesPresenter @AssistedInject constructor(
@Assisted private val role: RoomMember.Role,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val dispatchers: CoroutineDispatchers,
private val analyticsService: AnalyticsService,
) : Presenter<ChangeRolesState> {

View file

@ -21,8 +21,8 @@ import dagger.assisted.AssistedInject
import io.element.android.features.roomdetails.impl.analytics.trackPermissionChangeAnalytics
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels
import io.element.android.services.analytics.api.AnalyticsService
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
@ -31,7 +31,7 @@ import kotlinx.coroutines.launch
class ChangeRoomPermissionsPresenter @AssistedInject constructor(
@Assisted private val section: ChangeRoomPermissionsSection,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val analyticsService: AnalyticsService,
) : Presenter<ChangeRoomPermissionsState> {
companion object {
@ -59,8 +59,8 @@ class ChangeRoomPermissionsPresenter @AssistedInject constructor(
private val items: ImmutableList<RoomPermissionType> = itemsForSection(section)
private var initialPermissions by mutableStateOf<MatrixRoomPowerLevels?>(null)
private var currentPermissions by mutableStateOf<MatrixRoomPowerLevels?>(null)
private var initialPermissions by mutableStateOf<RoomPowerLevels?>(null)
private var currentPermissions by mutableStateOf<RoomPowerLevels?>(null)
private var saveAction by mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized)
private var confirmExitAction by mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized)

View file

@ -8,12 +8,12 @@
package io.element.android.features.roomdetails.impl.rolesandpermissions.permissions
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels
import kotlinx.collections.immutable.ImmutableList
data class ChangeRoomPermissionsState(
val section: ChangeRoomPermissionsSection,
val currentPermissions: MatrixRoomPowerLevels?,
val currentPermissions: RoomPowerLevels?,
val items: ImmutableList<RoomPermissionType>,
val hasChanges: Boolean,
val saveAction: AsyncAction<Unit>,

View file

@ -10,7 +10,7 @@ package io.element.android.features.roomdetails.impl.rolesandpermissions.permiss
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels
import kotlinx.collections.immutable.toPersistentList
class ChangeRoomPermissionsStateProvider : PreviewParameterProvider<ChangeRoomPermissionsState> {
@ -36,7 +36,7 @@ class ChangeRoomPermissionsStateProvider : PreviewParameterProvider<ChangeRoomPe
internal fun aChangeRoomPermissionsState(
section: ChangeRoomPermissionsSection,
currentPermissions: MatrixRoomPowerLevels = previewPermissions(),
currentPermissions: RoomPowerLevels = previewPermissions(),
items: List<RoomPermissionType> = ChangeRoomPermissionsPresenter.itemsForSection(section),
hasChanges: Boolean = false,
saveAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
@ -52,8 +52,8 @@ internal fun aChangeRoomPermissionsState(
eventSink = eventSink,
)
private fun previewPermissions(): MatrixRoomPowerLevels {
return MatrixRoomPowerLevels(
private fun previewPermissions(): RoomPowerLevels {
return RoomPowerLevels(
// MembershipModeration section
invite = RoomMember.Role.ADMIN.powerLevel,
kick = RoomMember.Role.MODERATOR.powerLevel,

View file

@ -36,7 +36,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.powerlevels.MatrixRoomPowerLevels
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPowerLevels
import io.element.android.libraries.ui.strings.CommonStrings
@OptIn(ExperimentalMaterial3Api::class)
@ -133,7 +133,7 @@ fun ChangeRoomPermissionsView(
private fun SelectRoleItem(
permissionsItem: RoomPermissionType,
role: RoomMember.Role,
currentPermissions: MatrixRoomPowerLevels?,
currentPermissions: RoomPowerLevels?,
onClick: (RoomPermissionType, RoomMember.Role) -> Unit
) {
val title = when (role) {
@ -153,7 +153,7 @@ private fun SelectRoleItem(
)
}
private fun MatrixRoomPowerLevels.isSelected(item: RoomPermissionType, role: RoomMember.Role): Boolean {
private fun RoomPowerLevels.isSelected(item: RoomPermissionType, role: RoomMember.Role): Boolean {
return when (item) {
RoomPermissionType.BAN -> RoomMember.Role.forPowerLevel(ban) == role
RoomPermissionType.INVITE -> RoomMember.Role.forPowerLevel(invite) == role

View file

@ -29,8 +29,8 @@ 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.RoomAlias
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.roomdirectory.RoomVisibility
@ -43,7 +43,7 @@ import kotlinx.coroutines.launch
class SecurityAndPrivacyPresenter @AssistedInject constructor(
@Assisted private val navigator: SecurityAndPrivacyNavigator,
private val matrixClient: MatrixClient,
private val room: MatrixRoom,
private val room: JoinedRoom,
) : Presenter<SecurityAndPrivacyState> {
@AssistedFactory
interface Factory {
@ -279,6 +279,6 @@ private fun SecurityAndPrivacyHistoryVisibility.map(): RoomHistoryVisibility {
}
}
private fun MatrixRoomInfo.firstDisplayableAlias(serverName: String): RoomAlias? {
private fun RoomInfo.firstDisplayableAlias(serverName: String): RoomAlias? {
return aliases.firstOrNull { it.matchesServer(serverName) } ?: aliases.firstOrNull()
}

View file

@ -25,8 +25,8 @@ import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runCatchingUpdatingState
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.alias.RoomAliasHelper
import io.element.android.libraries.matrix.api.roomAliasFromName
import io.element.android.libraries.matrix.ui.room.address.RoomAddressValidity
@ -37,7 +37,7 @@ import kotlinx.coroutines.launch
class EditRoomAddressPresenter @AssistedInject constructor(
@Assisted private val navigator: SecurityAndPrivacyNavigator,
private val client: MatrixClient,
private val room: MatrixRoom,
private val room: JoinedRoom,
private val roomAliasHelper: RoomAliasHelper,
) : Presenter<EditRoomAddressState> {
@AssistedFactory
@ -139,7 +139,7 @@ class EditRoomAddressPresenter @AssistedInject constructor(
/**
* Returns the first alias that matches the given server name, or null if none match.
*/
private fun MatrixRoomInfo.firstAliasMatching(serverName: String): RoomAlias? {
private fun RoomInfo.firstAliasMatching(serverName: String): RoomAlias? {
// Check if the canonical alias matches the homeserver
if (canonicalAlias?.matchesServer(serverName) == true) {
return canonicalAlias

View file

@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.produceState
import io.element.android.features.roomdetails.impl.securityandprivacy.permissions.SecurityAndPrivacyPermissions.Companion.DEFAULT
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.powerlevels.canSendState
@ -37,7 +37,7 @@ data class SecurityAndPrivacyPermissions(
}
@Composable
fun MatrixRoom.securityAndPrivacyPermissionsAsState(updateKey: Long): State<SecurityAndPrivacyPermissions> {
fun BaseRoom.securityAndPrivacyPermissionsAsState(updateKey: Long): State<SecurityAndPrivacyPermissions> {
return produceState(DEFAULT, key1 = updateKey) {
value = SecurityAndPrivacyPermissions(
canChangeRoomAccess = canSendState(type = StateEventType.ROOM_JOIN_RULES).getOrElse { false },

View file

@ -21,11 +21,66 @@ 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.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.tests.testutils.lambda.lambdaError
fun aMatrixRoom(
fun aRoom(
sessionId: SessionId = A_SESSION_ID,
roomId: RoomId = A_ROOM_ID,
displayName: String = A_ROOM_NAME,
rawName: String? = displayName,
topic: String? = A_ROOM_TOPIC,
avatarUrl: String? = AN_AVATAR_URL,
canonicalAlias: RoomAlias? = A_ROOM_ALIAS,
isEncrypted: Boolean = true,
isPublic: Boolean = true,
isDirect: Boolean = false,
joinRule: JoinRule? = null,
activeMemberCount: Long = 1,
joinedMemberCount: Long = 1,
invitedMemberCount: Long = 0,
canInviteResult: (UserId) -> Result<Boolean> = { lambdaError() },
canBanResult: (UserId) -> Result<Boolean> = { lambdaError() },
canKickResult: (UserId) -> Result<Boolean> = { lambdaError() },
canSendStateResult: (UserId, StateEventType) -> Result<Boolean> = { _, _ -> lambdaError() },
userDisplayNameResult: (UserId) -> Result<String?> = { lambdaError() },
userAvatarUrlResult: () -> Result<String?> = { lambdaError() },
canUserJoinCallResult: (UserId) -> Result<Boolean> = { lambdaError() },
getUpdatedMemberResult: (UserId) -> Result<RoomMember> = { lambdaError() },
userRoleResult: () -> Result<RoomMember.Role> = { lambdaError() },
setIsFavoriteResult: (Boolean) -> Result<Unit> = { lambdaError() },
) = FakeBaseRoom(
sessionId = sessionId,
roomId = roomId,
canInviteResult = canInviteResult,
canBanResult = canBanResult,
canKickResult = canKickResult,
canSendStateResult = canSendStateResult,
userDisplayNameResult = userDisplayNameResult,
userAvatarUrlResult = userAvatarUrlResult,
canUserJoinCallResult = canUserJoinCallResult,
getUpdatedMemberResult = getUpdatedMemberResult,
userRoleResult = userRoleResult,
setIsFavoriteResult = setIsFavoriteResult,
initialRoomInfo = aRoomInfo(
name = displayName,
rawName = rawName,
topic = topic,
avatarUrl = avatarUrl,
canonicalAlias = canonicalAlias,
isDirect = isDirect,
isPublic = isPublic,
isEncrypted = isEncrypted,
joinRule = joinRule,
joinedMembersCount = joinedMemberCount,
activeMembersCount = activeMemberCount,
invitedMembersCount = invitedMemberCount,
)
)
fun aJoinedRoom(
sessionId: SessionId = A_SESSION_ID,
roomId: RoomId = A_ROOM_ID,
displayName: String = A_ROOM_NAME,
@ -60,31 +115,33 @@ fun aMatrixRoom(
updateCanonicalAliasResult: (RoomAlias?, List<RoomAlias>) -> Result<Unit> = { _, _ -> lambdaError() },
publishRoomAliasInRoomDirectoryResult: (RoomAlias) -> Result<Boolean> = { lambdaError() },
removeRoomAliasFromRoomDirectoryResult: (RoomAlias) -> Result<Boolean> = { lambdaError() },
) = FakeMatrixRoom(
sessionId = sessionId,
roomId = roomId,
notificationSettingsService = notificationSettingsService,
canInviteResult = canInviteResult,
canBanResult = canBanResult,
canKickResult = canKickResult,
canSendStateResult = canSendStateResult,
userDisplayNameResult = userDisplayNameResult,
userAvatarUrlResult = userAvatarUrlResult,
setIsFavoriteResult: (Boolean) -> Result<Unit> = { lambdaError() },
) = FakeJoinedRoom(
roomNotificationSettingsService = notificationSettingsService,
setNameResult = setNameResult,
setTopicResult = setTopicResult,
updateAvatarResult = updateAvatarResult,
removeAvatarResult = removeAvatarResult,
canUserJoinCallResult = canUserJoinCallResult,
getUpdatedMemberResult = getUpdatedMemberResult,
userRoleResult = userRoleResult,
kickUserResult = kickUserResult,
banUserResult = banUserResult,
unBanUserResult = unBanUserResult,
updateCanonicalAliasResult = updateCanonicalAliasResult,
publishRoomAliasInRoomDirectoryResult = publishRoomAliasInRoomDirectoryResult,
removeRoomAliasFromRoomDirectoryResult = removeRoomAliasFromRoomDirectoryResult,
initialRoomInfo = aRoomInfo(
name = displayName,
baseRoom = aRoom(
sessionId = sessionId,
roomId = roomId,
canInviteResult = canInviteResult,
canBanResult = canBanResult,
canKickResult = canKickResult,
canSendStateResult = canSendStateResult,
userDisplayNameResult = userDisplayNameResult,
userAvatarUrlResult = userAvatarUrlResult,
canUserJoinCallResult = canUserJoinCallResult,
getUpdatedMemberResult = getUpdatedMemberResult,
userRoleResult = userRoleResult,
setIsFavoriteResult = setIsFavoriteResult,
displayName = displayName,
rawName = rawName,
topic = topic,
avatarUrl = avatarUrl,
@ -93,8 +150,8 @@ fun aMatrixRoom(
isPublic = isPublic,
isEncrypted = isEncrypted,
joinRule = joinRule,
joinedMembersCount = joinedMemberCount,
activeMembersCount = activeMemberCount,
invitedMembersCount = invitedMemberCount,
joinedMemberCount = joinedMemberCount,
activeMemberCount = activeMemberCount,
invitedMemberCount = invitedMemberCount,
)
)

View file

@ -25,8 +25,8 @@ import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.api.room.join.JoinRule
@ -39,7 +39,6 @@ import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.services.analytics.api.AnalyticsService
import io.element.android.services.analytics.test.FakeAnalyticsService
@ -70,7 +69,7 @@ class RoomDetailsPresenterTest {
}
private fun TestScope.createRoomDetailsPresenter(
room: MatrixRoom = aMatrixRoom(),
room: JoinedRoom = aJoinedRoom(),
leaveRoomState: LeaveRoomState = aLeaveRoomState(),
dispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
@ -116,7 +115,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - initial state is created from initial room info`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
@ -145,7 +144,7 @@ class RoomDetailsPresenterTest {
avatarUrl = AN_AVATAR_URL,
pinnedEventIds = listOf(AN_EVENT_ID),
)
val room = aMatrixRoom(
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
@ -166,7 +165,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - initial state with no room name`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
displayName = "",
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
@ -185,7 +184,7 @@ class RoomDetailsPresenterTest {
fun `present - initial state with DM member sets custom DM roomType`() = runTest {
val myRoomMember = aRoomMember(A_SESSION_ID)
val otherRoomMember = aRoomMember(A_USER_ID_2)
val room = aMatrixRoom(
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
@ -198,7 +197,7 @@ class RoomDetailsPresenterTest {
},
).apply {
val roomMembers = persistentListOf(myRoomMember, otherRoomMember)
givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers))
givenRoomMembersState(RoomMembersState.Ready(roomMembers))
givenRoomInfo(
aRoomInfo(
@ -222,7 +221,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - initial state when user can invite others to room`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
@ -240,7 +239,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - initial state when user can not invite others to room`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canInviteResult = { Result.success(false) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
@ -255,7 +254,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - initial state when canInvite errors`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canInviteResult = { Result.failure(Throwable("Whoops")) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
@ -270,7 +269,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - initial state when user can edit one attribute`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_TOPIC -> Result.success(true)
@ -296,7 +295,7 @@ class RoomDetailsPresenterTest {
fun `present - initial state when user can edit attributes in a DM`() = runTest {
val myRoomMember = aRoomMember(A_SESSION_ID)
val otherRoomMember = aRoomMember(A_USER_ID_2)
val room = aMatrixRoom(
val room = aJoinedRoom(
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_TOPIC,
@ -316,7 +315,7 @@ class RoomDetailsPresenterTest {
},
).apply {
val roomMembers = persistentListOf(myRoomMember, otherRoomMember)
givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers))
givenRoomMembersState(RoomMembersState.Ready(roomMembers))
givenRoomInfo(
aRoomInfo(
@ -343,7 +342,7 @@ class RoomDetailsPresenterTest {
fun `present - initial state when in a DM with no topic`() = runTest {
val myRoomMember = aRoomMember(A_SESSION_ID)
val otherRoomMember = aRoomMember(A_USER_ID_2)
val room = aMatrixRoom(
val room = aJoinedRoom(
isDirect = true,
topic = null,
canSendStateResult = { _, stateEventType ->
@ -365,7 +364,7 @@ class RoomDetailsPresenterTest {
},
).apply {
val roomMembers = persistentListOf(myRoomMember, otherRoomMember)
givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers))
givenRoomMembersState(RoomMembersState.Ready(roomMembers))
givenRoomInfo(
aRoomInfo(
@ -378,7 +377,7 @@ class RoomDetailsPresenterTest {
val presenter = createRoomDetailsPresenter(room)
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
skipItems(1)
skipItems(2)
// There's no topic, so we hide the entire UI for DMs
assertThat(awaitItem().roomTopic).isEqualTo(RoomTopicState.Hidden)
@ -389,7 +388,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - initial state when user can edit all attributes`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_TOPIC,
@ -416,7 +415,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - initial state when user can edit no attributes`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
StateEventType.ROOM_TOPIC,
@ -441,7 +440,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - topic state is hidden when no topic and user has no permission`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = null,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
@ -467,7 +466,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - topic state is 'can add topic' when no topic and user has permission`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = null,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
@ -499,7 +498,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - leave room event is passed on to leave room presenter`() = runTest {
val leaveRoomEventRecorder = EventsRecorder<LeaveRoomEvent>()
val room = aMatrixRoom(
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
@ -519,7 +518,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - notification mode changes`() = runTest {
val notificationSettingsService = FakeNotificationSettingsService()
val room = aMatrixRoom(
val room = aJoinedRoom(
notificationSettingsService = notificationSettingsService,
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
@ -548,7 +547,7 @@ class RoomDetailsPresenterTest {
fun `present - mute room notifications`() = runTest {
val notificationSettingsService =
FakeNotificationSettingsService(initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY)
val room = aMatrixRoom(
val room = aJoinedRoom(
notificationSettingsService = notificationSettingsService,
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
@ -576,7 +575,7 @@ class RoomDetailsPresenterTest {
initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
initialEncryptedGroupDefaultMode = RoomNotificationMode.ALL_MESSAGES
)
val room = aMatrixRoom(
val room = aJoinedRoom(
notificationSettingsService = notificationSettingsService,
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
@ -601,7 +600,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - when set is favorite event is emitted, then the action is called`() = runTest {
val setIsFavoriteResult = lambdaRecorder<Boolean, Result<Unit>> { _ -> Result.success(Unit) }
val room = FakeMatrixRoom(
val room = aJoinedRoom(
setIsFavoriteResult = setIsFavoriteResult,
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
@ -630,7 +629,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - changes in room info updates the is favorite flag`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
@ -651,7 +650,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - show knock requests`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },
@ -677,7 +676,7 @@ class RoomDetailsPresenterTest {
@Test
fun `present - show security and privacy`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canInviteResult = { Result.success(true) },
canUserJoinCallResult = { Result.success(true) },
canSendStateResult = { _, _ -> Result.success(true) },

View file

@ -10,11 +10,11 @@ package io.element.android.features.roomdetails.impl.edit
import android.net.Uri
import app.cash.turbine.ReceiveTurbine
import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomdetails.impl.aMatrixRoom
import io.element.android.features.roomdetails.impl.aJoinedRoom
import io.element.android.libraries.androidutils.file.TemporaryUriDeleter
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.core.mimetype.MimeTypes
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.StateEventType
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.A_ROOM_NAME
@ -74,7 +74,7 @@ class RoomDetailsEditPresenterTest {
}
private fun createRoomDetailsEditPresenter(
room: MatrixRoom,
room: JoinedRoom,
permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(),
temporaryUriDeleter: TemporaryUriDeleter = FakeTemporaryUriDeleter(),
): RoomDetailsEditPresenter {
@ -89,7 +89,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - initial state is created from room info`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
avatarUrl = AN_AVATAR_URL,
displayName = A_ROOM_NAME,
rawName = A_ROOM_RAW_NAME,
@ -118,7 +118,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - sets canChangeName if user has permission`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
@ -151,7 +151,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - sets canChangeAvatar if user has permission`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
@ -183,7 +183,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - sets canChangeTopic if user has permission`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
avatarUrl = AN_AVATAR_URL,
canSendStateResult = { _, stateEventType ->
when (stateEventType) {
@ -215,7 +215,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - updates state in response to changes`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -260,7 +260,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - obtains avatar uris from gallery`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -284,7 +284,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - obtains avatar uris from camera`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -325,7 +325,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - updates save button state`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -375,7 +375,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - updates save button state when initial values are null`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = null,
displayName = "fallback",
avatarUrl = null,
@ -428,7 +428,7 @@ class RoomDetailsEditPresenterTest {
val setNameResult = lambdaRecorder { _: String -> Result.success(Unit) }
val setTopicResult = lambdaRecorder { _: String -> Result.success(Unit) }
val removeAvatarResult = lambdaRecorder<Result<Unit>> { Result.success(Unit) }
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -457,7 +457,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - save doesn't change room details if they're the same trimmed`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -479,7 +479,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - save doesn't change topic if it was unset and is now blank`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = null,
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -501,7 +501,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - save doesn't change name if it's now empty`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -524,7 +524,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - save processes and sets avatar when processor returns successfully`() = runTest {
val updateAvatarResult = lambdaRecorder { _: String, _: ByteArray -> Result.success(Unit) }
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -552,7 +552,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - save does not set avatar data if processor fails`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -576,7 +576,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - sets save action to failure if name update fails`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -588,7 +588,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - sets save action to failure if topic update fails`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -600,7 +600,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - sets save action to failure if removing avatar fails`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -613,7 +613,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - sets save action to failure if setting avatar fails`() = runTest {
givenPickerReturnsFile()
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -626,7 +626,7 @@ class RoomDetailsEditPresenterTest {
@Test
fun `present - CancelSaveChanges resets save action state`() = runTest {
givenPickerReturnsFile()
val room = aMatrixRoom(
val room = aJoinedRoom(
topic = "My topic",
displayName = "Name",
avatarUrl = AN_AVATAR_URL,
@ -650,7 +650,7 @@ class RoomDetailsEditPresenterTest {
}
private suspend fun saveAndAssertFailure(
room: MatrixRoom,
room: JoinedRoom,
event: RoomDetailsEditEvents,
deleteCallbackNumberOfInvocation: Int = 2,
) {

View file

@ -11,19 +11,19 @@ import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomdetails.impl.aMatrixRoom
import io.element.android.features.roomdetails.impl.aRoom
import io.element.android.features.roomdetails.impl.members.RoomMemberListDataSource
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.roomdetails.impl.members.aRoomMemberList
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.ui.components.aMatrixUser
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
import io.element.android.libraries.usersearch.api.UserSearchResult
@ -47,7 +47,7 @@ internal class RoomInviteMembersPresenterTest {
fun `present - initial state has no results and no search`() = runTest {
val presenter = RoomInviteMembersPresenter(
userRepository = FakeUserRepository(),
roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
roomMemberListDataSource = createDataSource(FakeBaseRoom()),
coroutineDispatchers = testCoroutineDispatchers()
)
@ -69,7 +69,7 @@ internal class RoomInviteMembersPresenterTest {
fun `present - updates search active state`() = runTest {
val presenter = RoomInviteMembersPresenter(
userRepository = FakeUserRepository(),
roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
roomMemberListDataSource = createDataSource(FakeBaseRoom()),
coroutineDispatchers = testCoroutineDispatchers()
)
@ -91,7 +91,7 @@ internal class RoomInviteMembersPresenterTest {
val repository = FakeUserRepository()
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
roomMemberListDataSource = createDataSource(FakeBaseRoom()),
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -118,7 +118,7 @@ internal class RoomInviteMembersPresenterTest {
val repository = FakeUserRepository()
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
roomMemberListDataSource = createDataSource(FakeBaseRoom()),
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -159,9 +159,9 @@ internal class RoomInviteMembersPresenterTest {
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(
matrixRoom = FakeMatrixRoom().apply {
room = FakeBaseRoom().apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(
aRoomMember(userId = joinedUser.userId, membership = RoomMembershipState.JOIN),
aRoomMember(userId = invitedUser.userId, membership = RoomMembershipState.INVITE),
@ -219,9 +219,9 @@ internal class RoomInviteMembersPresenterTest {
val repository = FakeUserRepository()
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom().apply {
roomMemberListDataSource = createDataSource(FakeBaseRoom().apply {
givenRoomMembersState(
MatrixRoomMembersState.Ready(
RoomMembersState.Ready(
persistentListOf(
aRoomMember(userId = joinedUser.userId, membership = RoomMembershipState.JOIN),
aRoomMember(userId = invitedUser.userId, membership = RoomMembershipState.INVITE),
@ -295,7 +295,7 @@ internal class RoomInviteMembersPresenterTest {
val repository = FakeUserRepository()
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
roomMemberListDataSource = createDataSource(FakeBaseRoom()),
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -336,7 +336,7 @@ internal class RoomInviteMembersPresenterTest {
val repository = FakeUserRepository()
val presenter = RoomInviteMembersPresenter(
userRepository = repository,
roomMemberListDataSource = createDataSource(FakeMatrixRoom()),
roomMemberListDataSource = createDataSource(FakeBaseRoom()),
coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -397,11 +397,11 @@ internal class RoomInviteMembersPresenterTest {
}
private fun TestScope.createDataSource(
matrixRoom: MatrixRoom = aMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
room: BaseRoom = aRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
},
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers()
) = RoomMemberListDataSource(matrixRoom, coroutineDispatchers)
) = RoomMemberListDataSource(room, coroutineDispatchers)
private fun SearchBarResultState<ImmutableList<InvitableUser>>.users() =
(this as? SearchBarResultState.Results<ImmutableList<InvitableUser>>)?.results.orEmpty()

View file

@ -15,7 +15,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID_4
import io.element.android.libraries.matrix.test.A_USER_ID_5
import org.junit.Test
class PowerLevelRoomMemberComparatorTest {
class PowerLevelBaseRoomMemberComparatorTest {
@Test
fun `order is Admin, then Moderator, then User`() {
val memberList = listOf(

View file

@ -17,10 +17,12 @@ import io.element.android.features.roomdetails.impl.members.moderation.aRoomMemb
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.BaseRoom
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.WarmUpRule
@ -38,14 +40,16 @@ class RoomMemberListPresenterTest {
@Test
fun `member loading is done automatically on start, but is async`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
updateMembersResult = { Result.success(Unit) },
canInviteResult = { Result.success(true) }
).apply {
// Needed to avoid discarding the loaded members as a partial and invalid result
givenRoomInfo(aRoomInfo(joinedMembersCount = 2))
}
val presenter = createPresenter(matrixRoom = room)
)
val presenter = createPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -55,7 +59,7 @@ class RoomMemberListPresenterTest {
assertThat(initialState.searchQuery).isEmpty()
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
assertThat(initialState.isSearchActive).isFalse()
room.givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
room.givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
// Skip item while the new members state is processed
skipItems(1)
val loadedMembersState = awaitItem()
@ -69,9 +73,11 @@ class RoomMemberListPresenterTest {
@Test
fun `open search`() = runTest {
val presenter = createPresenter(
matrixRoom = FakeMatrixRoom(
updateMembersResult = { Result.success(Unit) },
canInviteResult = { Result.success(true) }
joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
updateMembersResult = { Result.success(Unit) },
canInviteResult = { Result.success(true) }
)
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -89,10 +95,12 @@ class RoomMemberListPresenterTest {
@Test
fun `search for something which is not found`() = runTest {
val presenter = createPresenter(
matrixRoom = FakeMatrixRoom(
joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
updateMembersResult = { Result.success(Unit) },
canInviteResult = { Result.success(true) }
)
)
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
@ -113,9 +121,11 @@ class RoomMemberListPresenterTest {
@Test
fun `search for something which is found`() = runTest {
val presenter = createPresenter(
matrixRoom = FakeMatrixRoom(
updateMembersResult = { Result.success(Unit) },
canInviteResult = { Result.success(true) }
joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
updateMembersResult = { Result.success(Unit) },
canInviteResult = { Result.success(true) }
)
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -139,9 +149,11 @@ class RoomMemberListPresenterTest {
@Test
fun `present - asynchronously sets canInvite when user has correct power level`() = runTest {
val presenter = createPresenter(
matrixRoom = FakeMatrixRoom(
canInviteResult = { Result.success(true) },
updateMembersResult = { Result.success(Unit) }
joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canInviteResult = { Result.success(true) },
updateMembersResult = { Result.success(Unit) }
)
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -156,9 +168,11 @@ class RoomMemberListPresenterTest {
@Test
fun `present - asynchronously sets canInvite when user does not have correct power level`() = runTest {
val presenter = createPresenter(
matrixRoom = FakeMatrixRoom(
canInviteResult = { Result.success(false) },
updateMembersResult = { Result.success(Unit) }
joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canInviteResult = { Result.success(false) },
updateMembersResult = { Result.success(Unit) }
)
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -173,9 +187,11 @@ class RoomMemberListPresenterTest {
@Test
fun `present - asynchronously sets canInvite when power level check fails`() = runTest {
val presenter = createPresenter(
matrixRoom = FakeMatrixRoom(
canInviteResult = { Result.failure(Throwable("Eek")) },
updateMembersResult = { Result.success(Unit) }
joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canInviteResult = { Result.failure(Throwable("Eek")) },
updateMembersResult = { Result.success(Unit) }
)
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -194,9 +210,11 @@ class RoomMemberListPresenterTest {
val presenter = createPresenter(
roomMembersModerationStateLambda = roomMembersModerationStateLambda,
navigator = navigator,
matrixRoom = FakeMatrixRoom(
updateMembersResult = { Result.success(Unit) },
canInviteResult = { Result.success(true) }
joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
updateMembersResult = { Result.success(Unit) },
canInviteResult = { Result.success(true) }
)
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -221,9 +239,11 @@ class RoomMemberListPresenterTest {
val presenter = createPresenter(
roomMembersModerationStateLambda = roomMembersModerationStateLambda,
navigator = navigator,
matrixRoom = FakeMatrixRoom(
updateMembersResult = { Result.success(Unit) },
canInviteResult = { Result.success(true) }
joinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
updateMembersResult = { Result.success(Unit) },
canInviteResult = { Result.success(true) }
)
)
)
moleculeFlow(RecompositionMode.Immediate) {
@ -247,24 +267,26 @@ private class FakeRoomMemberListNavigator : RoomMemberListNavigator {
@ExperimentalCoroutinesApi
private fun TestScope.createDataSource(
matrixRoom: MatrixRoom = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
room: BaseRoom = FakeBaseRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
},
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers()
) = RoomMemberListDataSource(matrixRoom, coroutineDispatchers)
) = RoomMemberListDataSource(room, coroutineDispatchers)
@ExperimentalCoroutinesApi
private fun TestScope.createPresenter(
coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true),
matrixRoom: MatrixRoom = FakeMatrixRoom(
updateMembersResult = { Result.success(Unit) }
joinedRoom: JoinedRoom = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
updateMembersResult = { Result.success(Unit) }
)
),
roomMemberListDataSource: RoomMemberListDataSource = createDataSource(coroutineDispatchers = coroutineDispatchers),
roomMembersModerationStateLambda: () -> RoomMembersModerationState = { aRoomMembersModerationState() },
encryptedService: FakeEncryptionService = FakeEncryptionService(),
navigator: RoomMemberListNavigator = object : RoomMemberListNavigator {}
) = RoomMemberListPresenter(
room = matrixRoom,
room = joinedRoom,
roomMemberListDataSource = roomMemberListDataSource,
coroutineDispatchers = coroutineDispatchers,
roomMembersModerationPresenter = { roomMembersModerationStateLambda() },

View file

@ -11,7 +11,7 @@ import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomdetails.impl.aMatrixRoom
import io.element.android.features.roomdetails.impl.aJoinedRoom
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.userprofile.api.UserProfileEvents
import io.element.android.features.userprofile.api.UserProfilePresenterFactory
@ -23,12 +23,13 @@ import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
import io.element.android.libraries.matrix.api.encryption.identity.IdentityStateChange
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.test.AN_EXCEPTION
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.consumeItemsUntilPredicate
@ -36,6 +37,7 @@ import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.test
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
@ -48,12 +50,12 @@ class RoomMemberDetailsPresenterTest {
@Test
fun `present - returns the room member's data, then updates it if needed`() = runTest {
val roomMember = aRoomMember(displayName = "Alice")
val room = aMatrixRoom(
val room = aJoinedRoom(
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
getUpdatedMemberResult = { Result.success(roomMember) },
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(roomMember)))
}
val presenter = createRoomMemberDetailsPresenter(
room = room,
@ -75,12 +77,12 @@ class RoomMemberDetailsPresenterTest {
displayName = "Alice",
avatarUrl = "Alice Avatar url",
)
val room = aMatrixRoom(
val room = aJoinedRoom(
userDisplayNameResult = { Result.failure(Throwable()) },
userAvatarUrlResult = { Result.failure(Throwable()) },
getUpdatedMemberResult = { Result.failure(AN_EXCEPTION) },
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(roomMember)))
}
val presenter = createRoomMemberDetailsPresenter(
@ -98,12 +100,12 @@ class RoomMemberDetailsPresenterTest {
@Test
fun `present - will fallback to original data if the updated data is null`() = runTest {
val roomMember = aRoomMember(displayName = "Alice")
val room = aMatrixRoom(
val room = aJoinedRoom(
userDisplayNameResult = { Result.success(null) },
userAvatarUrlResult = { Result.success(null) },
getUpdatedMemberResult = { Result.success(roomMember) }
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(roomMember)))
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(roomMember)))
}
val presenter = createRoomMemberDetailsPresenter(
room = room,
@ -119,7 +121,7 @@ class RoomMemberDetailsPresenterTest {
@Test
fun `present - will fallback to user profile if user is not a member of the room`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
userDisplayNameResult = { Result.failure(Exception("Not a member!")) },
userAvatarUrlResult = { Result.failure(Exception("Not a member!")) },
getUpdatedMemberResult = { Result.failure(AN_EXCEPTION) },
@ -142,7 +144,7 @@ class RoomMemberDetailsPresenterTest {
displayName = null,
avatarUrl = null,
)
val room = aMatrixRoom(
val room = aJoinedRoom(
userDisplayNameResult = { Result.success(null) },
userAvatarUrlResult = { Result.success(null) },
getUpdatedMemberResult = { Result.success(roomMember) },
@ -169,12 +171,14 @@ class RoomMemberDetailsPresenterTest {
@Test
fun `present - when user's identity is verified, the value in the state is VERIFIED`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(IdentityState.Verified) },
)
@ -188,12 +192,14 @@ class RoomMemberDetailsPresenterTest {
@Test
fun `present - when user's identity is unknown, the value in the state is UNKNOWN`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(null) },
)
@ -207,12 +213,14 @@ class RoomMemberDetailsPresenterTest {
@Test
fun `present - when user's identity is pinned, the value in the state is UNVERIFIED`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(IdentityState.Pinned) },
)
@ -226,12 +234,14 @@ class RoomMemberDetailsPresenterTest {
@Test
fun `present - when user's identity is pin violation, the value in the state is UNVERIFIED`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(IdentityState.PinViolation) },
)
@ -245,12 +255,14 @@ class RoomMemberDetailsPresenterTest {
@Test
fun `present - when user's identity has a verification violation, the value in the state is VERIFICATION_VIOLATION`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(IdentityState.VerificationViolation) },
)
@ -264,11 +276,15 @@ class RoomMemberDetailsPresenterTest {
@Test
fun `present - user identity updates in real time if the room is encrypted`() = runTest {
val room = FakeMatrixRoom(
val identityStateChanges = MutableStateFlow(emptyList<IdentityStateChange>())
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
),
identityStateChangesFlow = identityStateChanges,
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(null) },
@ -280,24 +296,28 @@ class RoomMemberDetailsPresenterTest {
room.emitSyncUpdate()
room.emitIdentityStateChanges(listOf(IdentityStateChange(A_USER_ID, IdentityState.Pinned)))
identityStateChanges.emit(listOf(IdentityStateChange(A_USER_ID, IdentityState.Pinned)))
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.UNVERIFIED }
room.emitIdentityStateChanges(listOf(IdentityStateChange(A_USER_ID, IdentityState.Verified)))
identityStateChanges.emit(listOf(IdentityStateChange(A_USER_ID, IdentityState.Verified)))
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.VERIFIED }
room.emitIdentityStateChanges(listOf(IdentityStateChange(A_USER_ID, IdentityState.VerificationViolation)))
identityStateChanges.emit(listOf(IdentityStateChange(A_USER_ID, IdentityState.VerificationViolation)))
consumeItemsUntilPredicate { it.verificationState == UserProfileVerificationState.VERIFICATION_VIOLATION }
}
}
@Test
fun `present - user identity can't update in real time if the room is not encrypted`() = runTest {
val room = FakeMatrixRoom(
val identityStateChanges = MutableStateFlow(emptyList<IdentityStateChange>())
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = false),
),
identityStateChangesFlow = identityStateChanges,
)
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(null) },
@ -308,7 +328,7 @@ class RoomMemberDetailsPresenterTest {
assertThat(awaitItem().verificationState).isEqualTo(UserProfileVerificationState.UNKNOWN)
room.emitSyncUpdate()
room.emitIdentityStateChanges(listOf(IdentityStateChange(A_USER_ID, IdentityState.Pinned)))
identityStateChanges.emit(listOf(IdentityStateChange(A_USER_ID, IdentityState.Pinned)))
// No new events emitted
ensureAllEventsConsumed()
@ -317,12 +337,14 @@ class RoomMemberDetailsPresenterTest {
@Test
fun `present - handles WithdrawVerification action`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
getUpdatedMemberResult = { Result.success(aRoomMember(A_USER_ID)) },
userDisplayNameResult = { Result.success("A custom name") },
userAvatarUrlResult = { Result.success("A custom avatar") },
initialRoomInfo = aRoomInfo(isEncrypted = true),
)
)
val withdrawVerificationResult = lambdaRecorder<UserId, Result<Unit>> { Result.success(Unit) }
val encryptionService = FakeEncryptionService(
getUserIdentityResult = { Result.success(IdentityState.VerificationViolation) },
@ -342,7 +364,7 @@ class RoomMemberDetailsPresenterTest {
}
private fun createRoomMemberDetailsPresenter(
room: MatrixRoom,
room: JoinedRoom,
userProfilePresenterFactory: UserProfilePresenterFactory = UserProfilePresenterFactory {
Presenter {
aUserProfileState(

View file

@ -12,19 +12,19 @@ import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import im.vector.app.features.analytics.plan.RoomModeration
import io.element.android.features.roomdetails.impl.aMatrixRoom
import io.element.android.features.roomdetails.impl.aJoinedRoom
import io.element.android.features.roomdetails.impl.members.aRoomMember
import io.element.android.features.roomdetails.impl.members.aVictor
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.test.A_REASON
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.lambda.lambdaRecorder
@ -39,7 +39,7 @@ import org.junit.Test
class RoomMembersModerationPresenterTest {
@Test
fun `canDisplayModerationActions - when room is DM is false`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
isPublic = true,
activeMemberCount = 2,
canKickResult = { Result.success(true) },
@ -48,7 +48,7 @@ class RoomMembersModerationPresenterTest {
).apply {
givenRoomInfo(aRoomInfo(isDirect = true, activeMembersCount = 2))
}
val presenter = createRoomMembersModerationPresenter(matrixRoom = room)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room)
presenter.test {
assertThat(awaitItem().canDisplayModerationActions).isFalse()
}
@ -56,13 +56,13 @@ class RoomMembersModerationPresenterTest {
@Test
fun `canDisplayModerationActions - when user can kick other users, FF is enabled and room is not a DM returns true`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
activeMemberCount = 10,
canKickResult = { Result.success(true) },
canBanResult = { Result.success(true) },
userRoleResult = { Result.success(RoomMember.Role.ADMIN) },
)
val presenter = createRoomMembersModerationPresenter(matrixRoom = room)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room)
presenter.test {
skipItems(1)
assertThat(awaitItem().canDisplayModerationActions).isTrue()
@ -71,13 +71,13 @@ class RoomMembersModerationPresenterTest {
@Test
fun `canDisplayModerationActions - when user can ban other users, FF is enabled and room is not a DM returns true`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
activeMemberCount = 10,
canKickResult = { Result.success(true) },
canBanResult = { Result.success(true) },
userRoleResult = { Result.success(RoomMember.Role.ADMIN) },
)
val presenter = createRoomMembersModerationPresenter(matrixRoom = room)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room)
presenter.test {
skipItems(1)
assertThat(awaitItem().canDisplayModerationActions).isTrue()
@ -86,13 +86,13 @@ class RoomMembersModerationPresenterTest {
@Test
fun `present - SelectRoomMember when the current user has permissions displays member actions`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canKickResult = { Result.success(true) },
canBanResult = { Result.success(true) },
userRoleResult = { Result.success(RoomMember.Role.ADMIN) },
)
val selectedMember = aVictor()
val presenter = createRoomMembersModerationPresenter(matrixRoom = room)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -112,14 +112,14 @@ class RoomMembersModerationPresenterTest {
@Test
fun `present - SelectRoomMember displays only view profile if selected member has same power level as the current user`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
sessionId = A_USER_ID,
canKickResult = { Result.success(true) },
canBanResult = { Result.success(true) },
userRoleResult = { Result.success(RoomMember.Role.ADMIN) },
)
val selectedMember = aRoomMember(A_USER_ID_2, powerLevel = 100L)
val presenter = createRoomMembersModerationPresenter(matrixRoom = room)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -138,12 +138,12 @@ class RoomMembersModerationPresenterTest {
@Test
fun `present - SelectRoomMember displays an unban confirmation dialog when the member is banned`() = runTest {
val selectedMember = aRoomMember(A_USER_ID_2, membership = RoomMembershipState.BAN)
val room = aMatrixRoom(
val room = aJoinedRoom(
canKickResult = { Result.success(true) },
canBanResult = { Result.success(true) },
userRoleResult = { Result.success(RoomMember.Role.ADMIN) },
)
val presenter = createRoomMembersModerationPresenter(matrixRoom = room)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -160,14 +160,14 @@ class RoomMembersModerationPresenterTest {
fun `present - Kick requires confirmation and then kicks the user`() = runTest {
val analyticsService = FakeAnalyticsService()
val kickUserResult = lambdaRecorder<UserId, String?, Result<Unit>> { _, _ -> Result.success(Unit) }
val room = aMatrixRoom(
val room = aJoinedRoom(
canKickResult = { Result.success(true) },
canBanResult = { Result.success(true) },
userRoleResult = { Result.success(RoomMember.Role.ADMIN) },
kickUserResult = kickUserResult,
)
val selectedMember = aVictor()
val presenter = createRoomMembersModerationPresenter(matrixRoom = room, analyticsService = analyticsService)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room, analyticsService = analyticsService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -198,14 +198,14 @@ class RoomMembersModerationPresenterTest {
fun `present - BanUser requires confirmation and then bans the user`() = runTest {
val analyticsService = FakeAnalyticsService()
val banUserResult = lambdaRecorder<UserId, String?, Result<Unit>> { _, _ -> Result.success(Unit) }
val room = aMatrixRoom(
val room = aJoinedRoom(
canKickResult = { Result.success(true) },
canBanResult = { Result.success(true) },
userRoleResult = { Result.success(RoomMember.Role.ADMIN) },
banUserResult = banUserResult,
)
val selectedMember = aVictor()
val presenter = createRoomMembersModerationPresenter(matrixRoom = room, analyticsService = analyticsService)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room, analyticsService = analyticsService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -237,15 +237,15 @@ class RoomMembersModerationPresenterTest {
fun `present - UnbanUser requires confirmation and then unbans the user`() = runTest {
val analyticsService = FakeAnalyticsService()
val selectedMember = aRoomMember(A_USER_ID_2, membership = RoomMembershipState.BAN)
val room = aMatrixRoom(
val room = aJoinedRoom(
canKickResult = { Result.success(true) },
canBanResult = { Result.success(true) },
userRoleResult = { Result.success(RoomMember.Role.ADMIN) },
unBanUserResult = { _, _ -> Result.success(Unit) },
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(persistentListOf(selectedMember)))
givenRoomMembersState(RoomMembersState.Ready(persistentListOf(selectedMember)))
}
val presenter = createRoomMembersModerationPresenter(matrixRoom = room, analyticsService = analyticsService)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room, analyticsService = analyticsService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -269,12 +269,12 @@ class RoomMembersModerationPresenterTest {
@Test
fun `present - Reset removes the selected user and actions`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canKickResult = { Result.success(true) },
canBanResult = { Result.success(true) },
userRoleResult = { Result.success(RoomMember.Role.USER) },
)
val presenter = createRoomMembersModerationPresenter(matrixRoom = room)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -291,7 +291,7 @@ class RoomMembersModerationPresenterTest {
@Test
fun `present - Reset resets any async actions`() = runTest {
val room = aMatrixRoom(
val room = aJoinedRoom(
canKickResult = { Result.success(true) },
canBanResult = { Result.success(true) },
kickUserResult = { _, _ -> Result.failure(Throwable("Eek")) },
@ -299,7 +299,7 @@ class RoomMembersModerationPresenterTest {
unBanUserResult = { _, _ -> Result.failure(Throwable("Eek")) },
userRoleResult = { Result.success(RoomMember.Role.USER) },
)
val presenter = createRoomMembersModerationPresenter(matrixRoom = room)
val presenter = createRoomMembersModerationPresenter(joinedRoom = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -338,12 +338,12 @@ class RoomMembersModerationPresenterTest {
}
private fun TestScope.createRoomMembersModerationPresenter(
matrixRoom: FakeMatrixRoom = aMatrixRoom(),
joinedRoom: FakeJoinedRoom = aJoinedRoom(),
dispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
): RoomMembersModerationPresenter {
return RoomMembersModerationPresenter(
room = matrixRoom,
room = joinedRoom,
dispatchers = dispatchers,
analyticsService = analyticsService,
)

View file

@ -11,12 +11,12 @@ import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomdetails.impl.aMatrixRoom
import io.element.android.features.roomdetails.impl.aJoinedRoom
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_THROWABLE
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.tests.testutils.awaitLastSequentialItem
import io.element.android.tests.testutils.consumeItemsUntilPredicate
import kotlinx.coroutines.test.runTest
@ -158,7 +158,7 @@ class RoomNotificationSettingsPresenterTest {
val notificationService = FakeNotificationSettingsService().apply {
givenCanHomeServerPushEncryptedEventsToDeviceResult(Result.success(false))
}
val room = aMatrixRoom(notificationSettingsService = notificationService, isEncrypted = true)
val room = aJoinedRoom(notificationSettingsService = notificationService, isEncrypted = true)
val presenter = createRoomNotificationSettingsPresenter(notificationService, room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
@ -172,7 +172,7 @@ class RoomNotificationSettingsPresenterTest {
val notificationService = FakeNotificationSettingsService().apply {
givenCanHomeServerPushEncryptedEventsToDeviceResult(Result.success(false))
}
val room = aMatrixRoom(notificationSettingsService = notificationService, isEncrypted = false)
val room = aJoinedRoom(notificationSettingsService = notificationService, isEncrypted = false)
val presenter = createRoomNotificationSettingsPresenter(notificationService, room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
@ -183,7 +183,7 @@ class RoomNotificationSettingsPresenterTest {
private fun createRoomNotificationSettingsPresenter(
notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService(),
room: FakeMatrixRoom = aMatrixRoom(notificationSettingsService = notificationSettingsService),
room: FakeJoinedRoom = aJoinedRoom(notificationSettingsService = notificationSettingsService),
): RoomNotificationSettingsPresenter {
return RoomNotificationSettingsPresenter(
room = room,

View file

@ -15,7 +15,7 @@ import im.vector.app.features.analytics.plan.RoomModeration
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.defaultRoomPowerLevels
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.testCoroutineDispatchers
@ -59,7 +59,7 @@ class RolesAndPermissionPresenterTest {
fun `present - DemoteSelfTo changes own role to the specified one`() = runTest(StandardTestDispatcher()) {
val presenter = createRolesAndPermissionsPresenter(
dispatchers = testCoroutineDispatchers(),
room = FakeMatrixRoom(
room = FakeJoinedRoom(
updateUserRoleResult = { Result.success(Unit) }
),
)
@ -80,7 +80,7 @@ class RolesAndPermissionPresenterTest {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `present - DemoteSelfTo can handle failures and clean them`() = runTest(StandardTestDispatcher()) {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
updateUserRoleResult = { Result.failure(Exception("Failed to update role")) }
)
val presenter = createRolesAndPermissionsPresenter(room = room, dispatchers = testCoroutineDispatchers())
@ -120,7 +120,7 @@ class RolesAndPermissionPresenterTest {
val analyticsService = FakeAnalyticsService()
val presenter = createRolesAndPermissionsPresenter(
analyticsService = analyticsService,
room = FakeMatrixRoom(
room = FakeJoinedRoom(
resetPowerLevelsResult = { Result.success(defaultRoomPowerLevels()) }
)
)
@ -153,7 +153,7 @@ class RolesAndPermissionPresenterTest {
}
private fun TestScope.createRolesAndPermissionsPresenter(
room: FakeMatrixRoom = FakeMatrixRoom(),
room: FakeJoinedRoom = FakeJoinedRoom(),
dispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
analyticsService: FakeAnalyticsService = FakeAnalyticsService()
): RolesAndPermissionsPresenter {

View file

@ -16,12 +16,13 @@ import io.element.android.features.roomdetails.impl.members.aRoomMemberList
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembersState
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.A_USER_ID_2
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
import io.element.android.libraries.matrix.test.room.aRoomInfo
import io.element.android.services.analytics.test.FakeAnalyticsService
import io.element.android.tests.testutils.testCoroutineDispatchers
@ -54,8 +55,8 @@ class ChangeRolesPresenterTest {
@Test
fun `present - initial results are loaded automatically`() = runTest {
val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
}
val presenter = createChangeRolesPresenter(room = room)
moleculeFlow(RecompositionMode.Immediate) {
@ -68,8 +69,8 @@ class ChangeRolesPresenterTest {
@Test
fun `present - ToggleSearchActive changes the value`() = runTest {
val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
}
val presenter = createChangeRolesPresenter(room = room)
moleculeFlow(RecompositionMode.Immediate) {
@ -87,8 +88,8 @@ class ChangeRolesPresenterTest {
@Test
fun `present - QueryChanged produces new results`() = runTest {
val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
}
val presenter = createChangeRolesPresenter(room = room)
moleculeFlow(RecompositionMode.Immediate) {
@ -113,8 +114,8 @@ class ChangeRolesPresenterTest {
@Test
fun `present - changes in the room members produce new results`() = runTest {
val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
}
val presenter = createChangeRolesPresenter(room = room)
moleculeFlow(RecompositionMode.Immediate) {
@ -126,7 +127,7 @@ class ChangeRolesPresenterTest {
assertThat(initialResults?.moderators).hasSize(1)
assertThat(initialResults?.admins).hasSize(1)
room.givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList().take(1).toPersistentList()))
room.givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList().take(1).toPersistentList()))
skipItems(1)
val searchResults = (awaitItem().searchResults as? SearchBarResultState.Results)?.results
@ -139,8 +140,8 @@ class ChangeRolesPresenterTest {
@Test
fun `present - UserSelectionToggle adds and removes users from the selected user list`() = runTest {
val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 100)))
}
val presenter = createChangeRolesPresenter(room = room)
@ -161,8 +162,8 @@ class ChangeRolesPresenterTest {
@Test
fun `present - hasPendingChanges is true when the initial selected users don't match the new ones`() = runTest {
val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 100)))
}
val presenter = createChangeRolesPresenter(room = room)
@ -190,8 +191,8 @@ class ChangeRolesPresenterTest {
@Test
fun `present - Exit will display success if no pending changes`() = runTest {
val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 100)))
}
val presenter = createChangeRolesPresenter(room = room)
@ -210,8 +211,8 @@ class ChangeRolesPresenterTest {
@Test
fun `present - CancelExit will remove exit confirmation`() = runTest {
val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 100)))
}
val presenter = createChangeRolesPresenter(room = room)
@ -236,8 +237,8 @@ class ChangeRolesPresenterTest {
@Test
fun `present - Exit will display a confirmation dialog if there are pending changes, calling it again will actually exit`() = runTest {
val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 100)))
}
val presenter = createChangeRolesPresenter(room = room)
@ -264,11 +265,11 @@ class ChangeRolesPresenterTest {
@Test
fun `present - Save will display a confirmation when adding admins`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
updateUserRoleResult = { Result.success(Unit) },
updateMembersResult = { Result.success(Unit) },
baseRoom = FakeBaseRoom(updateMembersResult = { Result.success(Unit) }),
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 100)))
}
val presenter = createChangeRolesPresenter(role = RoomMember.Role.ADMIN, room = room)
@ -285,14 +286,19 @@ class ChangeRolesPresenterTest {
assertThat(confirmingState.savingState).isEqualTo(AsyncAction.ConfirmingNoParams)
confirmingState.eventSink(ChangeRolesEvent.Save)
val loadingState = awaitItem()
assertThat(loadingState.savingState).isInstanceOf(AsyncAction.Loading::class.java)
skipItems(1)
assertThat(awaitItem().savingState).isEqualTo(AsyncAction.Success(Unit))
}
}
@Test
fun `present - CancelSave will remove the confirmation dialog`() = runTest {
val room = FakeMatrixRoom().apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
val room = FakeJoinedRoom().apply {
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 100)))
}
val presenter = createChangeRolesPresenter(role = RoomMember.Role.ADMIN, room = room)
@ -317,11 +323,11 @@ class ChangeRolesPresenterTest {
@Test
fun `present - Save will just save the data for moderators`() = runTest {
val analyticsService = FakeAnalyticsService()
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
updateUserRoleResult = { Result.success(Unit) },
updateMembersResult = { Result.success(Unit) },
baseRoom = FakeBaseRoom(updateMembersResult = { Result.success(Unit) }),
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 50)))
}
val presenter = createChangeRolesPresenter(
@ -339,6 +345,11 @@ class ChangeRolesPresenterTest {
initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(MatrixUser(A_USER_ID_2)))
awaitItem().eventSink(ChangeRolesEvent.Save)
val loadingState = awaitItem()
assertThat(loadingState.savingState).isInstanceOf(AsyncAction.Loading::class.java)
skipItems(1)
assertThat(awaitItem().savingState).isEqualTo(AsyncAction.Success(Unit))
assertThat(analyticsService.capturedEvents.last()).isEqualTo(RoomModeration(RoomModeration.Action.ChangeMemberRole, RoomModeration.Role.Moderator))
}
@ -346,10 +357,10 @@ class ChangeRolesPresenterTest {
@Test
fun `present - Save can handle failures and ClearError clears them`() = runTest {
val room = FakeMatrixRoom(
val room = FakeJoinedRoom(
updateUserRoleResult = { Result.failure(IllegalStateException("Failed")) }
).apply {
givenRoomMembersState(MatrixRoomMembersState.Ready(aRoomMemberList()))
givenRoomMembersState(RoomMembersState.Ready(aRoomMemberList()))
givenRoomInfo(aRoomInfo(userPowerLevels = persistentMapOf(A_USER_ID to 50)))
}
val presenter = createChangeRolesPresenter(role = RoomMember.Role.MODERATOR, room = room)
@ -363,6 +374,9 @@ class ChangeRolesPresenterTest {
initialState.eventSink(ChangeRolesEvent.UserSelectionToggled(MatrixUser(A_USER_ID_2)))
awaitItem().eventSink(ChangeRolesEvent.Save)
val loadingState = awaitItem()
assertThat(loadingState.savingState).isInstanceOf(AsyncAction.Loading::class.java)
skipItems(1)
val failedState = awaitItem()
assertThat(failedState.savingState).isInstanceOf(AsyncAction.Failure::class.java)
@ -373,7 +387,7 @@ class ChangeRolesPresenterTest {
private fun TestScope.createChangeRolesPresenter(
role: RoomMember.Role = RoomMember.Role.ADMIN,
room: FakeMatrixRoom = FakeMatrixRoom(),
room: FakeJoinedRoom = FakeJoinedRoom(),
dispatchers: CoroutineDispatchers = testCoroutineDispatchers(),
analyticsService: FakeAnalyticsService = FakeAnalyticsService(),
): ChangeRolesPresenter {

Some files were not shown because too many files have changed in this diff Show more