From 025c6294c29981b19a1a28c060c27e6ea20b296d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 19 Apr 2024 18:05:57 +0200 Subject: [PATCH 1/5] Change API `MatrixClient.joinRoom(roomId: RoomId): Result` to `MatrixClient.joinRoom(roomId: RoomId): Result` --- .../impl/response/AcceptDeclineInvitePresenter.kt | 12 +++++++----- .../response/AcceptDeclineInvitePresenterTest.kt | 6 +++--- .../impl/root/RoomDirectoryPresenter.kt | 1 + .../features/roomdirectory/impl/root/di/JoinRoom.kt | 2 +- .../features/roomdirectory/impl/root/FakeJoinRoom.kt | 2 +- .../impl/root/RoomDirectoryPresenterTest.kt | 8 ++++---- .../android/libraries/matrix/api/MatrixClient.kt | 2 +- .../libraries/matrix/impl/RustMatrixClient.kt | 3 +-- .../libraries/matrix/test/FakeMatrixClient.kt | 6 +++--- 9 files changed, 22 insertions(+), 20 deletions(-) diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt index 5f7e80b7b1..ec18aea045 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenter.kt @@ -102,12 +102,14 @@ class AcceptDeclineInvitePresenter @Inject constructor( private fun CoroutineScope.acceptInvite(roomId: RoomId, acceptedAction: MutableState>) = launch { acceptedAction.runUpdatingState { - client.joinRoom(roomId).onSuccess { - notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId, doRender = true) - client.getRoom(roomId)?.use { room -> - analyticsService.capture(room.toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite)) + client.joinRoom(roomId) + .onSuccess { + notificationDrawerManager.clearMembershipNotificationForRoom(client.sessionId, roomId, doRender = true) + client.getRoom(roomId)?.use { room -> + analyticsService.capture(room.toAnalyticsJoinedRoom(JoinedRoom.Trigger.Invite)) + } } - } + .map { roomId } } } diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt index dfb330da59..90dcc104d4 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/response/AcceptDeclineInvitePresenterTest.kt @@ -164,7 +164,7 @@ class AcceptDeclineInvitePresenterTest { @Test fun `present - accepting invite error flow`() = runTest { val joinRoomFailure = lambdaRecorder { roomId: RoomId -> - Result.failure(RuntimeException("Failed to join room $roomId")) + Result.failure(RuntimeException("Failed to join room $roomId")) } val client = FakeMatrixClient().apply { joinRoomLambda = joinRoomFailure @@ -197,8 +197,8 @@ class AcceptDeclineInvitePresenterTest { @Test fun `present - accepting invite success flow`() = runTest { - val joinRoomSuccess = lambdaRecorder { roomId: RoomId -> - Result.success(roomId) + val joinRoomSuccess = lambdaRecorder { _: RoomId -> + Result.success(Unit) } val client = FakeMatrixClient().apply { joinRoomLambda = joinRoomSuccess diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt index 5d4cef55cb..4f9130613f 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenter.kt @@ -108,6 +108,7 @@ class RoomDirectoryPresenter @Inject constructor( private fun CoroutineScope.joinRoom(state: MutableState>, roomId: RoomId) = launch { state.runUpdatingState { joinRoom(roomId) + .map { roomId } } } diff --git a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/di/JoinRoom.kt b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/di/JoinRoom.kt index 983d2a1dd2..477b49e4f6 100644 --- a/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/di/JoinRoom.kt +++ b/features/roomdirectory/impl/src/main/kotlin/io/element/android/features/roomdirectory/impl/root/di/JoinRoom.kt @@ -23,7 +23,7 @@ import io.element.android.libraries.matrix.api.core.RoomId import javax.inject.Inject interface JoinRoom { - suspend operator fun invoke(roomId: RoomId): Result + suspend operator fun invoke(roomId: RoomId): Result } @ContributesBinding(SessionScope::class) diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/FakeJoinRoom.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/FakeJoinRoom.kt index 3f4d17aefd..6251bcaefa 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/FakeJoinRoom.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/FakeJoinRoom.kt @@ -20,7 +20,7 @@ import io.element.android.features.roomdirectory.impl.root.di.JoinRoom import io.element.android.libraries.matrix.api.core.RoomId class FakeJoinRoom( - var lambda: (RoomId) -> Result = { Result.success(it) } + var lambda: (RoomId) -> Result = { Result.success(Unit) } ) : JoinRoom { override suspend fun invoke(roomId: RoomId) = lambda(roomId) } diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt index eefafc86e1..3af102146b 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt @@ -138,11 +138,11 @@ import org.junit.Test @Test fun `present - emit join room event`() = runTest { - val joinRoomSuccess = lambdaRecorder { roomId: RoomId -> - Result.success(roomId) + val joinRoomSuccess = lambdaRecorder { _: RoomId -> + Result.success(Unit) } val joinRoomFailure = lambdaRecorder { roomId: RoomId -> - Result.failure(RuntimeException("Failed to join room $roomId")) + Result.failure(RuntimeException("Failed to join room $roomId")) } val fakeJoinRoom = FakeJoinRoom(joinRoomSuccess) val presenter = createRoomDirectoryPresenter(joinRoom = fakeJoinRoom) @@ -171,7 +171,7 @@ import org.junit.Test roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService( createRoomDirectoryListFactory = { FakeRoomDirectoryList() } ), - joinRoom: JoinRoom = FakeJoinRoom { Result.success(it) }, + joinRoom: JoinRoom = FakeJoinRoom { Result.success(Unit) }, ): RoomDirectoryPresenter { return RoomDirectoryPresenter( dispatchers = testCoroutineDispatchers(), diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index ac2a00dbdc..3e9c1a264f 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -65,7 +65,7 @@ interface MatrixClient : Closeable { suspend fun setDisplayName(displayName: String): Result suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result suspend fun removeAvatar(): Result - suspend fun joinRoom(roomId: RoomId): Result + suspend fun joinRoom(roomId: RoomId): Result fun syncService(): SyncService fun sessionVerificationService(): SessionVerificationService fun pushersService(): PushersService diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index 48683d77ba..f5ec5d71ee 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -440,7 +440,7 @@ class RustMatrixClient( runCatching { client.removeAvatar() } } - override suspend fun joinRoom(roomId: RoomId): Result = withContext(sessionDispatcher) { + override suspend fun joinRoom(roomId: RoomId): Result = withContext(sessionDispatcher) { runCatching { client.joinRoomById(roomId.value).destroy() try { @@ -448,7 +448,6 @@ class RustMatrixClient( } catch (e: Exception) { Timber.e(e, "Timeout waiting for the room to be available in the room list") } - roomId } } diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index e43d7655f0..8578105f7d 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -103,8 +103,8 @@ class FakeMatrixClient( private var setDisplayNameResult: Result = Result.success(Unit) private var uploadAvatarResult: Result = Result.success(Unit) private var removeAvatarResult: Result = Result.success(Unit) - var joinRoomLambda: (RoomId) -> Result = { - Result.success(it) + var joinRoomLambda: (RoomId) -> Result = { + Result.success(Unit) } var getRoomInfoFlowLambda = { _: RoomId -> @@ -197,7 +197,7 @@ class FakeMatrixClient( return removeAvatarResult } - override suspend fun joinRoom(roomId: RoomId): Result = joinRoomLambda(roomId) + override suspend fun joinRoom(roomId: RoomId): Result = joinRoomLambda(roomId) override fun sessionVerificationService(): SessionVerificationService = sessionVerificationService From 70d7b5a61f8c1e2092d98841fed1cccbb0e300d3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 19 Apr 2024 17:51:08 +0200 Subject: [PATCH 2/5] Implement Knock action (until the SDK level) --- .../features/joinroom/impl/JoinRoomEvents.kt | 2 ++ .../features/joinroom/impl/JoinRoomNode.kt | 1 + .../joinroom/impl/JoinRoomPresenter.kt | 24 +++++++++++++ .../features/joinroom/impl/JoinRoomState.kt | 2 ++ .../joinroom/impl/JoinRoomStateProvider.kt | 3 ++ .../features/joinroom/impl/JoinRoomView.kt | 17 +++++++-- .../joinroom/impl/di/JoinRoomModule.kt | 2 ++ .../features/joinroom/impl/di/KnockRoom.kt | 32 +++++++++++++++++ .../features/joinroom/impl/FakeKnockRoom.kt | 26 ++++++++++++++ .../joinroom/impl/JoinRoomPresenterTest.kt | 36 +++++++++++++++++++ .../joinroom/impl/JoinRoomViewTest.kt | 21 +++++++++-- .../libraries/matrix/api/MatrixClient.kt | 1 + .../libraries/matrix/impl/RustMatrixClient.kt | 4 +++ .../libraries/matrix/test/FakeMatrixClient.kt | 6 +++- 14 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/KnockRoom.kt create mode 100644 features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/FakeKnockRoom.kt diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt index 7163fc2bad..312efd1ad2 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomEvents.kt @@ -19,6 +19,8 @@ package io.element.android.features.joinroom.impl sealed interface JoinRoomEvents { data object RetryFetchingContent : JoinRoomEvents data object JoinRoom : JoinRoomEvents + data object KnockRoom : JoinRoomEvents + data object ClearError : JoinRoomEvents data object AcceptInvite : JoinRoomEvents data object DeclineInvite : JoinRoomEvents } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt index d83a5f4b20..5d302abc8b 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomNode.kt @@ -49,6 +49,7 @@ class JoinRoomNode @AssistedInject constructor( JoinRoomView( state = state, onBackPressed = ::navigateUp, + onKnockSuccess = ::navigateUp, modifier = modifier ) acceptDeclineInviteView.Render( diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt index fbf4aeab31..ce3f0274d6 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt @@ -18,19 +18,25 @@ package io.element.android.features.joinroom.impl import androidx.annotation.VisibleForTesting import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.produceState import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import dagger.assisted.Assisted import dagger.assisted.AssistedInject 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.InviteData +import io.element.android.features.joinroom.impl.di.KnockRoom 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.runUpdatingState import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.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.preview.RoomPreview import io.element.android.libraries.matrix.ui.model.toInviteSender +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import java.util.Optional class JoinRoomPresenter @AssistedInject constructor( @@ -46,6 +54,7 @@ class JoinRoomPresenter @AssistedInject constructor( @Assisted private val roomIdOrAlias: RoomIdOrAlias, @Assisted private val roomDescription: Optional, private val matrixClient: MatrixClient, + private val knockRoom: KnockRoom, private val acceptDeclineInvitePresenter: Presenter, ) : Presenter { interface Factory { @@ -58,8 +67,10 @@ class JoinRoomPresenter @AssistedInject constructor( @Composable override fun present(): JoinRoomState { + val coroutineScope = rememberCoroutineScope() var retryCount by remember { mutableIntStateOf(0) } val roomInfo by matrixClient.getRoomInfoFlow(roomId).collectAsState(initial = Optional.empty()) + val knockAction: MutableState> = remember { mutableStateOf(AsyncAction.Uninitialized) } val contentState by produceState( initialValue = ContentState.Loading(roomIdOrAlias), key1 = roomInfo, @@ -101,6 +112,9 @@ class JoinRoomPresenter @AssistedInject constructor( AcceptDeclineInviteEvents.AcceptInvite(inviteData) ) } + JoinRoomEvents.KnockRoom -> { + coroutineScope.knockRoom(roomId, knockAction) + } JoinRoomEvents.DeclineInvite -> { val inviteData = contentState.toInviteData() ?: return acceptDeclineInviteState.eventSink( @@ -110,15 +124,25 @@ class JoinRoomPresenter @AssistedInject constructor( JoinRoomEvents.RetryFetchingContent -> { retryCount++ } + JoinRoomEvents.ClearError -> { + knockAction.value = AsyncAction.Uninitialized + } } } return JoinRoomState( contentState = contentState, acceptDeclineInviteState = acceptDeclineInviteState, + knockAction = knockAction.value, eventSink = ::handleEvents ) } + + private fun CoroutineScope.knockRoom(roomId: RoomId, knockAction: MutableState>) = launch { + knockAction.runUpdatingState { + knockRoom(roomId) + } + } } private fun RoomPreview.toContentState(): ContentState { diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt index 14f0cf2012..b32a63cc59 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomState.kt @@ -18,6 +18,7 @@ package io.element.android.features.joinroom.impl import androidx.compose.runtime.Immutable 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.AvatarSize 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( val contentState: ContentState, val acceptDeclineInviteState: AcceptDeclineInviteState, + val knockAction: AsyncAction, val eventSink: (JoinRoomEvents) -> Unit ) { val joinAuthorisationStatus = when (contentState) { diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt index 9afd4dd797..e6f50a3676 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomStateProvider.kt @@ -19,6 +19,7 @@ package io.element.android.features.joinroom.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.invite.api.response.AcceptDeclineInviteState 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.AvatarSize import io.element.android.libraries.matrix.api.core.RoomAlias @@ -105,10 +106,12 @@ fun aLoadedContentState( fun aJoinRoomState( contentState: ContentState = aLoadedContentState(), acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(), + knockAction: AsyncAction = AsyncAction.Uninitialized, eventSink: (JoinRoomEvents) -> Unit = {} ) = JoinRoomState( contentState = contentState, acceptDeclineInviteState = acceptDeclineInviteState, + knockAction = knockAction, eventSink = eventSink ) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index f9bc97231b..7deed58450 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -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.pages.HeaderFooterPage 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.AvatarSize import io.element.android.libraries.designsystem.components.button.BackButton @@ -60,6 +61,7 @@ import io.element.android.libraries.ui.strings.CommonStrings fun JoinRoomView( state: JoinRoomState, onBackPressed: () -> Unit, + onKnockSuccess: () -> Unit, modifier: Modifier = Modifier, ) { val gradientBackground = remember { LightGradientBackground() } @@ -85,12 +87,21 @@ fun JoinRoomView( onJoinRoom = { state.eventSink(JoinRoomEvents.JoinRoom) }, + onKnockRoom = { + state.eventSink(JoinRoomEvents.KnockRoom) + }, onRetry = { state.eventSink(JoinRoomEvents.RetryFetchingContent) } ) } ) + + AsyncActionView( + async = state.knockAction, + onSuccess = { onKnockSuccess() }, + onErrorDismiss = { state.eventSink(JoinRoomEvents.ClearError) }, + ) } @Composable @@ -99,6 +110,7 @@ private fun JoinRoomFooter( onAcceptInvite: () -> Unit, onDeclineInvite: () -> Unit, onJoinRoom: () -> Unit, + onKnockRoom: () -> Unit, onRetry: () -> Unit, modifier: Modifier = Modifier, ) { @@ -142,7 +154,7 @@ private fun JoinRoomFooter( JoinAuthorisationStatus.CanKnock -> { Button( text = stringResource(R.string.screen_join_room_knock_action), - onClick = onJoinRoom, + onClick = onKnockRoom, modifier = modifier.fillMaxWidth(), size = ButtonSize.Large, ) @@ -263,6 +275,7 @@ private fun JoinRoomTopBar( internal fun JoinRoomViewPreview(@PreviewParameter(JoinRoomStateProvider::class) state: JoinRoomState) = ElementPreview { JoinRoomView( state = state, - onBackPressed = { } + onBackPressed = { }, + onKnockSuccess = { }, ) } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt index 3a9e0aec48..b2f9790088 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/JoinRoomModule.kt @@ -35,6 +35,7 @@ object JoinRoomModule { @Provides fun providesJoinRoomPresenterFactory( client: MatrixClient, + knockRoom: KnockRoom, acceptDeclineInvitePresenter: Presenter, ): JoinRoomPresenter.Factory { return object : JoinRoomPresenter.Factory { @@ -48,6 +49,7 @@ object JoinRoomModule { roomIdOrAlias = roomIdOrAlias, roomDescription = roomDescription, matrixClient = client, + knockRoom = knockRoom, acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, ) } diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/KnockRoom.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/KnockRoom.kt new file mode 100644 index 0000000000..e7bfab591b --- /dev/null +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/di/KnockRoom.kt @@ -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 +} + +@ContributesBinding(SessionScope::class) +class DefaultKnockRoom @Inject constructor(private val client: MatrixClient) : KnockRoom { + override suspend fun invoke(roomId: RoomId) = client.knockRoom(roomId) +} diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/FakeKnockRoom.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/FakeKnockRoom.kt new file mode 100644 index 0000000000..d21369d2c3 --- /dev/null +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/FakeKnockRoom.kt @@ -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 = { Result.success(Unit) } +) : KnockRoom { + override suspend fun invoke(roomId: RoomId) = lambda(roomId) +} diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt index fb36532e2d..2934f09211 100644 --- a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt @@ -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.AcceptDeclineInviteState 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.libraries.architecture.AsyncAction import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.matrix.api.MatrixClient 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(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 fun `present - when room is not known RoomPreview is loaded`() = runTest { val client = FakeMatrixClient( @@ -377,6 +411,7 @@ class JoinRoomPresenterTest { roomId: RoomId = A_ROOM_ID, roomDescription: Optional = Optional.empty(), matrixClient: MatrixClient = FakeMatrixClient(), + knockRoom: KnockRoom = FakeKnockRoom(), acceptDeclineInvitePresenter: Presenter = Presenter { anAcceptDeclineInviteState() } ): JoinRoomPresenter { return JoinRoomPresenter( @@ -384,6 +419,7 @@ class JoinRoomPresenterTest { roomIdOrAlias = roomId.toRoomIdOrAlias(), roomDescription = roomDescription, matrixClient = matrixClient, + knockRoom = knockRoom, acceptDeclineInvitePresenter = acceptDeclineInvitePresenter ) } diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt index 8f3bd5bdd5..bd8f46295d 100644 --- a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomViewTest.kt @@ -20,6 +20,7 @@ import androidx.activity.ComponentActivity import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule 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.tests.testutils.EnsureNeverCalled import io.element.android.tests.testutils.EventsRecorder @@ -72,11 +73,25 @@ class JoinRoomViewTest { ), ) rule.clickOn(R.string.screen_join_room_knock_action) - eventsRecorder.assertSingle(JoinRoomEvents.JoinRoom) + eventsRecorder.assertSingle(JoinRoomEvents.KnockRoom) } @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() + 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() rule.setJoinRoomView( aJoinRoomState( @@ -118,11 +133,13 @@ class JoinRoomViewTest { private fun AndroidComposeTestRule.setJoinRoomView( state: JoinRoomState, onBackPressed: () -> Unit = EnsureNeverCalled(), + onKnockSuccess: () -> Unit = EnsureNeverCalled(), ) { setContent { JoinRoomView( state = state, onBackPressed = onBackPressed, + onKnockSuccess = onKnockSuccess, ) } } diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt index 3e9c1a264f..fb20e16c9d 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt @@ -66,6 +66,7 @@ interface MatrixClient : Closeable { suspend fun uploadAvatar(mimeType: String, data: ByteArray): Result suspend fun removeAvatar(): Result suspend fun joinRoom(roomId: RoomId): Result + suspend fun knockRoom(roomId: RoomId): Result fun syncService(): SyncService fun sessionVerificationService(): SessionVerificationService fun pushersService(): PushersService diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt index f5ec5d71ee..a24c4a35bb 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt @@ -451,6 +451,10 @@ class RustMatrixClient( } } + override suspend fun knockRoom(roomId: RoomId): Result { + return Result.failure(NotImplementedError("Not yet implemented")) + } + override suspend fun trackRecentlyVisitedRoom(roomId: RoomId): Result = withContext(sessionDispatcher) { runCatching { client.trackRecentlyVisitedRoom(roomId.value) diff --git a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt index 8578105f7d..015f764ff5 100644 --- a/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt +++ b/libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/FakeMatrixClient.kt @@ -106,7 +106,9 @@ class FakeMatrixClient( var joinRoomLambda: (RoomId) -> Result = { Result.success(Unit) } - + var knockRoomLambda: (RoomId) -> Result = { + Result.success(Unit) + } var getRoomInfoFlowLambda = { _: RoomId -> flowOf>(Optional.empty()) } @@ -199,6 +201,8 @@ class FakeMatrixClient( override suspend fun joinRoom(roomId: RoomId): Result = joinRoomLambda(roomId) + override suspend fun knockRoom(roomId: RoomId): Result = knockRoomLambda(roomId) + override fun sessionVerificationService(): SessionVerificationService = sessionVerificationService override fun pushersService(): PushersService = pushersService From 7133b821dbb26245439aa234801f8dd31320f1e4 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 19 Apr 2024 17:36:49 +0200 Subject: [PATCH 3/5] Fix missing background issue. --- .../features/joinroom/impl/JoinRoomView.kt | 71 ++++++++++--------- .../impl/RoomAliasResolverView.kt | 41 ++++++----- .../background/LightGradientBackground.kt | 50 ++++++------- 3 files changed, 85 insertions(+), 77 deletions(-) diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt index 7deed58450..89e7457fee 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomView.kt @@ -16,15 +16,15 @@ package io.element.android.features.joinroom.impl -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -64,38 +64,41 @@ fun JoinRoomView( onKnockSuccess: () -> Unit, modifier: Modifier = Modifier, ) { - val gradientBackground = remember { LightGradientBackground() } - HeaderFooterPage( - modifier = modifier.background(gradientBackground), - containerColor = Color.Transparent, - paddingValues = PaddingValues(16.dp), - topBar = { - JoinRoomTopBar(onBackClicked = onBackPressed) - }, - content = { - JoinRoomContent(contentState = state.contentState) - }, - footer = { - JoinRoomFooter( - state = state, - onAcceptInvite = { - state.eventSink(JoinRoomEvents.AcceptInvite) - }, - onDeclineInvite = { - state.eventSink(JoinRoomEvents.DeclineInvite) - }, - onJoinRoom = { - state.eventSink(JoinRoomEvents.JoinRoom) - }, - onKnockRoom = { - state.eventSink(JoinRoomEvents.KnockRoom) - }, - onRetry = { - state.eventSink(JoinRoomEvents.RetryFetchingContent) - } - ) - } - ) + Box( + modifier = modifier.fillMaxSize(), + ) { + LightGradientBackground() + HeaderFooterPage( + containerColor = Color.Transparent, + paddingValues = PaddingValues(16.dp), + topBar = { + JoinRoomTopBar(onBackClicked = onBackPressed) + }, + content = { + JoinRoomContent(contentState = state.contentState) + }, + footer = { + JoinRoomFooter( + state = state, + onAcceptInvite = { + state.eventSink(JoinRoomEvents.AcceptInvite) + }, + onDeclineInvite = { + state.eventSink(JoinRoomEvents.DeclineInvite) + }, + onJoinRoom = { + state.eventSink(JoinRoomEvents.JoinRoom) + }, + onKnockRoom = { + state.eventSink(JoinRoomEvents.KnockRoom) + }, + onRetry = { + state.eventSink(JoinRoomEvents.RetryFetchingContent) + } + ) + } + ) + } AsyncActionView( async = state.knockAction, diff --git a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverView.kt b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverView.kt index e12ef4170d..cd5bd042c8 100644 --- a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverView.kt +++ b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverView.kt @@ -16,17 +16,17 @@ package io.element.android.features.roomaliasresolver.impl -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -65,23 +65,26 @@ fun RoomAliasResolverView( latestOnAliasResolved(state.resolveState.data) } } - val gradientBackground = remember { LightGradientBackground() } - HeaderFooterPage( - modifier = modifier.background(gradientBackground), - containerColor = Color.Transparent, - paddingValues = PaddingValues(16.dp), - topBar = { - RoomAliasResolverTopBar(onBackClicked = onBackPressed) - }, - content = { - RoomAliasResolverContent(state = state) - }, - footer = { - RoomAliasResolverFooter( - state = state, - ) - } - ) + Box( + modifier = modifier.fillMaxSize(), + ) { + LightGradientBackground() + HeaderFooterPage( + containerColor = Color.Transparent, + paddingValues = PaddingValues(16.dp), + topBar = { + RoomAliasResolverTopBar(onBackClicked = onBackPressed) + }, + content = { + RoomAliasResolverContent(state = state) + }, + footer = { + RoomAliasResolverFooter( + state = state, + ) + } + ) + } } @Composable diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/background/LightGradientBackground.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/background/LightGradientBackground.kt index 89eede3bc0..793f4891f5 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/background/LightGradientBackground.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/background/LightGradientBackground.kt @@ -16,46 +16,48 @@ package io.element.android.libraries.designsystem.background -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Size import androidx.compose.ui.geometry.center import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.RadialGradientShader -import androidx.compose.ui.graphics.Shader import androidx.compose.ui.graphics.ShaderBrush import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight -class LightGradientBackground( - private val firstColor: Color = Color(0x1E0DBD8B), - private val secondColor: Color = Color(0x001273EB), - private val ratio: Float = 642 / 775f, -) : ShaderBrush() { - override fun createShader(size: Size): Shader { +/** + * Light gradient background for Join room screens. + */ +@Composable +fun LightGradientBackground( + modifier: Modifier = Modifier, + backgroundColor: Color = MaterialTheme.colorScheme.background, + firstColor: Color = Color(0x1E0DBD8B), + secondColor: Color = Color(0x001273EB), + ratio: Float = 642 / 775f, +) { + Canvas( + modifier = modifier.fillMaxSize() + ) { val biggerDimension = size.width * 1.98f - return RadialGradientShader( - colors = listOf(firstColor, secondColor), - center = size.center.copy(x = size.width * ratio, y = size.height * ratio), - radius = biggerDimension / 2f, - colorStops = listOf(0f, 0.95f) + val gradientShaderBrush = ShaderBrush( + RadialGradientShader( + colors = listOf(firstColor, secondColor), + center = size.center.copy(x = size.width * ratio, y = size.height * ratio), + radius = biggerDimension / 2f, + colorStops = listOf(0f, 0.95f) + ) ) + drawRect(backgroundColor, size = size) + drawRect(brush = gradientShaderBrush, size = size) } } @PreviewsDayNight @Composable internal fun LightGradientBackgroundPreview() = ElementPreview { - val gradientBackground = remember { - LightGradientBackground() - } - Box( - modifier = Modifier - .fillMaxSize() - .background(gradientBackground) - ) + LightGradientBackground() } From 875890f50338c3487d5a22876470165b95662ed6 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 19 Apr 2024 17:38:07 +0200 Subject: [PATCH 4/5] Move OnboardingBackground to a sub package --- .../android/features/analytics/impl/AnalyticsOptInView.kt | 2 +- .../features/ftue/impl/notifications/NotificationsOptInView.kt | 2 +- .../{components => background}/OnboardingBackground.kt | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) rename libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/{components => background}/OnboardingBackground.kt (95%) diff --git a/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt b/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt index 08095a4e33..a2290619ae 100644 --- a/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt +++ b/features/analytics/impl/src/main/kotlin/io/element/android/features/analytics/impl/AnalyticsOptInView.kt @@ -43,8 +43,8 @@ import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMo import io.element.android.libraries.designsystem.atomic.organisms.InfoListItem import io.element.android.libraries.designsystem.atomic.organisms.InfoListOrganism import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage +import io.element.android.libraries.designsystem.background.OnboardingBackground import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.components.OnboardingBackground import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight diff --git a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt index b9f902202b..1384d427dc 100644 --- a/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt +++ b/features/ftue/impl/src/main/kotlin/io/element/android/features/ftue/impl/notifications/NotificationsOptInView.kt @@ -41,8 +41,8 @@ import io.element.android.compound.tokens.generated.CompoundIcons import io.element.android.features.ftue.impl.R import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage +import io.element.android.libraries.designsystem.background.OnboardingBackground import io.element.android.libraries.designsystem.components.BigIcon -import io.element.android.libraries.designsystem.components.OnboardingBackground import io.element.android.libraries.designsystem.components.PageTitle import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/OnboardingBackground.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/background/OnboardingBackground.kt similarity index 95% rename from libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/OnboardingBackground.kt rename to libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/background/OnboardingBackground.kt index 5dbced7417..c8c703e48c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/OnboardingBackground.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/background/OnboardingBackground.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.libraries.designsystem.components +package io.element.android.libraries.designsystem.background import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.Box @@ -31,6 +31,7 @@ import androidx.compose.ui.graphics.LinearGradientShader import androidx.compose.ui.graphics.ShaderBrush import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme +import io.element.android.libraries.designsystem.components.drawWithLayer import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight From c4b6a6aa4d635048913c8f5d48aba6884847df8e Mon Sep 17 00:00:00 2001 From: ElementBot Date: Fri, 19 Apr 2024 16:23:43 +0000 Subject: [PATCH 5/5] Update screenshots --- ...ound_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en].png} | 0 ...nd_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en].png} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/uitests/src/test/snapshots/images/{ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en].png => ui_S_t[l.designsystem.background_OnboardingBackground_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en].png} (100%) rename tests/uitests/src/test/snapshots/images/{ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en].png => ui_S_t[l.designsystem.background_OnboardingBackground_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en].png} (100%) diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.background_OnboardingBackground_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.background_OnboardingBackground_null_OnboardingBackground-Day_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.background_OnboardingBackground_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.components_OnboardingBackground_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.background_OnboardingBackground_null_OnboardingBackground-Night_1_null,NEXUS_5,1.0,en].png