Implement Knock action (until the SDK level)

This commit is contained in:
Benoit Marty 2024-04-19 17:51:08 +02:00 committed by Benoit Marty
parent 025c6294c2
commit 70d7b5a61f
14 changed files with 172 additions and 5 deletions

View file

@ -19,6 +19,8 @@ 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 object KnockRoom : JoinRoomEvents
data object ClearError : JoinRoomEvents
data object AcceptInvite : JoinRoomEvents data object AcceptInvite : JoinRoomEvents
data object DeclineInvite : JoinRoomEvents data object DeclineInvite : JoinRoomEvents
} }

View file

@ -49,6 +49,7 @@ class JoinRoomNode @AssistedInject constructor(
JoinRoomView( JoinRoomView(
state = state, state = state,
onBackPressed = ::navigateUp, onBackPressed = ::navigateUp,
onKnockSuccess = ::navigateUp,
modifier = modifier modifier = modifier
) )
acceptDeclineInviteView.Render( acceptDeclineInviteView.Render(

View file

@ -18,19 +18,25 @@ package io.element.android.features.joinroom.impl
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableIntStateOf
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.setValue import androidx.compose.runtime.setValue
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
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.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.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.architecture.runUpdatingState
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.RoomId
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
@ -39,6 +45,8 @@ 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.MatrixRoomInfo
import io.element.android.libraries.matrix.api.room.preview.RoomPreview import io.element.android.libraries.matrix.api.room.preview.RoomPreview
import io.element.android.libraries.matrix.ui.model.toInviteSender import io.element.android.libraries.matrix.ui.model.toInviteSender
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import java.util.Optional import java.util.Optional
class JoinRoomPresenter @AssistedInject constructor( class JoinRoomPresenter @AssistedInject constructor(
@ -46,6 +54,7 @@ class JoinRoomPresenter @AssistedInject constructor(
@Assisted private val roomIdOrAlias: RoomIdOrAlias, @Assisted private val roomIdOrAlias: RoomIdOrAlias,
@Assisted private val roomDescription: Optional<RoomDescription>, @Assisted private val roomDescription: Optional<RoomDescription>,
private val matrixClient: MatrixClient, private val matrixClient: MatrixClient,
private val knockRoom: KnockRoom,
private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>, private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
) : Presenter<JoinRoomState> { ) : Presenter<JoinRoomState> {
interface Factory { interface Factory {
@ -58,8 +67,10 @@ class JoinRoomPresenter @AssistedInject constructor(
@Composable @Composable
override fun present(): JoinRoomState { override fun present(): JoinRoomState {
val coroutineScope = rememberCoroutineScope()
var retryCount by remember { mutableIntStateOf(0) } var retryCount by remember { mutableIntStateOf(0) }
val roomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty()) val roomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty())
val knockAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
val contentState by produceState<ContentState>( val contentState by produceState<ContentState>(
initialValue = ContentState.Loading(roomIdOrAlias), initialValue = ContentState.Loading(roomIdOrAlias),
key1 = roomInfo, key1 = roomInfo,
@ -101,6 +112,9 @@ class JoinRoomPresenter @AssistedInject constructor(
AcceptDeclineInviteEvents.AcceptInvite(inviteData) AcceptDeclineInviteEvents.AcceptInvite(inviteData)
) )
} }
JoinRoomEvents.KnockRoom -> {
coroutineScope.knockRoom(roomId, knockAction)
}
JoinRoomEvents.DeclineInvite -> { JoinRoomEvents.DeclineInvite -> {
val inviteData = contentState.toInviteData() ?: return val inviteData = contentState.toInviteData() ?: return
acceptDeclineInviteState.eventSink( acceptDeclineInviteState.eventSink(
@ -110,15 +124,25 @@ class JoinRoomPresenter @AssistedInject constructor(
JoinRoomEvents.RetryFetchingContent -> { JoinRoomEvents.RetryFetchingContent -> {
retryCount++ retryCount++
} }
JoinRoomEvents.ClearError -> {
knockAction.value = AsyncAction.Uninitialized
}
} }
} }
return JoinRoomState( return JoinRoomState(
contentState = contentState, contentState = contentState,
acceptDeclineInviteState = acceptDeclineInviteState, acceptDeclineInviteState = acceptDeclineInviteState,
knockAction = knockAction.value,
eventSink = ::handleEvents eventSink = ::handleEvents
) )
} }
private fun CoroutineScope.knockRoom(roomId: RoomId, knockAction: MutableState<AsyncAction<Unit>>) = launch {
knockAction.runUpdatingState {
knockRoom(roomId)
}
}
} }
private fun RoomPreview.toContentState(): ContentState { private fun RoomPreview.toContentState(): ContentState {

View file

@ -18,6 +18,7 @@ package io.element.android.features.joinroom.impl
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import io.element.android.features.invite.api.response.AcceptDeclineInviteState import io.element.android.features.invite.api.response.AcceptDeclineInviteState
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomAlias
@ -29,6 +30,7 @@ import io.element.android.libraries.matrix.ui.model.InviteSender
data class JoinRoomState( data class JoinRoomState(
val contentState: ContentState, val contentState: ContentState,
val acceptDeclineInviteState: AcceptDeclineInviteState, val acceptDeclineInviteState: AcceptDeclineInviteState,
val knockAction: AsyncAction<Unit>,
val eventSink: (JoinRoomEvents) -> Unit val eventSink: (JoinRoomEvents) -> Unit
) { ) {
val joinAuthorisationStatus = when (contentState) { val joinAuthorisationStatus = when (contentState) {

View file

@ -19,6 +19,7 @@ package io.element.android.features.joinroom.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
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.libraries.architecture.AsyncAction
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomAlias
@ -105,10 +106,12 @@ fun aLoadedContentState(
fun aJoinRoomState( fun aJoinRoomState(
contentState: ContentState = aLoadedContentState(), contentState: ContentState = aLoadedContentState(),
acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(), acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(),
knockAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
eventSink: (JoinRoomEvents) -> Unit = {} eventSink: (JoinRoomEvents) -> Unit = {}
) = JoinRoomState( ) = JoinRoomState(
contentState = contentState, contentState = contentState,
acceptDeclineInviteState = acceptDeclineInviteState, acceptDeclineInviteState = acceptDeclineInviteState,
knockAction = knockAction,
eventSink = eventSink eventSink = eventSink
) )

View file

@ -41,6 +41,7 @@ import io.element.android.libraries.designsystem.atomic.molecules.RoomPreviewMem
import io.element.android.libraries.designsystem.atomic.organisms.RoomPreviewOrganism import io.element.android.libraries.designsystem.atomic.organisms.RoomPreviewOrganism
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.background.LightGradientBackground import io.element.android.libraries.designsystem.background.LightGradientBackground
import io.element.android.libraries.designsystem.components.async.AsyncActionView
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
@ -60,6 +61,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
fun JoinRoomView( fun JoinRoomView(
state: JoinRoomState, state: JoinRoomState,
onBackPressed: () -> Unit, onBackPressed: () -> Unit,
onKnockSuccess: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val gradientBackground = remember { LightGradientBackground() } val gradientBackground = remember { LightGradientBackground() }
@ -85,12 +87,21 @@ fun JoinRoomView(
onJoinRoom = { onJoinRoom = {
state.eventSink(JoinRoomEvents.JoinRoom) state.eventSink(JoinRoomEvents.JoinRoom)
}, },
onKnockRoom = {
state.eventSink(JoinRoomEvents.KnockRoom)
},
onRetry = { onRetry = {
state.eventSink(JoinRoomEvents.RetryFetchingContent) state.eventSink(JoinRoomEvents.RetryFetchingContent)
} }
) )
} }
) )
AsyncActionView(
async = state.knockAction,
onSuccess = { onKnockSuccess() },
onErrorDismiss = { state.eventSink(JoinRoomEvents.ClearError) },
)
} }
@Composable @Composable
@ -99,6 +110,7 @@ private fun JoinRoomFooter(
onAcceptInvite: () -> Unit, onAcceptInvite: () -> Unit,
onDeclineInvite: () -> Unit, onDeclineInvite: () -> Unit,
onJoinRoom: () -> Unit, onJoinRoom: () -> Unit,
onKnockRoom: () -> Unit,
onRetry: () -> Unit, onRetry: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
@ -142,7 +154,7 @@ private fun JoinRoomFooter(
JoinAuthorisationStatus.CanKnock -> { JoinAuthorisationStatus.CanKnock -> {
Button( Button(
text = stringResource(R.string.screen_join_room_knock_action), text = stringResource(R.string.screen_join_room_knock_action),
onClick = onJoinRoom, onClick = onKnockRoom,
modifier = modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
size = ButtonSize.Large, size = ButtonSize.Large,
) )
@ -263,6 +275,7 @@ private fun JoinRoomTopBar(
internal fun JoinRoomViewPreview(@PreviewParameter(JoinRoomStateProvider::class) state: JoinRoomState) = ElementPreview { internal fun JoinRoomViewPreview(@PreviewParameter(JoinRoomStateProvider::class) state: JoinRoomState) = ElementPreview {
JoinRoomView( JoinRoomView(
state = state, state = state,
onBackPressed = { } onBackPressed = { },
onKnockSuccess = { },
) )
} }

View file

@ -35,6 +35,7 @@ object JoinRoomModule {
@Provides @Provides
fun providesJoinRoomPresenterFactory( fun providesJoinRoomPresenterFactory(
client: MatrixClient, client: MatrixClient,
knockRoom: KnockRoom,
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>, acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
): JoinRoomPresenter.Factory { ): JoinRoomPresenter.Factory {
return object : JoinRoomPresenter.Factory { return object : JoinRoomPresenter.Factory {
@ -48,6 +49,7 @@ object JoinRoomModule {
roomIdOrAlias = roomIdOrAlias, roomIdOrAlias = roomIdOrAlias,
roomDescription = roomDescription, roomDescription = roomDescription,
matrixClient = client, matrixClient = client,
knockRoom = knockRoom,
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, acceptDeclineInvitePresenter = acceptDeclineInvitePresenter,
) )
} }

View file

@ -0,0 +1,32 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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 KnockRoom {
suspend operator fun invoke(roomId: RoomId): Result<Unit>
}
@ContributesBinding(SessionScope::class)
class DefaultKnockRoom @Inject constructor(private val client: MatrixClient) : KnockRoom {
override suspend fun invoke(roomId: RoomId) = client.knockRoom(roomId)
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.joinroom.impl
import io.element.android.features.joinroom.impl.di.KnockRoom
import io.element.android.libraries.matrix.api.core.RoomId
class FakeKnockRoom(
var lambda: (RoomId) -> Result<Unit> = { Result.success(Unit) }
) : KnockRoom {
override suspend fun invoke(roomId: RoomId) = lambda(roomId)
}

View file

@ -20,7 +20,9 @@ import com.google.common.truth.Truth.assertThat
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.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.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomAlias import io.element.android.libraries.matrix.api.core.RoomAlias
@ -269,6 +271,38 @@ class JoinRoomPresenterTest {
} }
} }
@Test
fun `present - emit knock room event`() = runTest {
val knockRoomSuccess = lambdaRecorder { _: RoomId ->
Result.success(Unit)
}
val knockRoomFailure = lambdaRecorder { roomId: RoomId ->
Result.failure<Unit>(RuntimeException("Failed to knock room $roomId"))
}
val fakeKnockRoom = FakeKnockRoom(knockRoomSuccess)
val presenter = createJoinRoomPresenter(knockRoom = fakeKnockRoom)
presenter.test {
skipItems(1)
awaitItem().also { state ->
state.eventSink(JoinRoomEvents.KnockRoom)
}
awaitItem().also { state ->
assertThat(state.knockAction).isEqualTo(AsyncAction.Success(Unit))
fakeKnockRoom.lambda = knockRoomFailure
state.eventSink(JoinRoomEvents.KnockRoom)
}
awaitItem().also { state ->
assertThat(state.knockAction).isInstanceOf(AsyncAction.Failure::class.java)
}
}
assert(knockRoomSuccess)
.isCalledOnce()
.with(value(A_ROOM_ID))
assert(knockRoomFailure)
.isCalledOnce()
.with(value(A_ROOM_ID))
}
@Test @Test
fun `present - when room is not known RoomPreview is loaded`() = runTest { fun `present - when room is not known RoomPreview is loaded`() = runTest {
val client = FakeMatrixClient( val client = FakeMatrixClient(
@ -377,6 +411,7 @@ class JoinRoomPresenterTest {
roomId: RoomId = A_ROOM_ID, roomId: RoomId = A_ROOM_ID,
roomDescription: Optional<RoomDescription> = Optional.empty(), roomDescription: Optional<RoomDescription> = Optional.empty(),
matrixClient: MatrixClient = FakeMatrixClient(), matrixClient: MatrixClient = FakeMatrixClient(),
knockRoom: KnockRoom = FakeKnockRoom(),
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState> = Presenter { anAcceptDeclineInviteState() } acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState> = Presenter { anAcceptDeclineInviteState() }
): JoinRoomPresenter { ): JoinRoomPresenter {
return JoinRoomPresenter( return JoinRoomPresenter(
@ -384,6 +419,7 @@ class JoinRoomPresenterTest {
roomIdOrAlias = roomId.toRoomIdOrAlias(), roomIdOrAlias = roomId.toRoomIdOrAlias(),
roomDescription = roomDescription, roomDescription = roomDescription,
matrixClient = matrixClient, matrixClient = matrixClient,
knockRoom = knockRoom,
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter acceptDeclineInvitePresenter = acceptDeclineInvitePresenter
) )
} }

View file

@ -20,6 +20,7 @@ import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.libraries.architecture.AsyncAction
import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EnsureNeverCalled
import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.EventsRecorder
@ -72,11 +73,25 @@ class JoinRoomViewTest {
), ),
) )
rule.clickOn(R.string.screen_join_room_knock_action) rule.clickOn(R.string.screen_join_room_knock_action)
eventsRecorder.assertSingle(JoinRoomEvents.JoinRoom) eventsRecorder.assertSingle(JoinRoomEvents.KnockRoom)
} }
@Test @Test
fun `clicking on Accept invitationon IsInvited room emits the expected Event`() { fun `clicking on closing Knock error emits the expected Event`() {
val eventsRecorder = EventsRecorder<JoinRoomEvents>()
rule.setJoinRoomView(
aJoinRoomState(
contentState = aLoadedContentState(joinAuthorisationStatus = JoinAuthorisationStatus.CanKnock),
knockAction = AsyncAction.Failure(Exception("Error")),
eventSink = eventsRecorder,
),
)
rule.clickOn(CommonStrings.action_ok)
eventsRecorder.assertSingle(JoinRoomEvents.ClearError)
}
@Test
fun `clicking on Accept invitation IsInvited room emits the expected Event`() {
val eventsRecorder = EventsRecorder<JoinRoomEvents>() val eventsRecorder = EventsRecorder<JoinRoomEvents>()
rule.setJoinRoomView( rule.setJoinRoomView(
aJoinRoomState( aJoinRoomState(
@ -118,11 +133,13 @@ class JoinRoomViewTest {
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setJoinRoomView( private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setJoinRoomView(
state: JoinRoomState, state: JoinRoomState,
onBackPressed: () -> Unit = EnsureNeverCalled(), onBackPressed: () -> Unit = EnsureNeverCalled(),
onKnockSuccess: () -> Unit = EnsureNeverCalled(),
) { ) {
setContent { setContent {
JoinRoomView( JoinRoomView(
state = state, state = state,
onBackPressed = onBackPressed, onBackPressed = onBackPressed,
onKnockSuccess = onKnockSuccess,
) )
} }
} }

View file

@ -66,6 +66,7 @@ interface MatrixClient : Closeable {
suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result<Unit> suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result<Unit>
suspend fun removeAvatar(): Result<Unit> suspend fun removeAvatar(): Result<Unit>
suspend fun joinRoom(roomId: RoomId): Result<Unit> suspend fun joinRoom(roomId: RoomId): Result<Unit>
suspend fun knockRoom(roomId: RoomId): Result<Unit>
fun syncService(): SyncService fun syncService(): SyncService
fun sessionVerificationService(): SessionVerificationService fun sessionVerificationService(): SessionVerificationService
fun pushersService(): PushersService fun pushersService(): PushersService

View file

@ -451,6 +451,10 @@ class RustMatrixClient(
} }
} }
override suspend fun knockRoom(roomId: RoomId): Result<Unit> {
return Result.failure(NotImplementedError("Not yet implemented"))
}
override suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result<Unit> = withContext(sessionDispatcher) { override suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result<Unit> = withContext(sessionDispatcher) {
runCatching { runCatching {
client.trackRecentlyVisitedRoom(roomId.value) client.trackRecentlyVisitedRoom(roomId.value)

View file

@ -106,7 +106,9 @@ class FakeMatrixClient(
var joinRoomLambda: (RoomId) -> Result<Unit> = { var joinRoomLambda: (RoomId) -> Result<Unit> = {
Result.success(Unit) Result.success(Unit)
} }
var knockRoomLambda: (RoomId) -> Result<Unit> = {
Result.success(Unit)
}
var getRoomInfoFlowLambda = { _: RoomId -> var getRoomInfoFlowLambda = { _: RoomId ->
flowOf<Optional<MatrixRoomInfo>>(Optional.empty()) flowOf<Optional<MatrixRoomInfo>>(Optional.empty())
} }
@ -199,6 +201,8 @@ class FakeMatrixClient(
override suspend fun joinRoom(roomId: RoomId): Result<Unit> = joinRoomLambda(roomId) override suspend fun joinRoom(roomId: RoomId): Result<Unit> = joinRoomLambda(roomId)
override suspend fun knockRoom(roomId: RoomId): Result<Unit> = knockRoomLambda(roomId)
override fun sessionVerificationService(): SessionVerificationService = sessionVerificationService override fun sessionVerificationService(): SessionVerificationService = sessionVerificationService
override fun pushersService(): PushersService = pushersService override fun pushersService(): PushersService = pushersService