knock : improve a bit code and add tests.
This commit is contained in:
parent
6afc72e453
commit
2ffd46061e
17 changed files with 193 additions and 52 deletions
|
|
@ -10,8 +10,9 @@ package io.element.android.features.joinroom.impl
|
||||||
sealed interface JoinRoomEvents {
|
sealed interface JoinRoomEvents {
|
||||||
data object RetryFetchingContent : JoinRoomEvents
|
data object RetryFetchingContent : JoinRoomEvents
|
||||||
data object JoinRoom : JoinRoomEvents
|
data object JoinRoom : JoinRoomEvents
|
||||||
data class KnockRoom(val message: String) : JoinRoomEvents
|
data object KnockRoom : JoinRoomEvents
|
||||||
data class CancelKnock(val requiresConfirmation: Boolean) : JoinRoomEvents
|
data class CancelKnock(val requiresConfirmation: Boolean) : JoinRoomEvents
|
||||||
|
data class UpdateKnockMessage(val message: String) : JoinRoomEvents
|
||||||
data object ClearActionStates : JoinRoomEvents
|
data object ClearActionStates : JoinRoomEvents
|
||||||
data object AcceptInvite : JoinRoomEvents
|
data object AcceptInvite : JoinRoomEvents
|
||||||
data object DeclineInvite : JoinRoomEvents
|
data object DeclineInvite : JoinRoomEvents
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.produceState
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
|
|
@ -24,6 +25,7 @@ import im.vector.app.features.analytics.plan.JoinedRoom
|
||||||
import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents
|
import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents
|
||||||
import io.element.android.features.invite.api.response.AcceptDeclineInviteState
|
import io.element.android.features.invite.api.response.AcceptDeclineInviteState
|
||||||
import io.element.android.features.invite.api.response.InviteData
|
import io.element.android.features.invite.api.response.InviteData
|
||||||
|
import io.element.android.features.joinroom.impl.di.CancelKnockRoom
|
||||||
import io.element.android.features.joinroom.impl.di.KnockRoom
|
import io.element.android.features.joinroom.impl.di.KnockRoom
|
||||||
import io.element.android.features.roomdirectory.api.RoomDescription
|
import io.element.android.features.roomdirectory.api.RoomDescription
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
|
|
@ -46,6 +48,8 @@ import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.Optional
|
import java.util.Optional
|
||||||
|
|
||||||
|
private const val MAX_KNOCK_MESSAGE_LENGTH = 500
|
||||||
|
|
||||||
class JoinRoomPresenter @AssistedInject constructor(
|
class JoinRoomPresenter @AssistedInject constructor(
|
||||||
@Assisted private val roomId: RoomId,
|
@Assisted private val roomId: RoomId,
|
||||||
@Assisted private val roomIdOrAlias: RoomIdOrAlias,
|
@Assisted private val roomIdOrAlias: RoomIdOrAlias,
|
||||||
|
|
@ -55,6 +59,7 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||||
private val matrixClient: MatrixClient,
|
private val matrixClient: MatrixClient,
|
||||||
private val joinRoom: JoinRoom,
|
private val joinRoom: JoinRoom,
|
||||||
private val knockRoom: KnockRoom,
|
private val knockRoom: KnockRoom,
|
||||||
|
private val cancelKnockRoom: CancelKnockRoom,
|
||||||
private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
|
private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
|
||||||
private val buildMeta: BuildMeta,
|
private val buildMeta: BuildMeta,
|
||||||
) : Presenter<JoinRoomState> {
|
) : Presenter<JoinRoomState> {
|
||||||
|
|
@ -76,6 +81,7 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||||
val joinAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
|
val joinAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
|
||||||
val knockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
|
val knockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
|
||||||
val cancelKnockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
|
val cancelKnockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
|
||||||
|
var knockMessage by rememberSaveable { mutableStateOf("") }
|
||||||
val contentState by produceState<ContentState>(
|
val contentState by produceState<ContentState>(
|
||||||
initialValue = ContentState.Loading(roomIdOrAlias),
|
initialValue = ContentState.Loading(roomIdOrAlias),
|
||||||
key1 = roomInfo,
|
key1 = roomInfo,
|
||||||
|
|
@ -111,7 +117,7 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||||
fun handleEvents(event: JoinRoomEvents) {
|
fun handleEvents(event: JoinRoomEvents) {
|
||||||
when (event) {
|
when (event) {
|
||||||
JoinRoomEvents.JoinRoom -> coroutineScope.joinRoom(joinAction)
|
JoinRoomEvents.JoinRoom -> coroutineScope.joinRoom(joinAction)
|
||||||
is JoinRoomEvents.KnockRoom -> coroutineScope.knockRoom(knockAction, event.message)
|
is JoinRoomEvents.KnockRoom -> coroutineScope.knockRoom(knockAction, knockMessage)
|
||||||
JoinRoomEvents.AcceptInvite -> {
|
JoinRoomEvents.AcceptInvite -> {
|
||||||
val inviteData = contentState.toInviteData() ?: return
|
val inviteData = contentState.toInviteData() ?: return
|
||||||
acceptDeclineInviteState.eventSink(
|
acceptDeclineInviteState.eventSink(
|
||||||
|
|
@ -133,6 +139,9 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||||
joinAction.value = AsyncAction.Uninitialized
|
joinAction.value = AsyncAction.Uninitialized
|
||||||
cancelKnockAction.value = AsyncAction.Uninitialized
|
cancelKnockAction.value = AsyncAction.Uninitialized
|
||||||
}
|
}
|
||||||
|
is JoinRoomEvents.UpdateKnockMessage -> {
|
||||||
|
knockMessage = event.message.take(MAX_KNOCK_MESSAGE_LENGTH)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,6 +152,7 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||||
knockAction = knockAction.value,
|
knockAction = knockAction.value,
|
||||||
cancelKnockAction = cancelKnockAction.value,
|
cancelKnockAction = cancelKnockAction.value,
|
||||||
applicationName = buildMeta.applicationName,
|
applicationName = buildMeta.applicationName,
|
||||||
|
knockMessage = knockMessage,
|
||||||
eventSink = ::handleEvents
|
eventSink = ::handleEvents
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -159,7 +169,7 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||||
|
|
||||||
private fun CoroutineScope.knockRoom(knockAction: MutableState<AsyncAction<Unit>>, message: String) = launch {
|
private fun CoroutineScope.knockRoom(knockAction: MutableState<AsyncAction<Unit>>, message: String) = launch {
|
||||||
knockAction.runUpdatingState {
|
knockAction.runUpdatingState {
|
||||||
knockRoom(roomId)
|
knockRoom(roomIdOrAlias, message, serverNames)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,15 +177,8 @@ class JoinRoomPresenter @AssistedInject constructor(
|
||||||
if (requiresConfirmation) {
|
if (requiresConfirmation) {
|
||||||
cancelKnockAction.value = AsyncAction.ConfirmingNoParams
|
cancelKnockAction.value = AsyncAction.ConfirmingNoParams
|
||||||
} else {
|
} else {
|
||||||
val room = matrixClient.getRoom(roomId)
|
cancelKnockAction.runUpdatingState {
|
||||||
if (room == null) {
|
cancelKnockRoom(roomId)
|
||||||
cancelKnockAction.value = AsyncAction.Failure(RuntimeException())
|
|
||||||
} else {
|
|
||||||
room.use {
|
|
||||||
cancelKnockAction.runUpdatingState {
|
|
||||||
room.leave()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ data class JoinRoomState(
|
||||||
val knockAction: AsyncAction<Unit>,
|
val knockAction: AsyncAction<Unit>,
|
||||||
val cancelKnockAction: AsyncAction<Unit>,
|
val cancelKnockAction: AsyncAction<Unit>,
|
||||||
val applicationName: String,
|
val applicationName: String,
|
||||||
|
val knockMessage: String,
|
||||||
val eventSink: (JoinRoomEvents) -> Unit
|
val eventSink: (JoinRoomEvents) -> Unit
|
||||||
) {
|
) {
|
||||||
val joinAuthorisationStatus = when (contentState) {
|
val joinAuthorisationStatus = when (contentState) {
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,7 @@ fun aJoinRoomState(
|
||||||
joinAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
joinAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
||||||
knockAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
knockAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
||||||
cancelKnockAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
cancelKnockAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
||||||
|
knockMessage: String = "",
|
||||||
eventSink: (JoinRoomEvents) -> Unit = {}
|
eventSink: (JoinRoomEvents) -> Unit = {}
|
||||||
) = JoinRoomState(
|
) = JoinRoomState(
|
||||||
contentState = contentState,
|
contentState = contentState,
|
||||||
|
|
@ -139,6 +140,7 @@ fun aJoinRoomState(
|
||||||
knockAction = knockAction,
|
knockAction = knockAction,
|
||||||
cancelKnockAction = cancelKnockAction,
|
cancelKnockAction = cancelKnockAction,
|
||||||
applicationName = "AppName",
|
applicationName = "AppName",
|
||||||
|
knockMessage = knockMessage,
|
||||||
eventSink = eventSink
|
eventSink = eventSink
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.heightIn
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.sizeIn
|
import androidx.compose.foundation.layout.sizeIn
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
|
@ -27,10 +26,6 @@ import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
|
@ -85,7 +80,6 @@ fun JoinRoomView(
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier.fillMaxSize(),
|
modifier = modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
var knockMessage by rememberSaveable { mutableStateOf("") }
|
|
||||||
LightGradientBackground()
|
LightGradientBackground()
|
||||||
HeaderFooterPage(
|
HeaderFooterPage(
|
||||||
containerColor = Color.Transparent,
|
containerColor = Color.Transparent,
|
||||||
|
|
@ -97,8 +91,8 @@ fun JoinRoomView(
|
||||||
JoinRoomContent(
|
JoinRoomContent(
|
||||||
contentState = state.contentState,
|
contentState = state.contentState,
|
||||||
applicationName = state.applicationName,
|
applicationName = state.applicationName,
|
||||||
knockMessage = knockMessage,
|
knockMessage = state.knockMessage,
|
||||||
onKnockMessageUpdate = { knockMessage = it },
|
onKnockMessageUpdate = { state.eventSink(JoinRoomEvents.UpdateKnockMessage(it)) },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
footer = {
|
footer = {
|
||||||
|
|
@ -114,7 +108,7 @@ fun JoinRoomView(
|
||||||
state.eventSink(JoinRoomEvents.JoinRoom)
|
state.eventSink(JoinRoomEvents.JoinRoom)
|
||||||
},
|
},
|
||||||
onKnockRoom = {
|
onKnockRoom = {
|
||||||
state.eventSink(JoinRoomEvents.KnockRoom(knockMessage))
|
state.eventSink(JoinRoomEvents.KnockRoom)
|
||||||
},
|
},
|
||||||
onCancelKnock = {
|
onCancelKnock = {
|
||||||
state.eventSink(JoinRoomEvents.CancelKnock(requiresConfirmation = true))
|
state.eventSink(JoinRoomEvents.CancelKnock(requiresConfirmation = true))
|
||||||
|
|
@ -169,9 +163,11 @@ private fun JoinRoomFooter(
|
||||||
onGoBack: () -> Unit,
|
onGoBack: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Box(modifier = modifier
|
Box(
|
||||||
.fillMaxWidth()
|
modifier = modifier
|
||||||
.padding(top = 8.dp)) {
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp)
|
||||||
|
) {
|
||||||
if (state.contentState is ContentState.Failure) {
|
if (state.contentState is ContentState.Failure) {
|
||||||
Button(
|
Button(
|
||||||
text = stringResource(CommonStrings.action_retry),
|
text = stringResource(CommonStrings.action_retry),
|
||||||
|
|
@ -322,7 +318,7 @@ private fun JoinRoomContent(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun IsKnockedLoadedContent(modifier: Modifier = Modifier) {
|
private fun IsKnockedLoadedContent(modifier: Modifier = Modifier) {
|
||||||
BoxWithConstraints(
|
BoxWithConstraints(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
|
|
@ -397,9 +393,9 @@ private fun DefaultLoadedContent(
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = knockMessage,
|
value = knockMessage,
|
||||||
onValueChange = onKnockMessageUpdate,
|
onValueChange = onKnockMessageUpdate,
|
||||||
modifier = Modifier
|
maxLines = 3,
|
||||||
.fillMaxWidth()
|
minLines = 3,
|
||||||
.heightIn(min = 90.dp)
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.screen_join_room_knock_message_description),
|
text = stringResource(R.string.screen_join_room_knock_message_description),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
* Please see LICENSE in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.joinroom.impl.di
|
||||||
|
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
interface CancelKnockRoom {
|
||||||
|
suspend operator fun invoke(roomId: RoomId): Result<Unit>
|
||||||
|
}
|
||||||
|
|
||||||
|
@ContributesBinding(SessionScope::class)
|
||||||
|
class DefaultCancelKnockRoom @Inject constructor(private val client: MatrixClient) : CancelKnockRoom {
|
||||||
|
override suspend fun invoke(roomId: RoomId): Result<Unit> {
|
||||||
|
return client
|
||||||
|
.getPendingRoom(roomId)
|
||||||
|
?.leave()
|
||||||
|
?: Result.failure(IllegalStateException("No pending room found"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,6 +31,7 @@ object JoinRoomModule {
|
||||||
client: MatrixClient,
|
client: MatrixClient,
|
||||||
joinRoom: JoinRoom,
|
joinRoom: JoinRoom,
|
||||||
knockRoom: KnockRoom,
|
knockRoom: KnockRoom,
|
||||||
|
cancelKnockRoom: CancelKnockRoom,
|
||||||
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
|
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
|
||||||
buildMeta: BuildMeta,
|
buildMeta: BuildMeta,
|
||||||
): JoinRoomPresenter.Factory {
|
): JoinRoomPresenter.Factory {
|
||||||
|
|
@ -51,6 +52,7 @@ object JoinRoomModule {
|
||||||
matrixClient = client,
|
matrixClient = client,
|
||||||
joinRoom = joinRoom,
|
joinRoom = joinRoom,
|
||||||
knockRoom = knockRoom,
|
knockRoom = knockRoom,
|
||||||
|
cancelKnockRoom = cancelKnockRoom,
|
||||||
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter,
|
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter,
|
||||||
buildMeta = buildMeta,
|
buildMeta = buildMeta,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -10,18 +10,26 @@ package io.element.android.features.joinroom.impl.di
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
interface KnockRoom {
|
interface KnockRoom {
|
||||||
suspend operator fun invoke(roomId: RoomId): Result<Unit>
|
suspend operator fun invoke(
|
||||||
|
roomIdOrAlias: RoomIdOrAlias,
|
||||||
|
message: String,
|
||||||
|
serverNames: List<String>,
|
||||||
|
): Result<Unit>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ContributesBinding(SessionScope::class)
|
@ContributesBinding(SessionScope::class)
|
||||||
class DefaultKnockRoom @Inject constructor(private val client: MatrixClient) : KnockRoom {
|
class DefaultKnockRoom @Inject constructor(private val client: MatrixClient) : KnockRoom {
|
||||||
override suspend fun invoke(roomId: RoomId): Result<Unit> {
|
override suspend fun invoke(
|
||||||
|
roomIdOrAlias: RoomIdOrAlias,
|
||||||
|
message: String,
|
||||||
|
serverNames: List<String>
|
||||||
|
): Result<Unit> {
|
||||||
return client
|
return client
|
||||||
.knockRoom(roomId)
|
.knockRoom(roomIdOrAlias, message, serverNames)
|
||||||
.map { }
|
.map { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 New Vector Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
* Please see LICENSE in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.joinroom.impl
|
||||||
|
|
||||||
|
import io.element.android.features.joinroom.impl.di.CancelKnockRoom
|
||||||
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
import io.element.android.tests.testutils.simulateLongTask
|
||||||
|
|
||||||
|
class FakeCancelKnockRoom(
|
||||||
|
var lambda: (RoomId) -> Result<Unit> = { Result.success(Unit) }
|
||||||
|
) : CancelKnockRoom {
|
||||||
|
override suspend fun invoke(roomId: RoomId) = simulateLongTask {
|
||||||
|
lambda(roomId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,13 +8,13 @@
|
||||||
package io.element.android.features.joinroom.impl
|
package io.element.android.features.joinroom.impl
|
||||||
|
|
||||||
import io.element.android.features.joinroom.impl.di.KnockRoom
|
import io.element.android.features.joinroom.impl.di.KnockRoom
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
|
||||||
import io.element.android.tests.testutils.simulateLongTask
|
import io.element.android.tests.testutils.simulateLongTask
|
||||||
|
|
||||||
class FakeKnockRoom(
|
class FakeKnockRoom(
|
||||||
var lambda: (RoomId) -> Result<Unit> = { Result.success(Unit) }
|
var lambda: (RoomIdOrAlias, String, List<String>) -> Result<Unit> = { _, _, _ -> Result.success(Unit) }
|
||||||
) : KnockRoom {
|
) : KnockRoom {
|
||||||
override suspend fun invoke(roomId: RoomId) = simulateLongTask {
|
override suspend fun invoke(roomIdOrAlias: RoomIdOrAlias, message: String, serverNames: List<String>): Result<Unit> = simulateLongTask {
|
||||||
lambda(roomId)
|
lambda(roomIdOrAlias, message, serverNames)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import im.vector.app.features.analytics.plan.JoinedRoom
|
||||||
import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents
|
import io.element.android.features.invite.api.response.AcceptDeclineInviteEvents
|
||||||
import io.element.android.features.invite.api.response.AcceptDeclineInviteState
|
import io.element.android.features.invite.api.response.AcceptDeclineInviteState
|
||||||
import io.element.android.features.invite.api.response.anAcceptDeclineInviteState
|
import io.element.android.features.invite.api.response.anAcceptDeclineInviteState
|
||||||
|
import io.element.android.features.joinroom.impl.di.CancelKnockRoom
|
||||||
import io.element.android.features.joinroom.impl.di.KnockRoom
|
import io.element.android.features.joinroom.impl.di.KnockRoom
|
||||||
import io.element.android.features.roomdirectory.api.RoomDescription
|
import io.element.android.features.roomdirectory.api.RoomDescription
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
|
|
@ -37,6 +38,7 @@ import io.element.android.libraries.matrix.test.room.aRoomSummary
|
||||||
import io.element.android.libraries.matrix.test.room.join.FakeJoinRoom
|
import io.element.android.libraries.matrix.test.room.join.FakeJoinRoom
|
||||||
import io.element.android.libraries.matrix.ui.model.toInviteSender
|
import io.element.android.libraries.matrix.ui.model.toInviteSender
|
||||||
import io.element.android.tests.testutils.WarmUpRule
|
import io.element.android.tests.testutils.WarmUpRule
|
||||||
|
import io.element.android.tests.testutils.lambda.any
|
||||||
import io.element.android.tests.testutils.lambda.assert
|
import io.element.android.tests.testutils.lambda.assert
|
||||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||||
import io.element.android.tests.testutils.lambda.value
|
import io.element.android.tests.testutils.lambda.value
|
||||||
|
|
@ -59,6 +61,8 @@ class JoinRoomPresenterTest {
|
||||||
assertThat(state.contentState).isEqualTo(ContentState.Loading(A_ROOM_ID.toRoomIdOrAlias()))
|
assertThat(state.contentState).isEqualTo(ContentState.Loading(A_ROOM_ID.toRoomIdOrAlias()))
|
||||||
assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown)
|
assertThat(state.joinAuthorisationStatus).isEqualTo(JoinAuthorisationStatus.Unknown)
|
||||||
assertThat(state.acceptDeclineInviteState).isEqualTo(anAcceptDeclineInviteState())
|
assertThat(state.acceptDeclineInviteState).isEqualTo(anAcceptDeclineInviteState())
|
||||||
|
assertThat(state.cancelKnockAction).isEqualTo(AsyncAction.Uninitialized)
|
||||||
|
assertThat(state.knockAction).isEqualTo(AsyncAction.Uninitialized)
|
||||||
assertThat(state.applicationName).isEqualTo("AppName")
|
assertThat(state.applicationName).isEqualTo("AppName")
|
||||||
cancelAndIgnoreRemainingEvents()
|
cancelAndIgnoreRemainingEvents()
|
||||||
}
|
}
|
||||||
|
|
@ -325,16 +329,20 @@ class JoinRoomPresenterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - emit knock room event`() = runTest {
|
fun `present - emit knock room event`() = runTest {
|
||||||
val knockRoomSuccess = lambdaRecorder { _: RoomId ->
|
val knockMessage = "Knock message"
|
||||||
|
val knockRoomSuccess = lambdaRecorder { _: RoomIdOrAlias, _: String, _: List<String> ->
|
||||||
Result.success(Unit)
|
Result.success(Unit)
|
||||||
}
|
}
|
||||||
val knockRoomFailure = lambdaRecorder { roomId: RoomId ->
|
val knockRoomFailure = lambdaRecorder { roomIdOrAlias: RoomIdOrAlias, _: String, _: List<String> ->
|
||||||
Result.failure<Unit>(RuntimeException("Failed to knock room $roomId"))
|
Result.failure<Unit>(RuntimeException("Failed to knock room $roomIdOrAlias"))
|
||||||
}
|
}
|
||||||
val fakeKnockRoom = FakeKnockRoom(knockRoomSuccess)
|
val fakeKnockRoom = FakeKnockRoom(knockRoomSuccess)
|
||||||
val presenter = createJoinRoomPresenter(knockRoom = fakeKnockRoom)
|
val presenter = createJoinRoomPresenter(knockRoom = fakeKnockRoom)
|
||||||
presenter.test {
|
presenter.test {
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
|
awaitItem().also { state ->
|
||||||
|
state.eventSink(JoinRoomEvents.UpdateKnockMessage(knockMessage))
|
||||||
|
}
|
||||||
awaitItem().also { state ->
|
awaitItem().also { state ->
|
||||||
state.eventSink(JoinRoomEvents.KnockRoom)
|
state.eventSink(JoinRoomEvents.KnockRoom)
|
||||||
}
|
}
|
||||||
|
|
@ -353,8 +361,46 @@ class JoinRoomPresenterTest {
|
||||||
}
|
}
|
||||||
assert(knockRoomSuccess)
|
assert(knockRoomSuccess)
|
||||||
.isCalledOnce()
|
.isCalledOnce()
|
||||||
.with(value(A_ROOM_ID))
|
.with(value(A_ROOM_ID.toRoomIdOrAlias()), value(knockMessage), any())
|
||||||
assert(knockRoomFailure)
|
assert(knockRoomFailure)
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(value(A_ROOM_ID.toRoomIdOrAlias()), value(knockMessage), any())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - emit cancel knock room event`() = runTest {
|
||||||
|
val cancelKnockRoomSuccess = lambdaRecorder { _: RoomId ->
|
||||||
|
Result.success(Unit)
|
||||||
|
}
|
||||||
|
val cancelKnockRoomFailure = lambdaRecorder { roomId: RoomId ->
|
||||||
|
Result.failure<Unit>(RuntimeException("Failed to knock room $roomId"))
|
||||||
|
}
|
||||||
|
val cancelKnockRoom = FakeCancelKnockRoom(cancelKnockRoomSuccess)
|
||||||
|
val presenter = createJoinRoomPresenter(cancelKnockRoom = cancelKnockRoom)
|
||||||
|
presenter.test {
|
||||||
|
skipItems(1)
|
||||||
|
awaitItem().also { state ->
|
||||||
|
state.eventSink(JoinRoomEvents.CancelKnock(true))
|
||||||
|
}
|
||||||
|
awaitItem().also { state ->
|
||||||
|
assertThat(state.cancelKnockAction).isEqualTo(AsyncAction.ConfirmingNoParams)
|
||||||
|
state.eventSink(JoinRoomEvents.CancelKnock(false))
|
||||||
|
}
|
||||||
|
assertThat(awaitItem().cancelKnockAction).isEqualTo(AsyncAction.Loading)
|
||||||
|
awaitItem().also { state ->
|
||||||
|
assertThat(state.cancelKnockAction).isEqualTo(AsyncAction.Success(Unit))
|
||||||
|
cancelKnockRoom.lambda = cancelKnockRoomFailure
|
||||||
|
state.eventSink(JoinRoomEvents.CancelKnock(false))
|
||||||
|
}
|
||||||
|
assertThat(awaitItem().cancelKnockAction).isEqualTo(AsyncAction.Loading)
|
||||||
|
awaitItem().also { state ->
|
||||||
|
assertThat(state.cancelKnockAction).isInstanceOf(AsyncAction.Failure::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(cancelKnockRoomFailure)
|
||||||
|
.isCalledOnce()
|
||||||
|
.with(value(A_ROOM_ID))
|
||||||
|
assert(cancelKnockRoomSuccess)
|
||||||
.isCalledOnce()
|
.isCalledOnce()
|
||||||
.with(value(A_ROOM_ID))
|
.with(value(A_ROOM_ID))
|
||||||
}
|
}
|
||||||
|
|
@ -474,6 +520,7 @@ class JoinRoomPresenterTest {
|
||||||
Result.success(Unit)
|
Result.success(Unit)
|
||||||
},
|
},
|
||||||
knockRoom: KnockRoom = FakeKnockRoom(),
|
knockRoom: KnockRoom = FakeKnockRoom(),
|
||||||
|
cancelKnockRoom: CancelKnockRoom = FakeCancelKnockRoom(),
|
||||||
buildMeta: BuildMeta = aBuildMeta(applicationName = "AppName"),
|
buildMeta: BuildMeta = aBuildMeta(applicationName = "AppName"),
|
||||||
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState> = Presenter { anAcceptDeclineInviteState() }
|
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState> = Presenter { anAcceptDeclineInviteState() }
|
||||||
): JoinRoomPresenter {
|
): JoinRoomPresenter {
|
||||||
|
|
@ -486,6 +533,7 @@ class JoinRoomPresenterTest {
|
||||||
matrixClient = matrixClient,
|
matrixClient = matrixClient,
|
||||||
joinRoom = FakeJoinRoom(joinRoomLambda),
|
joinRoom = FakeJoinRoom(joinRoomLambda),
|
||||||
knockRoom = knockRoom,
|
knockRoom = knockRoom,
|
||||||
|
cancelKnockRoom = cancelKnockRoom,
|
||||||
buildMeta = buildMeta,
|
buildMeta = buildMeta,
|
||||||
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter
|
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ class JoinRoomViewTest {
|
||||||
rule.setJoinRoomView(
|
rule.setJoinRoomView(
|
||||||
aJoinRoomState(
|
aJoinRoomState(
|
||||||
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock),
|
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock),
|
||||||
|
knockMessage = "Knock knock",
|
||||||
eventSink = eventsRecorder,
|
eventSink = eventsRecorder,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -82,6 +83,33 @@ class JoinRoomViewTest {
|
||||||
eventsRecorder.assertSingle(JoinRoomEvents.ClearActionStates)
|
eventsRecorder.assertSingle(JoinRoomEvents.ClearActionStates)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `clicking on cancel knock request emit the expected Event`() {
|
||||||
|
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
|
||||||
|
rule.setJoinRoomView(
|
||||||
|
aJoinRoomState(
|
||||||
|
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked),
|
||||||
|
eventSink = eventsRecorder,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
rule.clickOn(R.string.screen_join_room_cancel_knock_action)
|
||||||
|
eventsRecorder.assertSingle(JoinRoomEvents.CancelKnock(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `clicking on closing Cancel Knock error emits the expected Event`() {
|
||||||
|
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
|
||||||
|
rule.setJoinRoomView(
|
||||||
|
aJoinRoomState(
|
||||||
|
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.IsKnocked),
|
||||||
|
cancelKnockAction = AsyncAction.Failure(Exception("Error")),
|
||||||
|
eventSink = eventsRecorder,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
rule.clickOn(CommonStrings.action_ok)
|
||||||
|
eventsRecorder.assertSingle(JoinRoomEvents.ClearActionStates)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `clicking on closing Join error emits the expected Event`() {
|
fun `clicking on closing Join error emits the expected Event`() {
|
||||||
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
|
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
|
||||||
|
|
@ -170,6 +198,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setJoinR
|
||||||
onBackClick: () -> Unit = EnsureNeverCalled(),
|
onBackClick: () -> Unit = EnsureNeverCalled(),
|
||||||
onJoinSuccess: () -> Unit = EnsureNeverCalled(),
|
onJoinSuccess: () -> Unit = EnsureNeverCalled(),
|
||||||
onKnockSuccess: () -> Unit = EnsureNeverCalled(),
|
onKnockSuccess: () -> Unit = EnsureNeverCalled(),
|
||||||
|
onCancelKnockSuccess: () -> Unit = EnsureNeverCalled(),
|
||||||
) {
|
) {
|
||||||
setContent {
|
setContent {
|
||||||
JoinRoomView(
|
JoinRoomView(
|
||||||
|
|
@ -177,6 +206,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setJoinR
|
||||||
onBackClick = onBackClick,
|
onBackClick = onBackClick,
|
||||||
onJoinSuccess = onJoinSuccess,
|
onJoinSuccess = onJoinSuccess,
|
||||||
onKnockSuccess = onKnockSuccess,
|
onKnockSuccess = onKnockSuccess,
|
||||||
|
onCancelKnockSuccess = onCancelKnockSuccess
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,9 @@ import io.element.android.libraries.matrix.api.notification.NotificationService
|
||||||
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
||||||
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
|
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
|
||||||
import io.element.android.libraries.matrix.api.pusher.PushersService
|
import io.element.android.libraries.matrix.api.pusher.PushersService
|
||||||
import io.element.android.libraries.matrix.api.room.PendingRoom
|
|
||||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
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.MatrixRoomInfo
|
||||||
|
import io.element.android.libraries.matrix.api.room.PendingRoom
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||||
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
||||||
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
|
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
|
||||||
|
|
@ -65,7 +65,7 @@ interface MatrixClient : Closeable {
|
||||||
suspend fun removeAvatar(): Result<Unit>
|
suspend fun removeAvatar(): Result<Unit>
|
||||||
suspend fun joinRoom(roomId: RoomId): Result<RoomSummary?>
|
suspend fun joinRoom(roomId: RoomId): Result<RoomSummary?>
|
||||||
suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomSummary?>
|
suspend fun joinRoomByIdOrAlias(roomIdOrAlias: RoomIdOrAlias, serverNames: List<String>): Result<RoomSummary?>
|
||||||
suspend fun knockRoom(roomId: RoomId): Result<RoomSummary?>
|
suspend fun knockRoom(roomIdOrAlias: RoomIdOrAlias, message: String, serverNames: List<String>): Result<RoomSummary?>
|
||||||
fun syncService(): SyncService
|
fun syncService(): SyncService
|
||||||
fun sessionVerificationService(): SessionVerificationService
|
fun sessionVerificationService(): SessionVerificationService
|
||||||
fun pushersService(): PushersService
|
fun pushersService(): PushersService
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ import io.element.android.libraries.matrix.api.notificationsettings.Notification
|
||||||
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
|
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
|
||||||
import io.element.android.libraries.matrix.api.pusher.PushersService
|
import io.element.android.libraries.matrix.api.pusher.PushersService
|
||||||
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
|
||||||
import io.element.android.libraries.matrix.api.room.PendingRoom
|
|
||||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||||
|
import io.element.android.libraries.matrix.api.room.PendingRoom
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||||
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
||||||
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
|
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
|
||||||
|
|
@ -394,11 +394,13 @@ class RustMatrixClient(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun knockRoom(roomId: RoomId): Result<RoomSummary?> = withContext(sessionDispatcher){
|
override suspend fun knockRoom(roomIdOrAlias: RoomIdOrAlias, message: String, serverNames: List<String>): Result<RoomSummary?> = withContext(
|
||||||
|
sessionDispatcher
|
||||||
|
) {
|
||||||
runCatching {
|
runCatching {
|
||||||
client.knock(roomId.toRoomIdOrAlias().identifier).destroy()
|
client.knock(roomIdOrAlias.identifier).destroy()
|
||||||
try {
|
try {
|
||||||
awaitRoom(roomId.toRoomIdOrAlias(), 10.seconds, CurrentUserMembership.KNOCKED)
|
awaitRoom(roomIdOrAlias, 10.seconds, CurrentUserMembership.KNOCKED)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "Timeout waiting for the room to be available in the room list")
|
Timber.e(e, "Timeout waiting for the room to be available in the room list")
|
||||||
null
|
null
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ class RustRoomFactory(
|
||||||
private val roomSyncSubscriber: RoomSyncSubscriber,
|
private val roomSyncSubscriber: RoomSyncSubscriber,
|
||||||
private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory,
|
private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
private val dispatcher = dispatchers.io.limitedParallelism(1)
|
private val dispatcher = dispatchers.io.limitedParallelism(1)
|
||||||
private val mutex = Mutex()
|
private val mutex = Mutex()
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ import io.element.android.libraries.matrix.api.notification.NotificationService
|
||||||
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
import io.element.android.libraries.matrix.api.notificationsettings.NotificationSettingsService
|
||||||
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
|
import io.element.android.libraries.matrix.api.oidc.AccountManagementAction
|
||||||
import io.element.android.libraries.matrix.api.pusher.PushersService
|
import io.element.android.libraries.matrix.api.pusher.PushersService
|
||||||
import io.element.android.libraries.matrix.api.room.PendingRoom
|
|
||||||
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
import io.element.android.libraries.matrix.api.room.MatrixRoom
|
||||||
|
import io.element.android.libraries.matrix.api.room.PendingRoom
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||||
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
||||||
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
|
import io.element.android.libraries.matrix.api.room.preview.RoomPreview
|
||||||
|
|
@ -114,7 +114,7 @@ class FakeMatrixClient(
|
||||||
var joinRoomByIdOrAliasLambda: (RoomIdOrAlias, List<String>) -> Result<RoomSummary?> = { _, _ ->
|
var joinRoomByIdOrAliasLambda: (RoomIdOrAlias, List<String>) -> Result<RoomSummary?> = { _, _ ->
|
||||||
Result.success(null)
|
Result.success(null)
|
||||||
}
|
}
|
||||||
var knockRoomLambda: (RoomId) -> Result<RoomSummary?> = {
|
var knockRoomLambda: (RoomIdOrAlias, String, List<String>) -> Result<RoomSummary?> = { _, _, _ ->
|
||||||
Result.success(null)
|
Result.success(null)
|
||||||
}
|
}
|
||||||
var getRoomSummaryFlowLambda = { _: RoomIdOrAlias ->
|
var getRoomSummaryFlowLambda = { _: RoomIdOrAlias ->
|
||||||
|
|
@ -223,7 +223,9 @@ class FakeMatrixClient(
|
||||||
return joinRoomByIdOrAliasLambda(roomIdOrAlias, serverNames)
|
return joinRoomByIdOrAliasLambda(roomIdOrAlias, serverNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun knockRoom(roomId: RoomId): Result<RoomSummary?> = knockRoomLambda(roomId)
|
override suspend fun knockRoom(roomIdOrAlias: RoomIdOrAlias, message: String, serverNames: List<String>): Result<RoomSummary?> {
|
||||||
|
return knockRoomLambda(roomIdOrAlias, message, serverNames)
|
||||||
|
}
|
||||||
|
|
||||||
override fun sessionVerificationService(): SessionVerificationService = sessionVerificationService
|
override fun sessionVerificationService(): SessionVerificationService = sessionVerificationService
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import io.element.android.compound.theme.ElementTheme
|
import io.element.android.compound.theme.ElementTheme
|
||||||
|
|
@ -35,7 +34,7 @@ fun InviteSenderView(
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
) {
|
) {
|
||||||
Box(modifier = Modifier.padding(vertical = 2.dp)){
|
Box(modifier = Modifier.padding(vertical = 2.dp)) {
|
||||||
Avatar(avatarData = inviteSender.avatarData)
|
Avatar(avatarData = inviteSender.avatarData)
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue