Implement Knock action (until the SDK level)
This commit is contained in:
parent
025c6294c2
commit
70d7b5a61f
14 changed files with 172 additions and 5 deletions
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 = { },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue