diff --git a/.idea/dictionaries/shared.xml b/.idea/dictionaries/shared.xml index 2fc10f455b..c3aa70ef23 100644 --- a/.idea/dictionaries/shared.xml +++ b/.idea/dictionaries/shared.xml @@ -4,6 +4,7 @@ backstack ftue homeserver + konsist kover measurables onboarding diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1545c312d..3a729e7992 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,6 +18,7 @@ * [knit](#knit) * [lint](#lint) * [Unit tests](#unit-tests) + * [konsist](#konsist) * [Tests](#tests) * [Accessibility](#accessibility) * [Jetpack Compose](#jetpack-compose) @@ -156,6 +157,10 @@ Make sure the following commands execute without any error: ./gradlew test +#### konsist + +[konsist](https://github.com/LemonAppDev/konsist) is setup in the project to check that the architecture and the naming rules are followed. Konsist tests are classical Unit tests. + ### Tests Element X is currently supported on Android Marshmallow (API 23+): please test your change on an Android device (or Android emulator) running with API 23. Many issues can happen (including crashes) on older devices. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 839a5095dd..5286bde045 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -230,6 +230,7 @@ dependencies { testImplementation(libs.test.truth) testImplementation(libs.test.turbine) testImplementation(projects.libraries.matrix.test) + testImplementation(libs.test.konsist) ksp(libs.showkase.processor) } diff --git a/app/src/main/kotlin/io/element/android/x/MainActivity.kt b/app/src/main/kotlin/io/element/android/x/MainActivity.kt index 2ebfd2ad12..3b35a0ebf4 100644 --- a/app/src/main/kotlin/io/element/android/x/MainActivity.kt +++ b/app/src/main/kotlin/io/element/android/x/MainActivity.kt @@ -34,7 +34,7 @@ import com.bumble.appyx.core.integrationpoint.NodeComponentActivity import com.bumble.appyx.core.plugin.NodeReadyObserver import io.element.android.libraries.architecture.bindings import io.element.android.libraries.core.log.logger.LoggerTag -import io.element.android.libraries.designsystem.utils.LocalSnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.LocalSnackbarDispatcher import io.element.android.libraries.theme.ElementTheme import io.element.android.x.di.AppBindings import io.element.android.x.intent.SafeUriHandler diff --git a/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt b/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt index 914be65946..185b3834c5 100644 --- a/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt +++ b/app/src/main/kotlin/io/element/android/x/di/AppBindings.kt @@ -18,7 +18,7 @@ package io.element.android.x.di import com.squareup.anvil.annotations.ContributesTo import io.element.android.features.rageshake.api.reporter.BugReporter -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.di.AppScope import io.element.android.libraries.matrix.api.tracing.TracingService diff --git a/app/src/main/kotlin/io/element/android/x/di/AppModule.kt b/app/src/main/kotlin/io/element/android/x/di/AppModule.kt index f8ab5532b0..17ba415762 100644 --- a/app/src/main/kotlin/io/element/android/x/di/AppModule.kt +++ b/app/src/main/kotlin/io/element/android/x/di/AppModule.kt @@ -28,7 +28,7 @@ import io.element.android.features.messages.impl.timeline.components.customreact import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildType -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.ApplicationContext import io.element.android.libraries.di.DefaultPreferences diff --git a/app/src/test/kotlin/io/element/android/app/KonsistTest.kt b/app/src/test/kotlin/io/element/android/app/KonsistTest.kt new file mode 100644 index 0000000000..25367e8c5a --- /dev/null +++ b/app/src/test/kotlin/io/element/android/app/KonsistTest.kt @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2023 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.app + +import androidx.compose.runtime.Composable +import com.lemonappdev.konsist.api.KoModifier +import com.lemonappdev.konsist.api.Konsist +import com.lemonappdev.konsist.api.ext.list.constructors +import com.lemonappdev.konsist.api.ext.list.modifierprovider.withoutModifier +import com.lemonappdev.konsist.api.ext.list.modifierprovider.withoutOverrideModifier +import com.lemonappdev.konsist.api.ext.list.parameters +import com.lemonappdev.konsist.api.ext.list.properties +import com.lemonappdev.konsist.api.ext.list.withAllAnnotationsOf +import com.lemonappdev.konsist.api.ext.list.withAllParentsOf +import com.lemonappdev.konsist.api.ext.list.withNameEndingWith +import com.lemonappdev.konsist.api.ext.list.withReturnType +import com.lemonappdev.konsist.api.ext.list.withTopLevel +import com.lemonappdev.konsist.api.ext.list.withoutName +import com.lemonappdev.konsist.api.ext.list.withoutNameEndingWith +import com.lemonappdev.konsist.api.verify.assertFalse +import com.lemonappdev.konsist.api.verify.assertTrue +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import org.junit.Test + +class KonsistTest { + + @Test + fun `Classes extending 'Presenter' should have 'Presenter' suffix`() { + Konsist.scopeFromProject() + .classes() + .withAllParentsOf(Presenter::class) + .assertTrue { + it.name.endsWith("Presenter") + } + } + + @Test + fun `Functions with '@PreviewsDayNight' annotation should have 'Preview' suffix`() { + Konsist + .scopeFromProject() + .functions() + .withAllAnnotationsOf(PreviewsDayNight::class) + .assertTrue { + it.hasNameEndingWith("Preview") && + it.hasNameEndingWith("LightPreview").not() && + it.hasNameEndingWith("DarkPreview").not() + } + } + + @Test + fun `Top level function with '@Composable' annotation starting with a upper case should be placed in a file with the same name`() { + Konsist + .scopeFromProject() + .functions() + .withTopLevel() + .withoutModifier(KoModifier.PRIVATE) + .withoutNameEndingWith("Preview") + .withAllAnnotationsOf(Composable::class) + .withoutName( + // Add some exceptions... + "OutlinedButton", + "TextButton", + "SimpleAlertDialogContent", + ) + .assertTrue( + additionalMessage = + """ + Please check the filename. It should match the top level Composable function. If the filename is correct: + - consider making the Composable private or moving it to its own file + - at last resort, you can add an exception in the Konsist test + """.trimIndent() + ) { + if (it.name.first().isLowerCase()) { + true + } else { + val fileName = it.containingFile.name.removeSuffix(".kt") + fileName == it.name + } + } + } + + @Test + fun `Data class state MUST not have default value`() { + Konsist + .scopeFromProject() + .classes() + .withNameEndingWith("State") + .withoutName( + "CameraPositionState", + ) + .constructors + .parameters + .assertTrue { parameterDeclaration -> + parameterDeclaration.defaultValue == null && + // Using parameterDeclaration.defaultValue == null is not enough apparently, + // Also check that the text does not contain an equal sign + parameterDeclaration.text.contains("=").not() + } + } + + @Test + fun `Function which creates Presenter in test MUST be named 'createPresenterName'`() { + Konsist + .scopeFromTest() + .functions() + .withReturnType { it.name.endsWith("Presenter") } + .withoutOverrideModifier() + .assertTrue { functionDeclaration -> + functionDeclaration.name == "create${functionDeclaration.returnType?.name}" + } + } + + @Test + fun `no field should have 'm' prefix`() { + Konsist + .scopeFromProject() + .classes() + .properties() + .assertFalse { + val secondCharacterIsUppercase = it.name.getOrNull(1)?.isUpperCase() ?: false + it.name.startsWith('m') && secondCharacterIsUppercase + } + } +} diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInEventProcessor.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInEventProcessor.kt index e55f059d14..6bf7687fef 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInEventProcessor.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInEventProcessor.kt @@ -16,8 +16,8 @@ package io.element.android.appnav -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher -import io.element.android.libraries.designsystem.utils.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.room.RoomMembershipObserver import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.VerificationFlowState diff --git a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt index cf67a765d7..72fd2461d2 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/LoggedInFlowNode.kt @@ -58,7 +58,7 @@ import io.element.android.libraries.architecture.animation.rememberDefaultTransi import io.element.android.libraries.architecture.createNode import io.element.android.libraries.architecture.waitForChildAttached import io.element.android.libraries.deeplink.DeeplinkData -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.di.SessionScope import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.MAIN_SPACE diff --git a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt index 6771718d81..5b382d1dc5 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/RootPresenterTest.kt @@ -42,7 +42,7 @@ class RootPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = createPresenter() + val presenter = createRootPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -54,7 +54,7 @@ class RootPresenterTest { @Test fun `present - passes app error state`() = runTest { - val presenter = createPresenter( + val presenter = createRootPresenter( appErrorService = DefaultAppErrorStateService().apply { showError("Bad news", "Something bad happened") } @@ -75,7 +75,7 @@ class RootPresenterTest { } } - private fun createPresenter( + private fun createRootPresenter( appErrorService: AppErrorStateService = DefaultAppErrorStateService() ): RootPresenter { val crashDataStore = FakeCrashDataStore() diff --git a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt index efada670b0..fcfba8f7a1 100644 --- a/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt +++ b/appnav/src/test/kotlin/io/element/android/appnav/loggedin/LoggedInPresenterTest.kt @@ -42,7 +42,7 @@ class LoggedInPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = createPresenter() + val presenter = createLoggedInPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -54,7 +54,7 @@ class LoggedInPresenterTest { @Test fun `present - show sync spinner`() = runTest { val roomListService = FakeRoomListService() - val presenter = createPresenter(roomListService, NetworkStatus.Online) + val presenter = createLoggedInPresenter(roomListService, NetworkStatus.Online) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -66,7 +66,7 @@ class LoggedInPresenterTest { } } - private fun createPresenter( + private fun createLoggedInPresenter( roomListService: RoomListService = FakeRoomListService(), networkStatus: NetworkStatus = NetworkStatus.Offline ): LoggedInPresenter { diff --git a/changelog.d/1526.misc b/changelog.d/1526.misc new file mode 100644 index 0000000000..5a23f085af --- /dev/null +++ b/changelog.d/1526.misc @@ -0,0 +1 @@ +Add some Konsist tests. diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt index aa5ee5f3bd..40a597b649 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/addpeople/AddPeopleView.kt @@ -84,7 +84,7 @@ fun AddPeopleView( @OptIn(ExperimentalMaterial3Api::class) @Composable -fun AddPeopleViewTopBar( +private fun AddPeopleViewTopBar( hasSelectedUsers: Boolean, modifier: Modifier = Modifier, onBackPressed: () -> Unit = {}, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt index 6398536e14..8c4de1af33 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/configureroom/ConfigureRoomView.kt @@ -181,7 +181,7 @@ fun ConfigureRoomView( @OptIn(ExperimentalMaterial3Api::class) @Composable -fun ConfigureRoomToolbar( +private fun ConfigureRoomToolbar( isNextActionEnabled: Boolean, modifier: Modifier = Modifier, onBackPressed: () -> Unit = {}, @@ -207,7 +207,7 @@ fun ConfigureRoomToolbar( } @Composable -fun RoomNameWithAvatar( +private fun RoomNameWithAvatar( avatarUri: Uri?, roomName: String, modifier: Modifier = Modifier, @@ -235,7 +235,7 @@ fun RoomNameWithAvatar( } @Composable -fun RoomTopic( +private fun RoomTopic( topic: String, modifier: Modifier = Modifier, onTopicChanged: (String) -> Unit = {}, @@ -254,7 +254,7 @@ fun RoomTopic( } @Composable -fun RoomPrivacyOptions( +private fun RoomPrivacyOptions( selected: RoomPrivacy?, modifier: Modifier = Modifier, onOptionSelected: (RoomPrivacyItem) -> Unit = {}, diff --git a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt index cf77ebc189..452efa2b85 100644 --- a/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt +++ b/features/createroom/impl/src/main/kotlin/io/element/android/features/createroom/impl/root/CreateRoomRootView.kt @@ -126,7 +126,7 @@ fun CreateRoomRootView( @OptIn(ExperimentalMaterial3Api::class) @Composable -fun CreateRoomRootViewTopBar( +private fun CreateRoomRootViewTopBar( modifier: Modifier = Modifier, onClosePressed: () -> Unit = {}, ) { @@ -148,7 +148,7 @@ fun CreateRoomRootViewTopBar( } @Composable -fun CreateRoomActionButtonsList( +private fun CreateRoomActionButtonsList( state: CreateRoomRootState, modifier: Modifier = Modifier, onNewRoomClicked: () -> Unit = {}, @@ -169,7 +169,7 @@ fun CreateRoomActionButtonsList( } @Composable -fun CreateRoomActionButton( +private fun CreateRoomActionButton( @DrawableRes iconRes: Int, text: String, modifier: Modifier = Modifier, diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListState.kt b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListState.kt index c1e00727f9..43644cd6aa 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListState.kt +++ b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListState.kt @@ -25,10 +25,10 @@ import kotlinx.collections.immutable.ImmutableList @Immutable data class InviteListState( val inviteList: ImmutableList, - val declineConfirmationDialog: InviteDeclineConfirmationDialog = InviteDeclineConfirmationDialog.Hidden, - val acceptedAction: Async = Async.Uninitialized, - val declinedAction: Async = Async.Uninitialized, - val eventSink: (InviteListEvents) -> Unit = {} + val declineConfirmationDialog: InviteDeclineConfirmationDialog, + val acceptedAction: Async, + val declinedAction: Async, + val eventSink: (InviteListEvents) -> Unit ) sealed interface InviteDeclineConfirmationDialog { diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListStateProvider.kt b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListStateProvider.kt index d4d1f5c166..f187398689 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListStateProvider.kt +++ b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListStateProvider.kt @@ -39,6 +39,10 @@ open class InviteListStateProvider : PreviewParameterProvider { internal fun aInviteListState() = InviteListState( inviteList = aInviteListInviteSummaryList(), + declineConfirmationDialog = InviteDeclineConfirmationDialog.Hidden, + acceptedAction = Async.Uninitialized, + declinedAction = Async.Uninitialized, + eventSink = {}, ) internal fun aInviteListInviteSummaryList(): ImmutableList { diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt index eb6dc312c4..d6d2d2be49 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt +++ b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/InviteListView.kt @@ -111,7 +111,7 @@ fun InviteListView( @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @Composable -fun InviteListContent( +private fun InviteListContent( state: InviteListState, modifier: Modifier = Modifier, onBackClicked: () -> Unit = {}, diff --git a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt index 27d8de0117..b48cea95da 100644 --- a/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt +++ b/features/invitelist/impl/src/main/kotlin/io/element/android/features/invitelist/impl/components/InviteSummaryRow.kt @@ -77,7 +77,7 @@ internal fun InviteSummaryRow( } @Composable -internal fun DefaultInviteSummaryRow( +private fun DefaultInviteSummaryRow( invite: InviteListInviteSummary, onAcceptClicked: () -> Unit = {}, onDeclineClicked: () -> Unit = {}, diff --git a/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomState.kt b/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomState.kt index 3f14833cf0..df6d44df4d 100644 --- a/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomState.kt +++ b/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomState.kt @@ -19,10 +19,10 @@ package io.element.android.features.leaveroom.api import io.element.android.libraries.matrix.api.core.RoomId data class LeaveRoomState( - val confirmation: Confirmation = Confirmation.Hidden, - val progress: Progress = Progress.Hidden, - val error: Error = Error.Hidden, - val eventSink: (LeaveRoomEvent) -> Unit = {}, + val confirmation: Confirmation, + val progress: Progress, + val error: Error, + val eventSink: (LeaveRoomEvent) -> Unit, ) { sealed interface Confirmation { data object Hidden : Confirmation diff --git a/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomStateProvider.kt b/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomStateProvider.kt index e9b08bcd18..f82b58cba3 100644 --- a/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomStateProvider.kt +++ b/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomStateProvider.kt @@ -22,32 +22,32 @@ import io.element.android.libraries.matrix.api.core.RoomId class LeaveRoomStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - LeaveRoomState( + aLeaveRoomState( confirmation = LeaveRoomState.Confirmation.Hidden, progress = LeaveRoomState.Progress.Hidden, error = LeaveRoomState.Error.Hidden, ), - LeaveRoomState( + aLeaveRoomState( confirmation = LeaveRoomState.Confirmation.Generic(A_ROOM_ID), progress = LeaveRoomState.Progress.Hidden, error = LeaveRoomState.Error.Hidden, ), - LeaveRoomState( + aLeaveRoomState( confirmation = LeaveRoomState.Confirmation.PrivateRoom(A_ROOM_ID), progress = LeaveRoomState.Progress.Hidden, error = LeaveRoomState.Error.Hidden, ), - LeaveRoomState( + aLeaveRoomState( confirmation = LeaveRoomState.Confirmation.LastUserInRoom(A_ROOM_ID), progress = LeaveRoomState.Progress.Hidden, error = LeaveRoomState.Error.Hidden, ), - LeaveRoomState( + aLeaveRoomState( confirmation = LeaveRoomState.Confirmation.Hidden, progress = LeaveRoomState.Progress.Shown, error = LeaveRoomState.Error.Hidden, ), - LeaveRoomState( + aLeaveRoomState( confirmation = LeaveRoomState.Confirmation.Hidden, progress = LeaveRoomState.Progress.Hidden, error = LeaveRoomState.Error.Shown, @@ -56,3 +56,14 @@ class LeaveRoomStateProvider : PreviewParameterProvider { } private val A_ROOM_ID = RoomId("!aRoomId:aDomain") + +fun aLeaveRoomState( + confirmation: LeaveRoomState.Confirmation = LeaveRoomState.Confirmation.Hidden, + progress: LeaveRoomState.Progress = LeaveRoomState.Progress.Hidden, + error: LeaveRoomState.Error = LeaveRoomState.Error.Hidden, +) = LeaveRoomState( + confirmation = confirmation, + progress = progress, + error = error, + eventSink = {}, +) diff --git a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt index fff7c00410..a508b4f448 100644 --- a/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt +++ b/features/leaveroom/impl/src/test/kotlin/io/element/android/features/leaveroom/impl/LeaveRoomPresenterImplTest.kt @@ -44,7 +44,7 @@ class LeaveRoomPresenterImplTest { @Test fun `present - initial state hides all dialogs`() = runTest { - val presenter = createPresenter() + val presenter = createLeaveRoomPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -57,7 +57,7 @@ class LeaveRoomPresenterImplTest { @Test fun `present - show generic confirmation`() = runTest { - val presenter = createPresenter( + val presenter = createLeaveRoomPresenter( client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, @@ -77,7 +77,7 @@ class LeaveRoomPresenterImplTest { @Test fun `present - show private room confirmation`() = runTest { - val presenter = createPresenter( + val presenter = createLeaveRoomPresenter( client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, @@ -97,7 +97,7 @@ class LeaveRoomPresenterImplTest { @Test fun `present - show last user in room confirmation`() = runTest { - val presenter = createPresenter( + val presenter = createLeaveRoomPresenter( client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, @@ -118,7 +118,7 @@ class LeaveRoomPresenterImplTest { @Test fun `present - leaving a room leaves the room`() = runTest { val roomMembershipObserver = RoomMembershipObserver() - val presenter = createPresenter( + val presenter = createLeaveRoomPresenter( client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, @@ -140,7 +140,7 @@ class LeaveRoomPresenterImplTest { @Test fun `present - show error if leave room fails`() = runTest { - val presenter = createPresenter( + val presenter = createLeaveRoomPresenter( client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, @@ -164,7 +164,7 @@ class LeaveRoomPresenterImplTest { @Test fun `present - show progress indicator while leaving a room`() = runTest { - val presenter = createPresenter( + val presenter = createLeaveRoomPresenter( client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, @@ -186,7 +186,7 @@ class LeaveRoomPresenterImplTest { @Test fun `present - hide error hides the error`() = runTest { - val presenter = createPresenter( + val presenter = createLeaveRoomPresenter( client = FakeMatrixClient().apply { givenGetRoomResult( roomId = A_ROOM_ID, @@ -212,7 +212,7 @@ class LeaveRoomPresenterImplTest { } } -private fun TestScope.createPresenter( +private fun TestScope.createLeaveRoomPresenter( client: MatrixClient = FakeMatrixClient(), roomMembershipObserver: RoomMembershipObserver = RoomMembershipObserver(), ): LeaveRoomPresenter = LeaveRoomPresenterImpl( diff --git a/features/leaveroom/test/src/main/kotlin/io/element/android/features/leaveroom/fake/FakeLeaveRoomPresenter.kt b/features/leaveroom/test/src/main/kotlin/io/element/android/features/leaveroom/fake/FakeLeaveRoomPresenter.kt index 7a6c086436..0aac5a0d74 100644 --- a/features/leaveroom/test/src/main/kotlin/io/element/android/features/leaveroom/fake/FakeLeaveRoomPresenter.kt +++ b/features/leaveroom/test/src/main/kotlin/io/element/android/features/leaveroom/fake/FakeLeaveRoomPresenter.kt @@ -21,7 +21,7 @@ import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomPresenter import io.element.android.features.leaveroom.api.LeaveRoomState -class FakeLeaveRoomPresenter: LeaveRoomPresenter { +class FakeLeaveRoomPresenter : LeaveRoomPresenter { val events = mutableListOf() @@ -29,7 +29,12 @@ class FakeLeaveRoomPresenter: LeaveRoomPresenter { events += event } - private var state = LeaveRoomState(eventSink = ::handleEvent) + private var state = LeaveRoomState( + confirmation = LeaveRoomState.Confirmation.Hidden, + progress = LeaveRoomState.Progress.Hidden, + error = LeaveRoomState.Error.Hidden, + eventSink = ::handleEvent, + ) set(value) { field = value.copy(eventSink = ::handleEvent) } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsState.kt index d58361a82f..7f53876df8 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsState.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsState.kt @@ -17,9 +17,9 @@ package io.element.android.features.location.impl.common.permissions data class PermissionsState( - val permissions: Permissions = Permissions.NoneGranted, - val shouldShowRationale: Boolean = false, - val eventSink: (PermissionsEvents) -> Unit = {}, + val permissions: Permissions, + val shouldShowRationale: Boolean, + val eventSink: (PermissionsEvents) -> Unit, ) { sealed interface Permissions { data object AllGranted : Permissions diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationState.kt index 5dae23c998..a41449801b 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationState.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationState.kt @@ -17,11 +17,11 @@ package io.element.android.features.location.impl.send data class SendLocationState( - val permissionDialog: Dialog = Dialog.None, - val mode: Mode = Mode.PinLocation, - val hasLocationPermission: Boolean = false, - val appName: String = "AppName", - val eventSink: (SendLocationEvents) -> Unit = {}, + val permissionDialog: Dialog, + val mode: Mode, + val hasLocationPermission: Boolean, + val appName: String, + val eventSink: (SendLocationEvents) -> Unit, ) { sealed interface Mode { data object SenderLocation : Mode diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationStateProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationStateProvider.kt index 15f16f593a..7cc3534f19 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationStateProvider.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationStateProvider.kt @@ -23,35 +23,44 @@ private const val APP_NAME = "ApplicationName" class SendLocationStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - SendLocationState( + aSendLocationState( permissionDialog = SendLocationState.Dialog.None, mode = SendLocationState.Mode.PinLocation, hasLocationPermission = false, - appName = APP_NAME, ), - SendLocationState( + aSendLocationState( permissionDialog = SendLocationState.Dialog.PermissionDenied, mode = SendLocationState.Mode.PinLocation, hasLocationPermission = false, - appName = APP_NAME, ), - SendLocationState( + aSendLocationState( permissionDialog = SendLocationState.Dialog.PermissionRationale, mode = SendLocationState.Mode.PinLocation, hasLocationPermission = false, - appName = APP_NAME, ), - SendLocationState( + aSendLocationState( permissionDialog = SendLocationState.Dialog.None, mode = SendLocationState.Mode.PinLocation, hasLocationPermission = true, - appName = APP_NAME, ), - SendLocationState( + aSendLocationState( permissionDialog = SendLocationState.Dialog.None, mode = SendLocationState.Mode.SenderLocation, hasLocationPermission = true, - appName = APP_NAME, ), ) } + +private fun aSendLocationState( + permissionDialog: SendLocationState.Dialog, + mode: SendLocationState.Mode, + hasLocationPermission: Boolean, +): SendLocationState { + return SendLocationState( + permissionDialog = permissionDialog, + mode = mode, + hasLocationPermission = hasLocationPermission, + appName = APP_NAME, + eventSink = {} + ) +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/PermissionsStateFactory.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/PermissionsStateFactory.kt new file mode 100644 index 0000000000..8fe90bea57 --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/PermissionsStateFactory.kt @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023 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.location.impl + +import io.element.android.features.location.impl.common.permissions.PermissionsState + +fun aPermissionsState( + permissions: PermissionsState.Permissions = PermissionsState.Permissions.NoneGranted, + shouldShowRationale: Boolean = false, +): PermissionsState { + return PermissionsState( + permissions = permissions, + shouldShowRationale = shouldShowRationale, + eventSink = {}, + ) +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenterFake.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenterFake.kt index ad653e4df4..dfeb18d4db 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenterFake.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenterFake.kt @@ -26,7 +26,11 @@ class PermissionsPresenterFake : PermissionsPresenter { events += event } - private var state = PermissionsState(eventSink = ::handleEvent) + private var state = PermissionsState( + permissions = PermissionsState.Permissions.NoneGranted, + shouldShowRationale = false, + eventSink = ::handleEvent + ) set(value) { field = value.copy(eventSink = ::handleEvent) } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt index c0b4cb7d35..1bb99f48ce 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/SendLocationPresenterTest.kt @@ -22,6 +22,7 @@ import app.cash.turbine.test import com.google.common.truth.Truth import im.vector.app.features.analytics.plan.Composer import io.element.android.features.location.api.Location +import io.element.android.features.location.impl.aPermissionsState import io.element.android.features.location.impl.common.actions.FakeLocationActions import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsPresenter @@ -65,7 +66,7 @@ class SendLocationPresenterTest { @Test fun `initial state with permissions granted`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.AllGranted, shouldShowRationale = false, ) @@ -92,7 +93,7 @@ class SendLocationPresenterTest { @Test fun `initial state with permissions partially granted`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.SomeGranted, shouldShowRationale = false, ) @@ -119,7 +120,7 @@ class SendLocationPresenterTest { @Test fun `initial state with permissions denied`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = false, ) @@ -145,7 +146,7 @@ class SendLocationPresenterTest { @Test fun `initial state with permissions denied once`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = true, ) @@ -171,7 +172,7 @@ class SendLocationPresenterTest { @Test fun `rationale dialog dismiss`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = true, ) @@ -202,7 +203,7 @@ class SendLocationPresenterTest { @Test fun `rationale dialog continue`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = true, ) @@ -230,7 +231,7 @@ class SendLocationPresenterTest { @Test fun `permission denied dialog dismiss`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = false, ) @@ -261,7 +262,7 @@ class SendLocationPresenterTest { @Test fun `share sender location`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.AllGranted, shouldShowRationale = false, ) @@ -317,7 +318,7 @@ class SendLocationPresenterTest { @Test fun `share pin location`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = false, ) @@ -373,7 +374,7 @@ class SendLocationPresenterTest { @Test fun `composer context passes through analytics`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = false, ) @@ -419,7 +420,7 @@ class SendLocationPresenterTest { @Test fun `open settings activity`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = false, ) diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt index 9eb0c3e1e2..28beb77819 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt @@ -21,6 +21,7 @@ import app.cash.molecule.moleculeFlow import app.cash.turbine.test import com.google.common.truth.Truth import io.element.android.features.location.api.Location +import io.element.android.features.location.impl.aPermissionsState import io.element.android.features.location.impl.common.actions.FakeLocationActions import io.element.android.features.location.impl.common.permissions.PermissionsEvents import io.element.android.features.location.impl.common.permissions.PermissionsPresenter @@ -55,7 +56,7 @@ class ShowLocationPresenterTest { @Test fun `emits initial state with no location permission`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = false, ) @@ -75,7 +76,7 @@ class ShowLocationPresenterTest { @Test fun `emits initial state location permission denied once`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = true, ) @@ -94,7 +95,7 @@ class ShowLocationPresenterTest { @Test fun `emits initial state with location permission`() = runTest { - permissionsPresenterFake.givenState(PermissionsState(permissions = PermissionsState.Permissions.AllGranted)) + permissionsPresenterFake.givenState(aPermissionsState(permissions = PermissionsState.Permissions.AllGranted)) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -109,7 +110,7 @@ class ShowLocationPresenterTest { @Test fun `emits initial state with partial location permission`() = runTest { - permissionsPresenterFake.givenState(PermissionsState(permissions = PermissionsState.Permissions.SomeGranted)) + permissionsPresenterFake.givenState(aPermissionsState(permissions = PermissionsState.Permissions.SomeGranted)) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -137,7 +138,7 @@ class ShowLocationPresenterTest { @Test fun `centers on user location`() = runTest { - permissionsPresenterFake.givenState(PermissionsState(permissions = PermissionsState.Permissions.AllGranted)) + permissionsPresenterFake.givenState(aPermissionsState(permissions = PermissionsState.Permissions.AllGranted)) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -166,7 +167,7 @@ class ShowLocationPresenterTest { @Test fun `rationale dialog dismiss`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = true, ) @@ -197,7 +198,7 @@ class ShowLocationPresenterTest { @Test fun `rationale dialog continue`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = true, ) @@ -225,7 +226,7 @@ class ShowLocationPresenterTest { @Test fun `permission denied dialog dismiss`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = false, ) @@ -256,7 +257,7 @@ class ShowLocationPresenterTest { @Test fun `open settings activity`() = runTest { permissionsPresenterFake.givenState( - PermissionsState( + aPermissionsState( permissions = PermissionsState.Permissions.NoneGranted, shouldShowRationale = false, ) @@ -290,7 +291,6 @@ class ShowLocationPresenterTest { } } - companion object { private const val A_DESCRIPTION = "My happy place" } diff --git a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt index ccf9ca0c3f..8a69cdf442 100644 --- a/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt +++ b/features/login/impl/src/main/kotlin/io/element/android/features/login/impl/screens/loginpassword/LoginPasswordView.kt @@ -167,7 +167,7 @@ fun LoginPasswordView( @OptIn(ExperimentalComposeUiApi::class) @Composable -internal fun LoginForm( +private fun LoginForm( state: LoginPasswordState, isLoading: Boolean, onSubmit: () -> Unit, @@ -272,7 +272,7 @@ internal fun LoginForm( } @Composable -internal fun LoginErrorDialog(error: Throwable, onDismiss: () -> Unit) { +private fun LoginErrorDialog(error: Throwable, onDismiss: () -> Unit) { ErrorDialog( title = stringResource(id = CommonStrings.dialog_title_error), content = stringResource(loginError(error)), diff --git a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceScreen.kt b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceView.kt similarity index 98% rename from features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceScreen.kt rename to features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceView.kt index e30a4944a4..24b7c8a266 100644 --- a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceScreen.kt +++ b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/LogoutPreferenceView.kt @@ -74,7 +74,7 @@ fun LogoutPreferenceView( } @Composable -fun LogoutPreferenceContent( +private fun LogoutPreferenceContent( onClick: () -> Unit = {}, ) { PreferenceText( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index c99c0372a8..20dc17eabc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -64,9 +64,9 @@ import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher -import io.element.android.libraries.designsystem.utils.SnackbarMessage -import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index 46aad1e191..31a66acd8c 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -25,7 +25,7 @@ import io.element.android.features.messages.impl.timeline.components.reactionsum import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState import io.element.android.libraries.architecture.Async import io.element.android.libraries.designsystem.components.avatar.AvatarData -import io.element.android.libraries.designsystem.utils.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.core.RoomId @Immutable diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 7a0ff89523..e112a451ad 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -79,8 +79,8 @@ import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.utils.LogCompositions -import io.element.android.libraries.designsystem.utils.SnackbarHost -import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost +import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.timeline.item.event.LocalEventSendState import io.element.android.libraries.theme.ElementTheme diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt index 1435573fbe..05db97d3be 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/actionlist/ActionListView.kt @@ -336,7 +336,7 @@ private fun MessageSummary(event: TimelineItem.Event, modifier: Modifier = Modif private val emojiRippleRadius = 24.dp @Composable -internal fun EmojiReactionsRow( +private fun EmojiReactionsRow( highlightedEmojis: ImmutableList, onEmojiReactionClicked: (String) -> Unit, onCustomReactionClicked: () -> Unit, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesView.kt index b6aa4645b6..1174c0ffcc 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/forward/ForwardMessagesView.kt @@ -204,7 +204,7 @@ fun ForwardMessagesView( } @Composable -internal fun SelectedRooms( +private fun SelectedRooms( selectedRooms: ImmutableList, onRoomRemoved: (RoomSummaryDetails) -> Unit, modifier: Modifier = Modifier, @@ -221,7 +221,7 @@ internal fun SelectedRooms( } @Composable -internal fun RoomSummaryView( +private fun RoomSummaryView( summary: RoomSummaryDetails, isSelected: Boolean, onSelection: (RoomSummaryDetails) -> Unit, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/LocalMediaView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/LocalMediaView.kt index 631ff71f91..3ca534c310 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/LocalMediaView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/local/LocalMediaView.kt @@ -142,7 +142,7 @@ private fun MediaImageView( @UnstableApi @Composable -fun MediaVideoView( +private fun MediaVideoView( localMediaViewState: LocalMediaViewState, localMedia: LocalMedia?, modifier: Modifier = Modifier, @@ -196,7 +196,7 @@ fun MediaVideoView( } @Composable -fun MediaPDFView( +private fun MediaPDFView( localMediaViewState: LocalMediaViewState, localMedia: LocalMedia?, zoomableState: ZoomableState, @@ -211,7 +211,7 @@ fun MediaPDFView( } @Composable -fun MediaFileView( +private fun MediaFileView( localMediaViewState: LocalMediaViewState, uri: Uri?, info: MediaInfo?, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt index b295f68e11..91fff1fa72 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerPresenter.kt @@ -34,9 +34,9 @@ import io.element.android.features.messages.impl.media.local.LocalMediaActions import io.element.android.features.messages.impl.media.local.LocalMediaFactory import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher -import io.element.android.libraries.designsystem.utils.SnackbarMessage -import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MediaFile import io.element.android.libraries.ui.strings.CommonStrings diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerState.kt index 18375746c5..86abaf648e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerState.kt @@ -19,7 +19,7 @@ package io.element.android.features.messages.impl.media.viewer import io.element.android.features.messages.impl.media.local.LocalMedia import io.element.android.features.messages.impl.media.local.MediaInfo import io.element.android.libraries.architecture.Async -import io.element.android.libraries.designsystem.utils.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.media.MediaSource data class MediaViewerState( diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt index f2e42538cf..cb2775c7b6 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/media/viewer/MediaViewerView.kt @@ -62,8 +62,8 @@ import io.element.android.libraries.designsystem.theme.components.IconButton import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.TopAppBar import io.element.android.libraries.designsystem.utils.CommonDrawables -import io.element.android.libraries.designsystem.utils.SnackbarHost -import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost +import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.ui.media.MediaRequestData import io.element.android.libraries.ui.strings.CommonStrings diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt index f67a3a54e1..b920e5967d 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/AttachmentsBottomSheet.kt @@ -95,7 +95,7 @@ internal fun AttachmentsBottomSheet( @OptIn(ExperimentalMaterialApi::class) @Composable -internal fun AttachmentSourcePickerMenu( +private fun AttachmentSourcePickerMenu( state: MessageComposerState, onSendLocationClicked: () -> Unit, onCreatePollClicked: () -> Unit, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt index f94b7a9431..a45056ac67 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/messagecomposer/MessageComposerPresenter.kt @@ -35,8 +35,8 @@ import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError import io.element.android.features.messages.impl.media.local.LocalMediaFactory import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher -import io.element.android.libraries.designsystem.utils.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.SingleIn import io.element.android.libraries.featureflag.api.FeatureFlagService diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenter.kt index 0ce4856ffa..d474e3d25f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/report/ReportMessagePresenter.kt @@ -30,8 +30,8 @@ import dagger.assisted.AssistedInject import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.runUpdatingState -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher -import io.element.android.libraries.designsystem.utils.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.MatrixRoom diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt index ba02b8eb95..fdb4b309eb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt @@ -155,7 +155,7 @@ fun TimelineView( } @Composable -fun TimelineItemRow( +private fun TimelineItemRow( timelineItem: TimelineItem, highlightedItem: String?, userHasPermissionToSendMessage: Boolean, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt index 4ab98ce953..0ef1c9bc67 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemEventRow.kt @@ -213,7 +213,7 @@ fun TimelineItemEventRow( * @param content the content to display. */ @Composable -fun SwipeSensitivity( +private fun SwipeSensitivity( sensitivityFactor: Float, content: @Composable () -> Unit, ) { @@ -306,7 +306,7 @@ private fun TimelineItemEventRowContent( // Reactions if (event.reactionsState.reactions.isNotEmpty()) { - TimelineItemReactions( + TimelineItemReactionsView( reactionsState = event.reactionsState, isOutgoing = event.isMine, onReactionClicked = onReactionClicked, @@ -315,7 +315,7 @@ private fun TimelineItemEventRowContent( modifier = Modifier .constrainAs(reactions) { top.linkTo(message.bottom, margin = (-4).dp) - this.linkStartOrEnd(event) + linkStartOrEnd(event) } .zIndex(1f) .padding(start = if (event.isMine) 16.dp else 36.dp, end = 16.dp) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsView.kt index ac1889a684..3f625fd6e4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/TimelineItemReactionsView.kt @@ -37,7 +37,7 @@ import io.element.android.libraries.designsystem.utils.CommonDrawables import kotlinx.collections.immutable.ImmutableList @Composable -fun TimelineItemReactions( +fun TimelineItemReactionsView( reactionsState: TimelineItemReactions, isOutgoing: Boolean, onReactionClicked: (emoji: String) -> Unit, @@ -46,16 +46,16 @@ fun TimelineItemReactions( modifier: Modifier = Modifier, ) { var expanded: Boolean by rememberSaveable { mutableStateOf(false) } - TimelineItemReactionsView( - modifier = modifier, - reactions = reactionsState.reactions, - expanded = expanded, - isOutgoing = isOutgoing, - onReactionClick = onReactionClicked, - onReactionLongClick = onReactionLongClicked, - onMoreReactionsClick = onMoreReactionsClicked, - onToggleExpandClick = { expanded = !expanded }, - ) + TimelineItemReactionsView( + modifier = modifier, + reactions = reactionsState.reactions, + expanded = expanded, + isOutgoing = isOutgoing, + onReactionClick = onReactionClicked, + onReactionLongClick = onReactionLongClicked, + onMoreReactionsClick = onMoreReactionsClicked, + onToggleExpandClick = { expanded = !expanded }, + ) } @Composable @@ -153,7 +153,7 @@ private fun ContentToPreview( reactions: ImmutableList, isOutgoing: Boolean = false ) { - TimelineItemReactions( + TimelineItemReactionsView( reactionsState = TimelineItemReactions( reactions ), diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt index 2458686a83..c9936855f1 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/customreaction/CustomReactionEvents.kt @@ -20,5 +20,5 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem sealed interface CustomReactionEvents { data class ShowCustomReactionSheet(val event: TimelineItem.Event) : CustomReactionEvents - object DismissCustomReactionSheet : CustomReactionEvents + data object DismissCustomReactionSheet : CustomReactionEvents } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemContentView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt similarity index 100% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemContentView.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/event/TimelineItemEventContentView.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt index 344f7d6a9e..b9260e2768 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt @@ -160,7 +160,7 @@ private fun SheetContent( } @Composable -fun AggregatedReactionButton( +private fun AggregatedReactionButton( reaction: AggregatedReaction, isHighlighted: Boolean, onClick: () -> Unit, @@ -215,7 +215,7 @@ fun AggregatedReactionButton( } @Composable -fun SenderRow( +private fun SenderRow( avatarData: AvatarData, name: String, userId: String, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenu.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenu.kt index 96b9ad6a2f..6959c448cb 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenu.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenu.kt @@ -72,7 +72,7 @@ internal fun RetrySendMessageMenu( @OptIn(ExperimentalMaterial3Api::class) @Composable -internal fun RetrySendMessageMenuBottomSheet( +private fun RetrySendMessageMenuBottomSheet( isVisible: Boolean, onRetry: () -> Unit, onRemoveFailed: () -> Unit, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemLoadingMoreIndicator.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineLoadingMoreIndicator.kt similarity index 100% rename from features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemLoadingMoreIndicator.kt rename to features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineLoadingMoreIndicator.kt diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRedactedContent.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRedactedContent.kt index 7a8edae953..853ab3f030 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRedactedContent.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/model/event/TimelineItemRedactedContent.kt @@ -16,6 +16,6 @@ package io.element.android.features.messages.impl.timeline.model.event -object TimelineItemRedactedContent : TimelineItemEventContent{ +data object TimelineItemRedactedContent : TimelineItemEventContent { override val type: String = "TimelineItemRedactedContent" } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt index 9bbb514117..def74c108a 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt @@ -51,7 +51,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.mimetype.MimeTypes import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.featureflag.test.InMemoryPreferencesStore @@ -96,7 +96,7 @@ class MessagesPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = createMessagePresenter() + val presenter = createMessagesPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -117,7 +117,7 @@ class MessagesPresenterTest { fun `present - handle toggling a reaction`() = runTest { val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true) val room = FakeMatrixRoom() - val presenter = createMessagePresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) + val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -137,7 +137,7 @@ class MessagesPresenterTest { fun `present - handle toggling a reaction twice`() = runTest { val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true) val room = FakeMatrixRoom() - val presenter = createMessagePresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) + val presenter = createMessagesPresenter(matrixRoom = room, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -154,7 +154,7 @@ class MessagesPresenterTest { @Test fun `present - handle action forward`() = runTest { val navigator = FakeMessagesNavigator() - val presenter = createMessagePresenter(navigator = navigator) + val presenter = createMessagesPresenter(navigator = navigator) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -169,7 +169,7 @@ class MessagesPresenterTest { fun `present - handle action copy`() = runTest { val clipboardHelper = FakeClipboardHelper() val event = aMessageEvent() - val presenter = createMessagePresenter(clipboardHelper = clipboardHelper) + val presenter = createMessagesPresenter(clipboardHelper = clipboardHelper) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -183,7 +183,7 @@ class MessagesPresenterTest { @Test fun `present - handle action reply`() = runTest { - val presenter = createMessagePresenter() + val presenter = createMessagesPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -198,7 +198,7 @@ class MessagesPresenterTest { @Test fun `present - handle action reply to an event with no id does nothing`() = runTest { - val presenter = createMessagePresenter() + val presenter = createMessagesPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -212,7 +212,7 @@ class MessagesPresenterTest { @Test fun `present - handle action reply to an image media message`() = runTest { - val presenter = createMessagePresenter() + val presenter = createMessagesPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -243,7 +243,7 @@ class MessagesPresenterTest { @Test fun `present - handle action reply to a video media message`() = runTest { - val presenter = createMessagePresenter() + val presenter = createMessagesPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -275,7 +275,7 @@ class MessagesPresenterTest { @Test fun `present - handle action reply to a file media message`() = runTest { - val presenter = createMessagePresenter() + val presenter = createMessagesPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -302,7 +302,7 @@ class MessagesPresenterTest { @Test fun `present - handle action edit`() = runTest { - val presenter = createMessagePresenter() + val presenter = createMessagesPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -319,7 +319,7 @@ class MessagesPresenterTest { fun `present - handle action redact`() = runTest { val coroutineDispatchers = testCoroutineDispatchers(useUnconfinedTestDispatcher = true) val matrixRoom = FakeMatrixRoom() - val presenter = createMessagePresenter(matrixRoom = matrixRoom, coroutineDispatchers = coroutineDispatchers) + val presenter = createMessagesPresenter(matrixRoom = matrixRoom, coroutineDispatchers = coroutineDispatchers) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -335,7 +335,7 @@ class MessagesPresenterTest { @Test fun `present - handle action report content`() = runTest { val navigator = FakeMessagesNavigator() - val presenter = createMessagePresenter(navigator = navigator) + val presenter = createMessagesPresenter(navigator = navigator) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -348,7 +348,7 @@ class MessagesPresenterTest { @Test fun `present - handle dismiss action`() = runTest { - val presenter = createMessagePresenter() + val presenter = createMessagesPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -362,7 +362,7 @@ class MessagesPresenterTest { @Test fun `present - handle action show developer info`() = runTest { val navigator = FakeMessagesNavigator() - val presenter = createMessagePresenter(navigator = navigator) + val presenter = createMessagesPresenter(navigator = navigator) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -376,7 +376,7 @@ class MessagesPresenterTest { @Test fun `present - shows prompt to reinvite users in DM`() = runTest { val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = true, activeMemberCount = 1L) - val presenter = createMessagePresenter(matrixRoom = room) + val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -402,7 +402,7 @@ class MessagesPresenterTest { @Test fun `present - doesn't show reinvite prompt in non-direct room`() = runTest { val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = false, activeMemberCount = 1L) - val presenter = createMessagePresenter(matrixRoom = room) + val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -418,7 +418,7 @@ class MessagesPresenterTest { @Test fun `present - doesn't show reinvite prompt if other party is present`() = runTest { val room = FakeMatrixRoom(sessionId = A_SESSION_ID, isDirect = true, activeMemberCount = 2L) - val presenter = createMessagePresenter(matrixRoom = room) + val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -442,7 +442,7 @@ class MessagesPresenterTest { ) ) ) - val presenter = createMessagePresenter(matrixRoom = room) + val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -469,7 +469,7 @@ class MessagesPresenterTest { ) ) ) - val presenter = createMessagePresenter(matrixRoom = room) + val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -490,7 +490,7 @@ class MessagesPresenterTest { fun `present - handle reinviting other user when memberlist is not ready`() = runTest { val room = FakeMatrixRoom(sessionId = A_SESSION_ID) room.givenRoomMembersState(MatrixRoomMembersState.Unknown) - val presenter = createMessagePresenter(matrixRoom = room) + val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -516,7 +516,7 @@ class MessagesPresenterTest { ) ) room.givenInviteUserResult(Result.failure(Throwable("Oops!"))) - val presenter = createMessagePresenter(matrixRoom = room) + val presenter = createMessagesPresenter(matrixRoom = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -537,7 +537,7 @@ class MessagesPresenterTest { fun `present - permission to post`() = runTest { val matrixRoom = FakeMatrixRoom() matrixRoom.givenCanSendEventResult(MessageEventType.ROOM_MESSAGE, Result.success(true)) - val presenter = createMessagePresenter(matrixRoom = matrixRoom) + val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -550,7 +550,7 @@ class MessagesPresenterTest { fun `present - no permission to post`() = runTest { val matrixRoom = FakeMatrixRoom() matrixRoom.givenCanSendEventResult(MessageEventType.ROOM_MESSAGE, Result.success(false)) - val presenter = createMessagePresenter(matrixRoom = matrixRoom) + val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -565,7 +565,7 @@ class MessagesPresenterTest { @Test fun `present - permission to redact`() = runTest { val matrixRoom = FakeMatrixRoom(canRedact = true) - val presenter = createMessagePresenter(matrixRoom = matrixRoom) + val presenter = createMessagesPresenter(matrixRoom = matrixRoom) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -579,7 +579,7 @@ class MessagesPresenterTest { fun `present - handle poll end`() = runTest { val room = FakeMatrixRoom() val analyticsService = FakeAnalyticsService() - val presenter = createMessagePresenter( + val presenter = createMessagesPresenter( matrixRoom = room, analyticsService = analyticsService, ) @@ -598,7 +598,7 @@ class MessagesPresenterTest { } } - private fun TestScope.createMessagePresenter( + private fun TestScope.createMessagesPresenter( coroutineDispatchers: CoroutineDispatchers = testCoroutineDispatchers(), matrixRoom: MatrixRoom = FakeMatrixRoom(), navigator: FakeMessagesNavigator = FakeMessagesNavigator(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt index 316e39317e..f94e79f0cb 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/actionlist/ActionListPresenterTest.kt @@ -46,7 +46,7 @@ class ActionListPresenterTest { @Test fun `present - initial state`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -57,7 +57,7 @@ class ActionListPresenterTest { @Test fun `present - compute for message from me redacted`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -82,7 +82,7 @@ class ActionListPresenterTest { @Test fun `present - compute for message from others redacted`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -107,7 +107,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -139,7 +139,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message cannot sent message`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -170,7 +170,7 @@ class ActionListPresenterTest { @Test fun `present - compute for others message and can redact`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -201,7 +201,7 @@ class ActionListPresenterTest { @Test fun `present - compute for my message`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -234,7 +234,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a media item`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -265,7 +265,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a state item in debug build`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = true) + val presenter = createActionListPresenter(isDeveloperModeEnabled = true) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -294,7 +294,7 @@ class ActionListPresenterTest { @Test fun `present - compute for a state item in non-debuggable build`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -322,7 +322,7 @@ class ActionListPresenterTest { @Test fun `present - compute message in non-debuggable build`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -354,7 +354,7 @@ class ActionListPresenterTest { @Test fun `present - compute message with no actions`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -381,7 +381,7 @@ class ActionListPresenterTest { @Test fun `present - compute not sent message`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -410,7 +410,7 @@ class ActionListPresenterTest { @Test fun `present - compute for poll message`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -436,7 +436,7 @@ class ActionListPresenterTest { @Test fun `present - compute for ended poll message`() = runTest { - val presenter = anActionListPresenter(isDeveloperModeEnabled = false) + val presenter = createActionListPresenter(isDeveloperModeEnabled = false) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -460,7 +460,7 @@ class ActionListPresenterTest { } } -private fun anActionListPresenter(isDeveloperModeEnabled: Boolean): ActionListPresenter { +private fun createActionListPresenter(isDeveloperModeEnabled: Boolean): ActionListPresenter { val preferencesStore = InMemoryPreferencesStore(isDeveloperModeEnabled = isDeveloperModeEnabled) return ActionListPresenter(preferencesStore = preferencesStore) } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt index 30c8d761b3..22f28f21d0 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/attachments/AttachmentsPreviewPresenterTest.kt @@ -59,7 +59,7 @@ class AttachmentsPreviewPresenterTest { Pair(10, 10) ) ) - val presenter = anAttachmentsPreviewPresenter(room = room) + val presenter = createAttachmentsPreviewPresenter(room = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -81,7 +81,7 @@ class AttachmentsPreviewPresenterTest { val room = FakeMatrixRoom() val failure = MediaPreProcessor.Failure(null) room.givenSendMediaResult(Result.failure(failure)) - val presenter = anAttachmentsPreviewPresenter(room = room) + val presenter = createAttachmentsPreviewPresenter(room = room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -101,7 +101,7 @@ class AttachmentsPreviewPresenterTest { @Test fun `present - dismissing the progress dialog stops media upload`() = runTest { - val presenter = anAttachmentsPreviewPresenter() + val presenter = createAttachmentsPreviewPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -114,7 +114,7 @@ class AttachmentsPreviewPresenterTest { } } - private fun anAttachmentsPreviewPresenter( + private fun createAttachmentsPreviewPresenter( localMedia: LocalMedia = aLocalMedia( uri = mockMediaUrl, ), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt index 6401f60f47..79c865ce92 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/media/viewer/MediaViewerPresenterTest.kt @@ -30,7 +30,7 @@ import io.element.android.features.messages.impl.media.viewer.MediaViewerPresent import io.element.android.features.messages.media.FakeLocalMediaActions import io.element.android.features.messages.media.FakeLocalMediaFactory import io.element.android.libraries.architecture.Async -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.matrix.test.media.FakeMediaLoader import io.element.android.libraries.matrix.test.media.aMediaSource import io.element.android.tests.testutils.WarmUpRule @@ -55,7 +55,7 @@ class MediaViewerPresenterTest { fun `present - download media success scenario`() = runTest { val mediaLoader = FakeMediaLoader() val mediaActions = FakeLocalMediaActions() - val presenter = aMediaViewerPresenter(mediaLoader, mediaActions) + val presenter = createMediaViewerPresenter(mediaLoader, mediaActions) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -76,7 +76,7 @@ class MediaViewerPresenterTest { val mediaLoader = FakeMediaLoader() val mediaActions = FakeLocalMediaActions() val snackbarDispatcher = SnackbarDispatcher() - val presenter = aMediaViewerPresenter(mediaLoader, mediaActions, snackbarDispatcher) + val presenter = createMediaViewerPresenter(mediaLoader, mediaActions, snackbarDispatcher) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -122,7 +122,7 @@ class MediaViewerPresenterTest { fun `present - download media failure then retry with success scenario`() = runTest { val mediaLoader = FakeMediaLoader() val mediaActions = FakeLocalMediaActions() - val presenter = aMediaViewerPresenter(mediaLoader, mediaActions) + val presenter = createMediaViewerPresenter(mediaLoader, mediaActions) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -147,7 +147,7 @@ class MediaViewerPresenterTest { } } - private fun aMediaViewerPresenter( + private fun createMediaViewerPresenter( mediaLoader: FakeMediaLoader, localMediaActions: FakeLocalMediaActions, snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(), diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt index 8244562622..94b971f300 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/report/ReportMessagePresenterTests.kt @@ -23,7 +23,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.messages.impl.report.ReportMessageEvents import io.element.android.features.messages.impl.report.ReportMessagePresenter import io.element.android.libraries.architecture.Async -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.matrix.api.room.MatrixRoom import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_USER_ID diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt index a0b0c68810..3f86ed8b80 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/textcomposer/MessageComposerPresenterTest.kt @@ -33,7 +33,7 @@ import io.element.android.features.messages.impl.messagecomposer.MessageComposer import io.element.android.features.messages.impl.messagecomposer.MessageComposerState import io.element.android.features.messages.media.FakeLocalMediaFactory import io.element.android.libraries.core.mimetype.MimeTypes -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.test.FakeFeatureFlagService diff --git a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorContainer.kt b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorContainer.kt new file mode 100644 index 0000000000..421b0c900f --- /dev/null +++ b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorContainer.kt @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 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.networkmonitor.api.ui + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.MutableTransitionState +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.spring +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.statusBars +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +/** + * A view that displays a connectivity indicator when the device is offline, passing the padding + * needed to make sure the status bar is not overlapped to its content views. + */ +@Composable +fun ConnectivityIndicatorContainer( + isOnline: Boolean, + modifier: Modifier = Modifier, + content: @Composable (topPadding: Dp) -> Unit = {}, +) { + val isIndicatorVisible = remember { MutableTransitionState(!isOnline) }.apply { targetState = !isOnline } + + val statusBarTopPadding = if (LocalInspectionMode.current) { + // Needed to get valid UI previews + 24.dp + } else { + WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 6.dp + } + val target = remember(isIndicatorVisible.targetState, statusBarTopPadding) { + if (!isIndicatorVisible.targetState) 0.dp else statusBarTopPadding + } + val animationStateOffset by animateDpAsState( + targetValue = target, + animationSpec = spring( + stiffness = Spring.StiffnessMediumLow, + visibilityThreshold = 1.dp, + ), + label = "insets-animation", + ) + + content(animationStateOffset) + + // Display the network indicator with an animation + AnimatedVisibility( + visibleState = isIndicatorVisible, + enter = fadeIn() + expandVertically(), + exit = fadeOut() + shrinkVertically(), + ) { + Indicator(modifier) + } +} diff --git a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt index 5f32d0baa0..45f62f94b6 100644 --- a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt +++ b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/ConnectivityIndicatorView.kt @@ -18,44 +18,17 @@ package io.element.android.features.networkmonitor.api.ui import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.MutableTransitionState -import androidx.compose.animation.core.Spring -import androidx.compose.animation.core.animateDpAsState -import androidx.compose.animation.core.spring import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkVertically -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.asPaddingValues -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.foundation.layout.width -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalInspectionMode -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.text.toDp -import io.element.android.libraries.designsystem.theme.components.Icon -import io.element.android.libraries.designsystem.theme.components.Text -import io.element.android.libraries.designsystem.utils.CommonDrawables -import io.element.android.libraries.theme.ElementTheme -import io.element.android.libraries.ui.strings.CommonStrings /** * A view that displays a connectivity indicator when the device is offline, adding a default @@ -88,75 +61,6 @@ fun ConnectivityIndicatorView( } } -/** - * A view that displays a connectivity indicator when the device is offline, passing the padding - * needed to make sure the status bar is not overlapped to its content views. - */ -@Composable -fun ConnectivityIndicatorContainer( - isOnline: Boolean, - modifier: Modifier = Modifier, - content: @Composable (topPadding: Dp) -> Unit, -) { - val isIndicatorVisible = remember { MutableTransitionState(!isOnline) }.apply { targetState = !isOnline } - - val statusBarTopPadding = if (LocalInspectionMode.current) { - // Needed to get valid UI previews - 24.dp - } else { - WindowInsets.statusBars.asPaddingValues().calculateTopPadding() + 6.dp - } - val target = remember(isIndicatorVisible.targetState, statusBarTopPadding) { - if (!isIndicatorVisible.targetState) 0.dp else statusBarTopPadding - } - val animationStateOffset by animateDpAsState( - targetValue = target, - animationSpec = spring( - stiffness = Spring.StiffnessMediumLow, - visibilityThreshold = 1.dp, - ), - label = "insets-animation", - ) - - content(animationStateOffset) - - // Display the network indicator with an animation - AnimatedVisibility( - visibleState = isIndicatorVisible, - enter = fadeIn() + expandVertically(), - exit = fadeOut() + shrinkVertically(), - ) { - Indicator(modifier) - } -} - -@Composable -private fun Indicator(modifier: Modifier = Modifier) { - Row( - modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.secondaryContainer) - .statusBarsPadding() - .padding(vertical = 6.dp), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically, - ) { - val tint = MaterialTheme.colorScheme.primary - Icon( - resourceId = CommonDrawables.ic_compound_offline, - contentDescription = null, - tint = tint, - modifier = Modifier.size(16.sp.toDp()), - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = stringResource(CommonStrings.common_offline), - style = ElementTheme.typography.fontBodyMdMedium, - color = tint, - ) - } -} - @Composable private fun StatusBarPaddingSpacer(modifier: Modifier = Modifier) { Spacer(modifier = modifier.statusBarsPadding()) diff --git a/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/Indicator.kt b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/Indicator.kt new file mode 100644 index 0000000000..0be8557bed --- /dev/null +++ b/features/networkmonitor/api/src/main/kotlin/io/element/android/features/networkmonitor/api/ui/Indicator.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 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.networkmonitor.api.ui + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBarsPadding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import io.element.android.libraries.designsystem.text.toDp +import io.element.android.libraries.designsystem.theme.components.Icon +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.utils.CommonDrawables +import io.element.android.libraries.theme.ElementTheme +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +internal fun Indicator( + modifier: Modifier = Modifier, +) { + Row( + modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.secondaryContainer) + .statusBarsPadding() + .padding(vertical = 6.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + val tint = MaterialTheme.colorScheme.primary + Icon( + resourceId = CommonDrawables.ic_compound_offline, + contentDescription = null, + tint = tint, + modifier = Modifier.size(16.sp.toDp()), + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = stringResource(CommonStrings.common_offline), + style = ElementTheme.typography.fontBodyMdMedium, + color = tint, + ) + } +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollState.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollState.kt index eccaea45fc..0a7a9ad618 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollState.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollState.kt @@ -26,7 +26,7 @@ data class CreatePollState( val answers: ImmutableList, val pollKind: PollKind, val showConfirmation: Boolean, - val eventSink: (CreatePollEvents) -> Unit = {}, + val eventSink: (CreatePollEvents) -> Unit, ) data class Answer( diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollStateProvider.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollStateProvider.kt index 29aa1288ad..c1393e0da0 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollStateProvider.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollStateProvider.kt @@ -18,12 +18,13 @@ package io.element.android.features.poll.impl.create import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.matrix.api.poll.PollKind +import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf class CreatePollStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - CreatePollState( + aCreatePollState( canCreate = false, canAddAnswer = true, question = "", @@ -34,7 +35,7 @@ class CreatePollStateProvider : PreviewParameterProvider { pollKind = PollKind.Disclosed, showConfirmation = false, ), - CreatePollState( + aCreatePollState( canCreate = true, canAddAnswer = true, question = "What type of food should we have?", @@ -45,7 +46,7 @@ class CreatePollStateProvider : PreviewParameterProvider { showConfirmation = false, pollKind = PollKind.Undisclosed, ), - CreatePollState( + aCreatePollState( canCreate = true, canAddAnswer = true, question = "What type of food should we have?", @@ -56,7 +57,7 @@ class CreatePollStateProvider : PreviewParameterProvider { showConfirmation = true, pollKind = PollKind.Undisclosed, ), - CreatePollState( + aCreatePollState( canCreate = true, canAddAnswer = true, question = "What type of food should we have?", @@ -69,7 +70,7 @@ class CreatePollStateProvider : PreviewParameterProvider { showConfirmation = false, pollKind = PollKind.Undisclosed, ), - CreatePollState( + aCreatePollState( canCreate = true, canAddAnswer = false, question = "Should there be more than 20 answers?", @@ -98,7 +99,7 @@ class CreatePollStateProvider : PreviewParameterProvider { showConfirmation = false, pollKind = PollKind.Undisclosed, ), - CreatePollState( + aCreatePollState( canCreate = true, canAddAnswer = true, question = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + @@ -122,3 +123,22 @@ class CreatePollStateProvider : PreviewParameterProvider { ) ) } + +private fun aCreatePollState( + canCreate: Boolean, + canAddAnswer: Boolean, + question: String, + answers: PersistentList, + showConfirmation: Boolean, + pollKind: PollKind +): CreatePollState { + return CreatePollState( + canCreate = canCreate, + canAddAnswer = canAddAnswer, + question = question, + answers = answers, + showConfirmation = showConfirmation, + pollKind = pollKind, + eventSink = {} + ) +} diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt index 7dd67482f8..a16eb72281 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/about/AboutView.kt @@ -21,7 +21,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.libraries.designsystem.components.preferences.PreferenceText -import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.ui.strings.CommonStrings @@ -33,7 +33,7 @@ fun AboutView( onBackPressed: () -> Unit, modifier: Modifier = Modifier, ) { - PreferenceView( + PreferencePage( modifier = modifier, onBackPressed = onBackPressed, title = stringResource(id = CommonStrings.common_about) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt index 6ab46402bc..3bbc9a1b71 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/advanced/AdvancedSettingsView.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.features.preferences.impl.R import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch -import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.ui.strings.CommonStrings @@ -33,7 +33,7 @@ fun AdvancedSettingsView( onBackPressed: () -> Unit, modifier: Modifier = Modifier, ) { - PreferenceView( + PreferencePage( modifier = modifier, onBackPressed = onBackPressed, title = stringResource(id = CommonStrings.common_advanced_settings) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsView.kt index 1d6e977718..751d513385 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/analytics/AnalyticsSettingsView.kt @@ -21,7 +21,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesView -import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.ui.strings.CommonStrings @@ -32,7 +32,7 @@ fun AnalyticsSettingsView( onBackPressed: () -> Unit, modifier: Modifier = Modifier, ) { - PreferenceView( + PreferencePage( modifier = modifier, onBackPressed = onBackPressed, title = stringResource(id = CommonStrings.common_analytics) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt index 7c9988f999..c52106cd82 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/DeveloperSettingsView.kt @@ -23,7 +23,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.features.rageshake.api.preferences.RageshakePreferencesView import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory import io.element.android.libraries.designsystem.components.preferences.PreferenceText -import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.featureflag.ui.FeatureListView @@ -38,7 +38,7 @@ fun DeveloperSettingsView( onBackPressed: () -> Unit, modifier: Modifier = Modifier, ) { - PreferenceView( + PreferencePage( modifier = modifier, onBackPressed = onBackPressed, title = stringResource(id = CommonStrings.common_developer_options) @@ -85,7 +85,7 @@ fun DeveloperSettingsView( } @Composable -fun FeatureListContent( +private fun FeatureListContent( state: DeveloperSettingsState, modifier: Modifier = Modifier ) { diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingView.kt index ce1ab2ab6e..15fd6e46b7 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/developer/tracing/ConfigureTracingView.kt @@ -139,7 +139,7 @@ fun ConfigureTracingView( } @Composable -fun CrateListContent( +private fun CrateListContent( state: ConfigureTracingState, modifier: Modifier = Modifier ) { @@ -178,7 +178,7 @@ private fun TargetAndLogLevelListView( } @Composable -fun TargetAndLogLevelView( +private fun TargetAndLogLevelView( target: Target, logLevel: LogLevel, onLogLevelChange: (LogLevel) -> Unit, @@ -197,7 +197,7 @@ fun TargetAndLogLevelView( } @Composable -fun LogLevelDropdownMenu( +private fun LogLevelDropdownMenu( logLevel: LogLevel, onLogLevelChange: (LogLevel) -> Unit, modifier: Modifier = Modifier, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt index 2c82a8a957..0844480697 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt @@ -38,7 +38,7 @@ import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch import io.element.android.libraries.designsystem.components.preferences.PreferenceText -import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.Button @@ -67,7 +67,7 @@ fun NotificationSettingsView( else -> Unit } } - PreferenceView( + PreferencePage( modifier = modifier, onBackPressed = onBackPressed, title = stringResource(id = CommonStrings.screen_notification_settings_title) @@ -79,7 +79,7 @@ fun NotificationSettingsView( onContinueClicked = { state.eventSink(NotificationSettingsEvents.FixConfigurationMismatch) }, onDismissError = { state.eventSink(NotificationSettingsEvents.ClearConfigurationMismatchError) }, ) - NotificationSettingsState.MatrixSettings.Uninitialized -> return@PreferenceView + NotificationSettingsState.MatrixSettings.Uninitialized -> return@PreferencePage is NotificationSettingsState.MatrixSettings.Valid -> NotificationSettingsContentView( matrixSettings = state.matrixSettings, systemSettings = state.appSettings, diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt index 4cc95af71f..3c2c27ac5c 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/edit/EditDefaultNotificationSettingView.kt @@ -22,7 +22,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory -import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.ui.strings.CommonStrings @@ -42,7 +42,7 @@ fun EditDefaultNotificationSettingView( } else { CommonStrings.screen_notification_settings_group_chats } - PreferenceView( + PreferencePage( modifier = modifier, onBackPressed = onBackPressed, title = stringResource(id = title) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt index dac7ae3204..200785e03d 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt @@ -27,8 +27,8 @@ import androidx.compose.runtime.saveable.rememberSaveable import io.element.android.features.logout.api.LogoutPreferencePresenter import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildType -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher -import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState import io.element.android.libraries.featureflag.api.FeatureFlagService import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.matrix.api.MatrixClient diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt index accede5d6d..f61ea5890d 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt @@ -17,7 +17,7 @@ package io.element.android.features.preferences.impl.root import io.element.android.features.logout.api.LogoutPreferenceState -import io.element.android.libraries.designsystem.utils.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.user.MatrixUser data class PreferencesRootState( diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt index 860c738687..467ca4c6d6 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt @@ -17,7 +17,7 @@ package io.element.android.features.preferences.impl.root import io.element.android.features.logout.api.aLogoutPreferenceState -import io.element.android.libraries.designsystem.utils.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.ui.strings.CommonStrings fun aPreferencesRootState() = PreferencesRootState( diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt index c473e763b6..2999ddea94 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt @@ -31,15 +31,15 @@ import androidx.compose.ui.unit.dp import io.element.android.features.logout.api.LogoutPreferenceView import io.element.android.features.preferences.impl.user.UserPreferences import io.element.android.libraries.designsystem.components.preferences.PreferenceText -import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.CommonDrawables -import io.element.android.libraries.designsystem.utils.SnackbarHost -import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost +import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.components.MatrixUserProvider import io.element.android.libraries.theme.ElementTheme @@ -64,7 +64,7 @@ fun PreferencesRootView( val snackbarHostState = rememberSnackbarHostState(snackbarMessage = state.snackbarMessage) // Include pref from other modules - PreferenceView( + PreferencePage( modifier = modifier, onBackPressed = onBackPressed, title = stringResource(id = CommonStrings.common_settings), @@ -151,7 +151,7 @@ fun PreferencesRootView( } @Composable -fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) { +private fun DeveloperPreferencesView(onOpenDeveloperSettings: () -> Unit) { PreferenceText( title = stringResource(id = CommonStrings.common_developer_options), iconResourceId = CommonDrawables.ic_developer_mode, diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt index 70d15c7a71..cc2c0a7035 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsPresenterTests.kt @@ -32,7 +32,7 @@ import kotlin.time.Duration.Companion.milliseconds class NotificationSettingsPresenterTests { @Test fun `present - ensures initial state is correct`() = runTest { - val presenter = aNotificationPresenter() + val presenter = createNotificationSettingsPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -58,7 +58,7 @@ class NotificationSettingsPresenterTests { @Test fun `present - default group notification mode changed`() = runTest { val notificationSettingsService = FakeNotificationSettingsService() - val presenter = aNotificationPresenter(notificationSettingsService) + val presenter = createNotificationSettingsPresenter(notificationSettingsService) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -77,7 +77,7 @@ class NotificationSettingsPresenterTests { @Test fun `present - notification settings mismatched`() = runTest { val notificationSettingsService = FakeNotificationSettingsService() - val presenter = aNotificationPresenter(notificationSettingsService) + val presenter = createNotificationSettingsPresenter(notificationSettingsService) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -108,7 +108,7 @@ class NotificationSettingsPresenterTests { initialEncryptedOneToOneDefaultMode = RoomNotificationMode.ALL_MESSAGES, initialOneToOneDefaultMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY ) - val presenter = aNotificationPresenter(notificationSettingsService) + val presenter = createNotificationSettingsPresenter(notificationSettingsService) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -125,7 +125,7 @@ class NotificationSettingsPresenterTests { @Test fun `present - set notifications enabled`() = runTest { - val presenter = aNotificationPresenter() + val presenter = createNotificationSettingsPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -145,7 +145,7 @@ class NotificationSettingsPresenterTests { @Test fun `present - set call notifications enabled`() = runTest { - val presenter = aNotificationPresenter() + val presenter = createNotificationSettingsPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -167,7 +167,7 @@ class NotificationSettingsPresenterTests { @Test fun `present - set atRoom notifications enabled`() = runTest { - val presenter = aNotificationPresenter() + val presenter = createNotificationSettingsPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -187,7 +187,7 @@ class NotificationSettingsPresenterTests { } } - private fun aNotificationPresenter( + private fun createNotificationSettingsPresenter( notificationSettingsService: FakeNotificationSettingsService = FakeNotificationSettingsService() ) : NotificationSettingsPresenter { val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService) diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt index 2237f717bd..e9eaf5ef13 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt @@ -23,7 +23,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.logout.impl.DefaultLogoutPreferencePresenter import io.element.android.libraries.architecture.Async import io.element.android.libraries.core.meta.BuildType -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.featureflag.test.FakeFeatureFlagService import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.test.AN_AVATAR_URL diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt index 914afd4421..3d49d637e5 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/crash/CrashDetectionView.kt @@ -49,7 +49,7 @@ fun CrashDetectionView( } @Composable -fun CrashDetectionContent( +private fun CrashDetectionContent( onNoClicked: () -> Unit = { }, onYesClicked: () -> Unit = { }, onDismiss: () -> Unit = { }, diff --git a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt index db0a305c72..88fe5dceb2 100644 --- a/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt +++ b/features/rageshake/api/src/main/kotlin/io/element/android/features/rageshake/api/detection/RageshakeDetectionView.kt @@ -81,7 +81,7 @@ private fun TakeScreenshot( } @Composable -fun RageshakeDialogContent( +private fun RageshakeDialogContent( onNoClicked: () -> Unit = { }, onDisableClicked: () -> Unit = { }, onYesClicked: () -> Unit = { }, diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt index 70033df079..d886819690 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportView.kt @@ -43,7 +43,7 @@ import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog import io.element.android.libraries.designsystem.components.form.textFieldState import io.element.android.libraries.designsystem.components.preferences.PreferenceRow import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch -import io.element.android.libraries.designsystem.components.preferences.PreferenceView +import io.element.android.libraries.designsystem.components.preferences.PreferencePage import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.debugPlaceholderBackground @@ -72,7 +72,7 @@ fun BugReportView( } Box(modifier = modifier) { - PreferenceView( + PreferencePage( title = stringResource(id = CommonStrings.common_report_a_bug), onBackPressed = onBackPressed ) { diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/logs/LogFormatter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/logs/LogFormatter.kt index e0dc1a5fbb..45c2d0a65b 100644 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/logs/LogFormatter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/logs/LogFormatter.kt @@ -28,9 +28,9 @@ import java.util.logging.LogRecord internal class LogFormatter : Formatter() { override fun format(r: LogRecord): String { - if (!mIsTimeZoneSet) { + if (!isTimeZoneSet) { DATE_FORMAT.timeZone = TimeZone.getTimeZone("UTC") - mIsTimeZoneSet = true + isTimeZoneSet = true } val thrown = r.thrown @@ -59,6 +59,6 @@ internal class LogFormatter : Formatter() { // private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US) private val DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss*SSSZZZZ", Locale.US) - private var mIsTimeZoneSet = false + private var isTimeZoneSet = false } } diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt index 46ccc7fc56..a693189d3c 100755 --- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt +++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt @@ -101,10 +101,10 @@ class DefaultBugReporter @Inject constructor( } // the pending bug report call - private var mBugReportCall: Call? = null + private var bugReportCall: Call? = null // boolean to cancel the bug report - private val mIsCancelled = false + private val isCancelled = false /* val adapter = MatrixJsonParser.getMoshi() @@ -151,7 +151,7 @@ class DefaultBugReporter @Inject constructor( listener: BugReporterListener? ) { // enumerate files to delete - val mBugReportFiles: MutableList = ArrayList() + val bugReportFiles: MutableList = ArrayList() try { @@ -172,7 +172,7 @@ class DefaultBugReporter @Inject constructor( val files = getLogFiles() files.mapNotNullTo(gzippedFiles) { f -> when { - mIsCancelled -> null + isCancelled -> null f.extension == "gz" -> f else -> compressFile(f) } @@ -180,7 +180,7 @@ class DefaultBugReporter @Inject constructor( files.deleteAllExceptMostRecent() } - if (!mIsCancelled && (withCrashLogs || withDevicesLogs)) { + if (!isCancelled && (withCrashLogs || withDevicesLogs)) { val gzippedLogcat = saveLogCat(false) if (null != gzippedLogcat) { @@ -215,7 +215,7 @@ class DefaultBugReporter @Inject constructor( val userId = sessionData?.userId ?: "undefined" var olmVersion = "undefined" - if (!mIsCancelled) { + if (!isCancelled) { val text = when (reportType) { ReportType.BUG_REPORT -> bugDescription ReportType.SUGGESTION -> "[Suggestion] $bugDescription" @@ -268,7 +268,7 @@ class DefaultBugReporter @Inject constructor( } } - mBugReportFiles.addAll(gzippedFiles) + bugReportFiles.addAll(gzippedFiles) if (gzippedFiles.isNotEmpty() && !uploadedSomeLogs) { serverError = "Couldn't upload any logs, please retry." @@ -336,8 +336,8 @@ class DefaultBugReporter @Inject constructor( 0 } - if (mIsCancelled && null != mBugReportCall) { - mBugReportCall!!.cancel() + if (isCancelled && null != bugReportCall) { + bugReportCall!!.cancel() } Timber.v("## onWrite() : $percentage%") @@ -360,8 +360,8 @@ class DefaultBugReporter @Inject constructor( // trigger the request try { - mBugReportCall = okHttpClient.get().newCall(request) - response = mBugReportCall!!.execute() + bugReportCall = okHttpClient.get().newCall(request) + response = bugReportCall!!.execute() responseCode = response.code } catch (e: CancellationException) { throw e @@ -423,11 +423,11 @@ class DefaultBugReporter @Inject constructor( } withContext(coroutineDispatchers.main) { - mBugReportCall = null + bugReportCall = null if (null != listener) { try { - if (mIsCancelled) { + if (isCancelled) { listener.onUploadCancelled() } else if (null == serverError) { listener.onUploadSucceed(reportURL) @@ -443,7 +443,7 @@ class DefaultBugReporter @Inject constructor( } } finally { // delete the generated files when the bug report process has finished - for (file in mBugReportFiles) { + for (file in bugReportFiles) { file.safeDelete() } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt index 675ef7de60..71eff4e9e6 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt @@ -68,7 +68,7 @@ class RoomDetailsFlowNode @AssistedInject constructor( data object InviteMembers : NavTarget @Parcelize - object RoomNotificationSettings : NavTarget + data object RoomNotificationSettings : NavTarget @Parcelize data class RoomMemberDetails(val roomMemberId: UserId) : NavTarget diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt index c580e6d677..bbbcc64da6 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsStateProvider.kt @@ -18,6 +18,7 @@ package io.element.android.features.roomdetails.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.leaveroom.api.LeaveRoomState +import io.element.android.features.leaveroom.api.aLeaveRoomState import io.element.android.features.roomdetails.impl.members.details.aRoomMemberDetailsState import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomMember @@ -80,7 +81,7 @@ fun aRoomDetailsState() = RoomDetailsState( canShowNotificationSettings = true, roomType = RoomDetailsType.Room, roomMemberDetailsState = null, - leaveRoomState = LeaveRoomState(), + leaveRoomState = aLeaveRoomState(), roomNotificationSettings = RoomNotificationSettings(mode = RoomNotificationMode.MUTE, isDefault = false), eventSink = {} ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index d6c339bb7c..c6b90e5cc6 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -183,7 +183,7 @@ fun RoomDetailsView( @OptIn(ExperimentalMaterial3Api::class) @Composable -internal fun RoomDetailsTopBar( +private fun RoomDetailsTopBar( goBack: () -> Unit, onActionClicked: (RoomDetailsAction) -> Unit, showEdit: Boolean, @@ -220,7 +220,7 @@ internal fun RoomDetailsTopBar( } @Composable -internal fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit, modifier: Modifier = Modifier) { +private fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit, modifier: Modifier = Modifier) { Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { val roomNotificationSettings = state.roomNotificationSettings if (state.canShowNotificationSettings && roomNotificationSettings != null) { @@ -252,7 +252,7 @@ internal fun MainActionsSection(state: RoomDetailsState, onShareRoom: () -> Unit } @Composable -internal fun RoomHeaderSection( +private fun RoomHeaderSection( avatarUrl: String?, roomId: String, roomName: String, @@ -289,7 +289,7 @@ internal fun RoomHeaderSection( } @Composable -internal fun TopicSection( +private fun TopicSection( roomTopic: RoomTopicState, onActionClicked: (RoomDetailsAction) -> Unit, modifier: Modifier = Modifier @@ -315,7 +315,7 @@ internal fun TopicSection( } @Composable -internal fun NotificationSection( +private fun NotificationSection( isDefaultMode: Boolean, openRoomNotificationSettings: () -> Unit, modifier: Modifier = Modifier @@ -336,7 +336,7 @@ internal fun NotificationSection( } @Composable -internal fun MembersSection( +private fun MembersSection( memberCount: Long, openRoomMemberList: () -> Unit, modifier: Modifier = Modifier, @@ -352,7 +352,7 @@ internal fun MembersSection( } @Composable -internal fun InviteSection( +private fun InviteSection( invitePeople: () -> Unit, modifier: Modifier = Modifier, ) { @@ -366,7 +366,7 @@ internal fun InviteSection( } @Composable -internal fun SecuritySection(modifier: Modifier = Modifier) { +private fun SecuritySection(modifier: Modifier = Modifier) { PreferenceCategory(title = stringResource(R.string.screen_room_details_security_title), modifier = modifier) { PreferenceText( title = stringResource(R.string.screen_room_details_encryption_enabled_title), @@ -377,7 +377,7 @@ internal fun SecuritySection(modifier: Modifier = Modifier) { } @Composable -internal fun OtherActionsSection(onLeaveRoom: () -> Unit, modifier: Modifier = Modifier) { +private fun OtherActionsSection(onLeaveRoom: () -> Unit, modifier: Modifier = Modifier) { PreferenceCategory(showDivider = false, modifier = modifier) { PreferenceText( title = stringResource(R.string.screen_room_details_leave_room_title), diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserDialogs.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserDialogs.kt new file mode 100644 index 0000000000..ddbff5b6a9 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserDialogs.kt @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 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.roomdetails.impl.blockuser + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import io.element.android.features.roomdetails.impl.R +import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsEvents +import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState +import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog + +@Composable +fun BlockUserDialogs(state: RoomMemberDetailsState) { + when (state.displayConfirmationDialog) { + null -> Unit + RoomMemberDetailsState.ConfirmationDialog.Block -> { + BlockConfirmationDialog( + onBlockAction = { + state.eventSink( + RoomMemberDetailsEvents.BlockUser( + needsConfirmation = false + ) + ) + }, + onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) } + ) + } + RoomMemberDetailsState.ConfirmationDialog.Unblock -> { + UnblockConfirmationDialog( + onUnblockAction = { + state.eventSink( + RoomMemberDetailsEvents.UnblockUser( + needsConfirmation = false + ) + ) + }, + onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) } + ) + } + } +} + +@Composable +private fun BlockConfirmationDialog(onBlockAction: () -> Unit, onDismiss: () -> Unit) { + ConfirmationDialog( + title = stringResource(R.string.screen_dm_details_block_user), + content = stringResource(R.string.screen_dm_details_block_alert_description), + submitText = stringResource(R.string.screen_dm_details_block_alert_action), + onSubmitClicked = onBlockAction, + onDismiss = onDismiss + ) +} + +@Composable +private fun UnblockConfirmationDialog(onUnblockAction: () -> Unit, onDismiss: () -> Unit) { + ConfirmationDialog( + title = stringResource(R.string.screen_dm_details_unblock_user), + content = stringResource(R.string.screen_dm_details_unblock_alert_description), + submitText = stringResource(R.string.screen_dm_details_unblock_alert_action), + onSubmitClicked = onUnblockAction, + onDismiss = onDismiss + ) +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserSection.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserSection.kt index cccf682c9c..c21e8520b3 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserSection.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/blockuser/BlockUserSection.kt @@ -27,7 +27,6 @@ import io.element.android.features.roomdetails.impl.members.details.RoomMemberDe import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsState import io.element.android.libraries.architecture.Async import io.element.android.libraries.core.bool.orFalse -import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.RetryDialog import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory import io.element.android.libraries.designsystem.components.preferences.PreferenceText @@ -85,44 +84,3 @@ private fun PreferenceBlockUser( ) } } - -@Composable -internal fun BlockUserDialogs(state: RoomMemberDetailsState) { - when (state.displayConfirmationDialog) { - null -> Unit - RoomMemberDetailsState.ConfirmationDialog.Block -> { - BlockConfirmationDialog( - onBlockAction = { state.eventSink(RoomMemberDetailsEvents.BlockUser(needsConfirmation = false)) }, - onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) } - ) - } - RoomMemberDetailsState.ConfirmationDialog.Unblock -> { - UnblockConfirmationDialog( - onUnblockAction = { state.eventSink(RoomMemberDetailsEvents.UnblockUser(needsConfirmation = false)) }, - onDismiss = { state.eventSink(RoomMemberDetailsEvents.ClearConfirmationDialog) } - ) - } - } -} - -@Composable -internal fun BlockConfirmationDialog(onBlockAction: () -> Unit, onDismiss: () -> Unit) { - ConfirmationDialog( - title = stringResource(R.string.screen_dm_details_block_user), - content = stringResource(R.string.screen_dm_details_block_alert_description), - submitText = stringResource(R.string.screen_dm_details_block_alert_action), - onSubmitClicked = onBlockAction, - onDismiss = onDismiss - ) -} - -@Composable -internal fun UnblockConfirmationDialog(onUnblockAction: () -> Unit, onDismiss: () -> Unit) { - ConfirmationDialog( - title = stringResource(R.string.screen_dm_details_unblock_user), - content = stringResource(R.string.screen_dm_details_unblock_alert_description), - submitText = stringResource(R.string.screen_dm_details_unblock_alert_action), - onSubmitClicked = onUnblockAction, - onDismiss = onDismiss - ) -} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersState.kt index 9a2ceb7c4b..16436debf0 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersState.kt @@ -19,15 +19,14 @@ package io.element.android.features.roomdetails.impl.invite import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf data class RoomInviteMembersState( - val canInvite: Boolean = false, - val searchQuery: String = "", - val searchResults: SearchBarResultState> = SearchBarResultState.NotSearching(), - val selectedUsers: ImmutableList = persistentListOf(), - val isSearchActive: Boolean = false, - val eventSink: (RoomInviteMembersEvents) -> Unit = {}, + val canInvite: Boolean, + val searchQuery: String, + val searchResults: SearchBarResultState>, + val selectedUsers: ImmutableList, + val isSearchActive: Boolean, + val eventSink: (RoomInviteMembersEvents) -> Unit, ) data class InvitableUser( diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersStateProvider.kt index 00e9496c2a..f44d518fb5 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersStateProvider.kt @@ -18,20 +18,22 @@ package io.element.android.features.roomdetails.impl.invite import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.libraries.designsystem.theme.components.SearchBarResultState +import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUserList +import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList internal class RoomInviteMembersStateProvider : PreviewParameterProvider { override val values: Sequence get() = sequenceOf( - RoomInviteMembersState(), - RoomInviteMembersState(canInvite = true, selectedUsers = aMatrixUserList().toImmutableList()), - RoomInviteMembersState(isSearchActive = true, searchQuery = "some query"), - RoomInviteMembersState(isSearchActive = true, searchQuery = "some query", selectedUsers = aMatrixUserList().toImmutableList()), - RoomInviteMembersState(isSearchActive = true, searchQuery = "some query", searchResults = SearchBarResultState.NoResults()), - RoomInviteMembersState( + aRoomInviteMembersState(), + aRoomInviteMembersState(canInvite = true, selectedUsers = aMatrixUserList().toImmutableList()), + aRoomInviteMembersState(isSearchActive = true, searchQuery = "some query"), + aRoomInviteMembersState(isSearchActive = true, searchQuery = "some query", selectedUsers = aMatrixUserList().toImmutableList()), + aRoomInviteMembersState(isSearchActive = true, searchQuery = "some query", searchResults = SearchBarResultState.NoResults()), + aRoomInviteMembersState( isSearchActive = true, canInvite = true, searchQuery = "some query", @@ -48,7 +50,7 @@ internal class RoomInviteMembersStateProvider : PreviewParameterProvider> = SearchBarResultState.NotSearching(), + selectedUsers: ImmutableList = persistentListOf(), + isSearchActive: Boolean = false, +): RoomInviteMembersState { + return RoomInviteMembersState( + canInvite = canInvite, + searchQuery = searchQuery, + searchResults = searchResults, + selectedUsers = selectedUsers, + isSearchActive = isSearchActive, + eventSink = {}, + ) +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt index d100fa0fd3..ef37ee26bb 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/invite/RoomInviteMembersView.kt @@ -111,7 +111,7 @@ fun RoomInviteMembersView( @OptIn(ExperimentalMaterial3Api::class) @Composable -fun RoomInviteMembersTopBar( +private fun RoomInviteMembersTopBar( canSend: Boolean, modifier: Modifier = Modifier, onBackPressed: () -> Unit = {}, diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsState.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsState.kt index 0d3423e179..957db2233e 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsState.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsState.kt @@ -23,7 +23,7 @@ data class RoomMemberDetailsState( val userName: String?, val avatarUrl: String?, val isBlocked: Async, - val displayConfirmationDialog: ConfirmationDialog? = null, + val displayConfirmationDialog: ConfirmationDialog?, val isCurrentUser: Boolean, val eventSink: (RoomMemberDetailsEvents) -> Unit ) { diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsStateProvider.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsStateProvider.kt index 6883b20898..b14b0e3634 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsStateProvider.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsStateProvider.kt @@ -37,6 +37,7 @@ fun aRoomMemberDetailsState() = RoomMemberDetailsState( userName = "Daniel", avatarUrl = null, isBlocked = Async.Success(false), + displayConfirmationDialog = null, isCurrentUser = false, eventSink = {}, ) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsView.kt index ec0a1781e0..bd65e706b4 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberDetailsView.kt @@ -16,49 +16,27 @@ package io.element.android.features.roomdetails.impl.members.details -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.consumeWindowInsets -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.ChatBubbleOutline import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.features.roomdetails.impl.blockuser.BlockUserDialogs import io.element.android.features.roomdetails.impl.blockuser.BlockUserSection -import io.element.android.libraries.designsystem.components.avatar.Avatar -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.button.BackButton -import io.element.android.libraries.designsystem.components.button.MainActionButton -import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory -import io.element.android.libraries.designsystem.components.preferences.PreferenceText import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.PreviewWithLargeHeight import io.element.android.libraries.designsystem.theme.components.Scaffold -import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.TopAppBar -import io.element.android.libraries.designsystem.utils.CommonDrawables -import io.element.android.libraries.theme.ElementTheme -import io.element.android.libraries.ui.strings.CommonStrings @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @Composable @@ -103,51 +81,9 @@ fun RoomMemberDetailsView( } } +/* @Composable -internal fun RoomMemberHeaderSection( - avatarUrl: String?, - userId: String, - userName: String?, - modifier: Modifier = Modifier -) { - Column(modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Box(modifier = Modifier.size(70.dp)) { - Avatar( - avatarData = AvatarData(userId, userName, avatarUrl, AvatarSize.UserHeader), - modifier = Modifier.fillMaxSize() - ) - } - Spacer(modifier = Modifier.height(24.dp)) - if (userName != null) { - Text(text = userName, style = ElementTheme.typography.fontHeadingLgBold) - Spacer(modifier = Modifier.height(6.dp)) - } - Text( - text = userId, - style = ElementTheme.typography.fontBodyLgRegular, - color = MaterialTheme.colorScheme.secondary, - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp), - textAlign = TextAlign.Center, - ) - Spacer(Modifier.height(40.dp)) - } -} - -@Composable -internal fun RoomMemberMainActionsSection(onShareUser: () -> Unit, modifier: Modifier = Modifier) { - Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { - MainActionButton( - title = stringResource(CommonStrings.action_share), - iconResourceId = CommonDrawables.ic_compound_share_android, - onClick = onShareUser - ) - } -} - -@Composable -internal fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier = Modifier) { +private fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier = Modifier) { PreferenceCategory(modifier = modifier) { PreferenceText( title = stringResource(CommonStrings.action_send_message), @@ -156,6 +92,7 @@ internal fun SendMessageSection(onSendMessage: () -> Unit, modifier: Modifier = ) } } + */ @PreviewWithLargeHeight @Composable diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberHeaderSection.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberHeaderSection.kt new file mode 100644 index 0000000000..26412577b8 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberHeaderSection.kt @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 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.roomdetails.impl.members.details + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.theme.ElementTheme + +@Composable +fun RoomMemberHeaderSection( + avatarUrl: String?, + userId: String, + userName: String?, + modifier: Modifier = Modifier +) { + Column(modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { + Box(modifier = Modifier.size(70.dp)) { + Avatar( + avatarData = AvatarData(userId, userName, avatarUrl, AvatarSize.UserHeader), + modifier = Modifier.fillMaxSize() + ) + } + Spacer(modifier = Modifier.height(24.dp)) + if (userName != null) { + Text(text = userName, style = ElementTheme.typography.fontHeadingLgBold) + Spacer(modifier = Modifier.height(6.dp)) + } + Text( + text = userId, + style = ElementTheme.typography.fontBodyLgRegular, + color = MaterialTheme.colorScheme.secondary, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + textAlign = TextAlign.Center, + ) + Spacer(Modifier.height(40.dp)) + } +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberMainActionsSection.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberMainActionsSection.kt new file mode 100644 index 0000000000..edd352f228 --- /dev/null +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/members/details/RoomMemberMainActionsSection.kt @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 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.roomdetails.impl.members.details + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import io.element.android.libraries.designsystem.components.button.MainActionButton +import io.element.android.libraries.designsystem.utils.CommonDrawables +import io.element.android.libraries.ui.strings.CommonStrings + +@Composable +fun RoomMemberMainActionsSection(onShareUser: () -> Unit, modifier: Modifier = Modifier) { + Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + MainActionButton( + title = stringResource(CommonStrings.action_share), + iconResourceId = CommonDrawables.ic_compound_share_android, + onClick = onShareUser + ) + } +} diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt index 7c8206f6a2..8234582c9c 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/notificationsettings/RoomNotificationSettingsView.kt @@ -108,7 +108,7 @@ fun RoomNotificationSettingsView( @OptIn(ExperimentalMaterial3Api::class) @Composable -fun RoomNotificationSettingsTopBar( +private fun RoomNotificationSettingsTopBar( modifier: Modifier = Modifier, onBackPressed: () -> Unit = {}, ) { @@ -125,7 +125,7 @@ fun RoomNotificationSettingsTopBar( } @Composable -fun RoomNotificationSettingsOptions( +private fun RoomNotificationSettingsOptions( selected: RoomNotificationMode?, enabled: Boolean, modifier: Modifier = Modifier, diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt index 940468862a..5ab79d2cee 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/RoomDetailsPresenterTests.kt @@ -59,7 +59,8 @@ class RoomDetailsPresenterTests { @get:Rule val warmUpRule = WarmUpRule() - private fun aRoomDetailsPresenter( + + private fun createRoomDetailsPresenter( room: MatrixRoom, leaveRoomPresenter: LeaveRoomPresenter = FakeLeaveRoomPresenter(), dispatchers: CoroutineDispatchers, @@ -88,7 +89,7 @@ class RoomDetailsPresenterTests { @Test fun `present - initial state is created from room info`() = runTest { val room = aMatrixRoom() - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -107,7 +108,7 @@ class RoomDetailsPresenterTests { @Test fun `present - initial state with no room name`() = runTest { val room = aMatrixRoom(name = null) - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -129,7 +130,7 @@ class RoomDetailsPresenterTests { val roomMembers = listOf(myRoomMember, otherRoomMember) givenRoomMembersState(MatrixRoomMembersState.Ready(roomMembers)) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -145,7 +146,7 @@ class RoomDetailsPresenterTests { val room = aMatrixRoom().apply { givenCanInviteResult(Result.success(true)) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -163,7 +164,7 @@ class RoomDetailsPresenterTests { val room = aMatrixRoom().apply { givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -178,7 +179,7 @@ class RoomDetailsPresenterTests { val room = aMatrixRoom().apply { givenCanInviteResult(Result.failure(Throwable("Whoops"))) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -196,7 +197,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.failure(Throwable("Whelp"))) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -225,7 +226,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true)) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -254,7 +255,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true)) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -275,7 +276,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true)) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -296,7 +297,7 @@ class RoomDetailsPresenterTests { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(false)) givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -314,7 +315,7 @@ class RoomDetailsPresenterTests { givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -332,7 +333,7 @@ class RoomDetailsPresenterTests { givenCanInviteResult(Result.success(false)) } - val presenter = aRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, dispatchers = testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -350,7 +351,7 @@ class RoomDetailsPresenterTests { fun `present - leave room event is passed on to leave room presenter`() = runTest { val leaveRoomPresenter = FakeLeaveRoomPresenter() val room = aMatrixRoom() - val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers()) + val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers()) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -367,7 +368,7 @@ class RoomDetailsPresenterTests { val leaveRoomPresenter = FakeLeaveRoomPresenter() val notificationSettingsService = FakeNotificationSettingsService() val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) - val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) + val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -386,7 +387,7 @@ class RoomDetailsPresenterTests { val leaveRoomPresenter = FakeLeaveRoomPresenter() val notificationSettingsService = FakeNotificationSettingsService(initialRoomMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY) val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) - val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) + val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -407,7 +408,7 @@ class RoomDetailsPresenterTests { initialEncryptedGroupDefaultMode = RoomNotificationMode.ALL_MESSAGES ) val room = aMatrixRoom(notificationSettingsService = notificationSettingsService) - val presenter = aRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) + val presenter = createRoomDetailsPresenter(room, leaveRoomPresenter, testCoroutineDispatchers(), notificationSettingsService) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt index 03a47026dd..eb89c40a24 100644 --- a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/edit/RoomDetailsEditPresenterTest.kt @@ -77,7 +77,7 @@ class RoomDetailsEditPresenterTest { unmockkAll() } - private fun aRoomDetailsEditPresenter( + private fun createRoomDetailsEditPresenter( room: MatrixRoom, permissionsPresenter: PermissionsPresenter = FakePermissionsPresenter(), ): RoomDetailsEditPresenter { @@ -92,7 +92,7 @@ class RoomDetailsEditPresenterTest { @Test fun `present - initial state is created from room info`() = runTest { val room = aMatrixRoom(avatarUrl = AN_AVATAR_URL) - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -119,7 +119,7 @@ class RoomDetailsEditPresenterTest { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(false)) givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.failure(Throwable("Oops"))) } - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -145,7 +145,7 @@ class RoomDetailsEditPresenterTest { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.success(true)) givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.failure(Throwable("Oops"))) } - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -171,7 +171,7 @@ class RoomDetailsEditPresenterTest { givenCanSendStateResult(StateEventType.ROOM_AVATAR, Result.failure(Throwable("Oops"))) givenCanSendStateResult(StateEventType.ROOM_TOPIC, Result.success(true)) } - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -193,7 +193,7 @@ class RoomDetailsEditPresenterTest { @Test fun `present - updates state in response to changes`() = runTest { val room = aMatrixRoom(topic = "My topic", name = "Name", avatarUrl = AN_AVATAR_URL) - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -239,7 +239,7 @@ class RoomDetailsEditPresenterTest { fakePickerProvider.givenResult(anotherAvatarUri) - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -260,7 +260,7 @@ class RoomDetailsEditPresenterTest { fakePickerProvider.givenResult(anotherAvatarUri) val fakePermissionsPresenter = FakePermissionsPresenter() - val presenter = aRoomDetailsEditPresenter( + val presenter = createRoomDetailsEditPresenter( room = room, permissionsPresenter = fakePermissionsPresenter, ) @@ -293,7 +293,7 @@ class RoomDetailsEditPresenterTest { fakePickerProvider.givenResult(roomAvatarUri) - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -345,7 +345,7 @@ class RoomDetailsEditPresenterTest { fakePickerProvider.givenResult(roomAvatarUri) - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -395,7 +395,7 @@ class RoomDetailsEditPresenterTest { fun `present - save changes room details if different`() = runTest { val room = aMatrixRoom(topic = "My topic", name = "Name", avatarUrl = AN_AVATAR_URL) - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -420,7 +420,7 @@ class RoomDetailsEditPresenterTest { fun `present - save doesn't change room details if they're the same trimmed`() = runTest { val room = aMatrixRoom(topic = "My topic", name = "Name", avatarUrl = AN_AVATAR_URL) - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -444,7 +444,7 @@ class RoomDetailsEditPresenterTest { fun `present - save doesn't change topic if it was unset and is now blank`() = runTest { val room = aMatrixRoom(topic = null, name = "Name", avatarUrl = AN_AVATAR_URL) - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -467,7 +467,7 @@ class RoomDetailsEditPresenterTest { fun `present - save doesn't change name if it's now empty`() = runTest { val room = aMatrixRoom(topic = "My topic", name = "Name", avatarUrl = AN_AVATAR_URL) - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -492,7 +492,7 @@ class RoomDetailsEditPresenterTest { givenPickerReturnsFile() - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -517,7 +517,7 @@ class RoomDetailsEditPresenterTest { fakePickerProvider.givenResult(anotherAvatarUri) fakeMediaPreProcessor.givenResult(Result.failure(Throwable("Oh no"))) - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -583,7 +583,7 @@ class RoomDetailsEditPresenterTest { givenSetTopicResult(Result.failure(Throwable("!"))) } - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() @@ -602,7 +602,7 @@ class RoomDetailsEditPresenterTest { } private suspend fun saveAndAssertFailure(room: MatrixRoom, event: RoomDetailsEditEvents) { - val presenter = aRoomDetailsEditPresenter(room) + val presenter = createRoomDetailsEditPresenter(room) moleculeFlow(RecompositionMode.Immediate) { presenter.present() diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt index e069634d49..5238144755 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt @@ -33,8 +33,8 @@ import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource import io.element.android.features.roomlist.impl.datasource.RoomListDataSource import io.element.android.libraries.architecture.Presenter -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher -import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.collectSnackbarMessageAsState import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.getCurrentUser diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt index c555afeca7..f0dfe8e3a9 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt @@ -19,7 +19,7 @@ package io.element.android.features.roomlist.impl import androidx.compose.runtime.Immutable import io.element.android.features.leaveroom.api.LeaveRoomState import io.element.android.features.roomlist.impl.model.RoomListRoomSummary -import io.element.android.libraries.designsystem.utils.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.user.MatrixUser import kotlinx.collections.immutable.ImmutableList diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt index 421e243504..2a27777e4a 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt @@ -18,11 +18,12 @@ package io.element.android.features.roomlist.impl import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.leaveroom.api.LeaveRoomState +import io.element.android.features.leaveroom.api.aLeaveRoomState import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryPlaceholders import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize -import io.element.android.libraries.designsystem.utils.SnackbarMessage +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.user.MatrixUser @@ -58,7 +59,7 @@ internal fun aRoomListState() = RoomListState( invitesState = InvitesState.NoInvites, displaySearchResults = false, contextMenu = RoomListState.ContextMenu.Hidden, - leaveRoomState = LeaveRoomState(), + leaveRoomState = aLeaveRoomState(), eventSink = {} ) diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt index a669c9d707..b01c5fba4d 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListView.kt @@ -59,8 +59,8 @@ import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.LogCompositions -import io.element.android.libraries.designsystem.utils.SnackbarHost -import io.element.android.libraries.designsystem.utils.rememberSnackbarHostState +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost +import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState import io.element.android.libraries.matrix.api.core.RoomId @Composable @@ -124,7 +124,7 @@ fun RoomListView( @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @Composable -fun RoomListContent( +private fun RoomListContent( state: RoomListState, onVerifyClicked: () -> Unit, onRoomClicked: (RoomId) -> Unit, diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt index 384777774e..2016cf5a6b 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomSummaryRow.kt @@ -85,7 +85,7 @@ internal fun RoomSummaryRow( @OptIn(ExperimentalFoundationApi::class) @Composable -internal fun RoomSummaryRealRow( +private fun RoomSummaryRealRow( room: RoomListRoomSummary, onClick: (RoomListRoomSummary) -> Unit, onLongClick: (RoomListRoomSummary) -> Unit, diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearch.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchResultView.kt similarity index 99% rename from features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearch.kt rename to features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchResultView.kt index 07043b5e5d..799e94bdbd 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearch.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/search/RoomListSearchResultView.kt @@ -100,7 +100,7 @@ internal fun RoomListSearchResultView( @OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @Composable -internal fun RoomListSearchResultContent( +private fun RoomListSearchResultContent( state: RoomListState, onRoomClicked: (RoomId) -> Unit, onRoomLongClicked: (RoomListRoomSummary) -> Unit, diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt index 3b2adf9d7d..fd5c0160fc 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt @@ -34,7 +34,7 @@ import io.element.android.libraries.dateformatter.api.LastMessageTimestampFormat import io.element.android.libraries.dateformatter.test.FakeLastMessageTimestampFormatter import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter import io.element.android.libraries.matrix.api.MatrixClient diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt index 703559dd6b..9ee44a790a 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionView.kt @@ -89,7 +89,7 @@ fun VerifySelfSessionView( } @Composable -internal fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier = Modifier) { +private fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier = Modifier) { val iconResourceId = when (verificationFlowStep) { FlowStep.Initial -> R.drawable.ic_verification_devices FlowStep.Canceled -> R.drawable.ic_verification_warning @@ -118,7 +118,7 @@ internal fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier = } @Composable -internal fun Content(flowState: FlowStep, modifier: Modifier = Modifier) { +private fun Content(flowState: FlowStep, modifier: Modifier = Modifier) { Column(modifier.fillMaxHeight(), verticalArrangement = Arrangement.Center) { when (flowState) { FlowStep.Initial, FlowStep.Ready, FlowStep.Canceled, FlowStep.Completed -> Unit @@ -129,14 +129,14 @@ internal fun Content(flowState: FlowStep, modifier: Modifier = Modifier) { } @Composable -internal fun ContentWaiting(modifier: Modifier = Modifier) { +private fun ContentWaiting(modifier: Modifier = Modifier) { Row(modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { CircularProgressIndicator() } } @Composable -internal fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier: Modifier = Modifier) { +private fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier: Modifier = Modifier) { // We want each row to have up to 4 emojis val rows = verificationFlowStep.emojiList.chunked(4) Column(modifier = modifier.fillMaxWidth()) { @@ -155,7 +155,7 @@ internal fun ContentVerifying(verificationFlowStep: FlowStep.Verifying, modifier } @Composable -internal fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifier) { +private fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifier) { Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier) { Text( text = emoji.code, @@ -173,7 +173,7 @@ internal fun EmojiItemView(emoji: VerificationEmoji, modifier: Modifier = Modifi } @Composable -internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit) { +private fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit) { val verificationViewState = screenState.verificationFlowStep val eventSink = screenState.eventSink diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt index eee6c51a07..403324816f 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/VerifySelfSessionPresenterTests.kt @@ -40,7 +40,7 @@ class VerifySelfSessionPresenterTests { @Test fun `present - Initial state is received`() = runTest { - val presenter = createPresenter() + val presenter = createVerifySelfSessionPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -51,7 +51,7 @@ class VerifySelfSessionPresenterTests { @Test fun `present - Handles requestVerification`() = runTest { val service = FakeSessionVerificationService() - val presenter = createPresenter(service) + val presenter = createVerifySelfSessionPresenter(service) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -62,7 +62,7 @@ class VerifySelfSessionPresenterTests { @Test fun `present - Handles startSasVerification`() = runTest { val service = FakeSessionVerificationService() - val presenter = createPresenter(service) + val presenter = createVerifySelfSessionPresenter(service) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -81,7 +81,7 @@ class VerifySelfSessionPresenterTests { @Test fun `present - Cancelation on initial state does nothing`() = runTest { - val presenter = createPresenter() + val presenter = createVerifySelfSessionPresenter() moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -96,7 +96,7 @@ class VerifySelfSessionPresenterTests { @Test fun `present - A fail in the flow cancels it`() = runTest { val service = FakeSessionVerificationService() - val presenter = createPresenter(service) + val presenter = createVerifySelfSessionPresenter(service) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -113,7 +113,7 @@ class VerifySelfSessionPresenterTests { @Test fun `present - Canceling the flow once it's verifying cancels it`() = runTest { val service = FakeSessionVerificationService() - val presenter = createPresenter(service) + val presenter = createVerifySelfSessionPresenter(service) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -127,7 +127,7 @@ class VerifySelfSessionPresenterTests { @Test fun `present - When verifying, if we receive another challenge we ignore it`() = runTest { val service = FakeSessionVerificationService() - val presenter = createPresenter(service) + val presenter = createVerifySelfSessionPresenter(service) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -140,7 +140,7 @@ class VerifySelfSessionPresenterTests { @Test fun `present - Restart after cancelation returns to requesting verification`() = runTest { val service = FakeSessionVerificationService() - val presenter = createPresenter(service) + val presenter = createVerifySelfSessionPresenter(service) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -162,7 +162,7 @@ class VerifySelfSessionPresenterTests { val service = FakeSessionVerificationService().apply { givenEmojiList(emojis) } - val presenter = createPresenter(service) + val presenter = createVerifySelfSessionPresenter(service) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -176,7 +176,7 @@ class VerifySelfSessionPresenterTests { @Test fun `present - When verification is declined, the flow is canceled`() = runTest { val service = FakeSessionVerificationService() - val presenter = createPresenter(service) + val presenter = createVerifySelfSessionPresenter(service) moleculeFlow(RecompositionMode.Immediate) { presenter.present() }.test { @@ -210,7 +210,9 @@ class VerifySelfSessionPresenterTests { return state } - private fun createPresenter(service: FakeSessionVerificationService = FakeSessionVerificationService()): VerifySelfSessionPresenter { + private fun createVerifySelfSessionPresenter( + service: FakeSessionVerificationService = FakeSessionVerificationService() + ): VerifySelfSessionPresenter { return VerifySelfSessionPresenter(service, VerifySelfSessionStateMachine(service)) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f956f84899..bf33c7d492 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -122,6 +122,7 @@ test_uiautomator = "androidx.test.uiautomator:uiautomator:2.2.0" test_junitext = "androidx.test.ext:junit:1.1.5" test_mockk = "io.mockk:mockk:1.13.8" test_barista = "com.adevinta.android:barista:4.3.0" +test_konsist = "com.lemonappdev:konsist:0.13.0" test_hamcrest = "org.hamcrest:hamcrest:2.2" test_orchestrator = "androidx.test:orchestrator:1.4.2" test_turbine = "app.cash.turbine:turbine:1.0.0" diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/BlurHashAsyncImage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/BlurHashAsyncImage.kt index 0ddd0b7346..dcfce743c1 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/BlurHashAsyncImage.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/BlurHashAsyncImage.kt @@ -71,7 +71,7 @@ fun BlurHashAsyncImage( } @Composable -fun BlurHashImage( +private fun BlurHashImage( blurHash: String?, modifier: Modifier = Modifier, contentDescription: String? = null, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ListDialog.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ListDialog.kt index 8061e6a1a5..e82ebfe532 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ListDialog.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/ListDialog.kt @@ -72,7 +72,7 @@ fun ListDialog( } @Composable -internal fun ListDialogContent( +private fun ListDialogContent( listItems: LazyListScope.() -> Unit, onDismissRequest: () -> Unit, onSubmitClicked: () -> Unit, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/MultipleSelectionDialog.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/MultipleSelectionDialog.kt index a697a3c753..5ed79f2c35 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/MultipleSelectionDialog.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/MultipleSelectionDialog.kt @@ -78,7 +78,7 @@ fun MultipleSelectionDialog( } @Composable -internal fun MultipleSelectionDialogContent( +private fun MultipleSelectionDialogContent( options: ImmutableList, confirmButtonTitle: String, onConfirmClicked: (List) -> Unit, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/SingleSelectionDialog.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/SingleSelectionDialog.kt index ee45e05d8b..db9e7faef2 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/SingleSelectionDialog.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/dialogs/SingleSelectionDialog.kt @@ -74,7 +74,7 @@ fun SingleSelectionDialog( } @Composable -internal fun SingleSelectionDialogContent( +private fun SingleSelectionDialogContent( options: ImmutableList, onOptionSelected: (Int) -> Unit, onDismissRequest: () -> Unit, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt index 885059cb70..e3036194a4 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceCategory.kt @@ -52,7 +52,7 @@ fun PreferenceCategory( } @Composable -fun PreferenceCategoryTitle(title: String, modifier: Modifier = Modifier) { +private fun PreferenceCategoryTitle(title: String, modifier: Modifier = Modifier) { Text( modifier = modifier.padding( top = 20.dp, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceScreen.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferencePage.kt similarity index 98% rename from libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceScreen.kt rename to libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferencePage.kt index c43fbd3d45..653df4a74d 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferenceScreen.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/preferences/PreferencePage.kt @@ -44,7 +44,7 @@ import io.element.android.libraries.theme.ElementTheme @OptIn(ExperimentalLayoutApi::class) @Composable -fun PreferenceView( +fun PreferencePage( title: String, modifier: Modifier = Modifier, onBackPressed: () -> Unit = {}, @@ -79,7 +79,7 @@ fun PreferenceView( @OptIn(ExperimentalMaterial3Api::class) @Composable -fun PreferenceTopAppBar( +private fun PreferenceTopAppBar( title: String, modifier: Modifier = Modifier, onBackPressed: () -> Unit = {}, @@ -104,7 +104,7 @@ fun PreferenceTopAppBar( @PreviewsDayNight @Composable internal fun PreferenceViewPreview() = ElementPreview { - PreferenceView( + PreferencePage( title = "Preference screen" ) { PreferenceCategory( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt index 3c2d61a76e..70777e0184 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreview.kt @@ -16,90 +16,11 @@ package io.element.android.libraries.designsystem.preview -import androidx.compose.foundation.background import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.dp import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.theme.ElementTheme -@Composable -fun ElementPreviewLight( - showBackground: Boolean = true, - content: @Composable () -> Unit -) { - ElementPreview( - darkTheme = false, - showBackground = showBackground, - content = content - ) -} - -@Composable -fun ElementPreviewDark( - showBackground: Boolean = true, - content: @Composable () -> Unit -) { - ElementPreview( - darkTheme = true, - showBackground = showBackground, - content = content - ) -} - -@Composable -@Suppress("ModifierMissing") -fun ElementThemedPreview( - showBackground: Boolean = true, - vertical: Boolean = true, - content: @Composable () -> Unit, -) { - Box( - modifier = Modifier - .background(Color.Gray) - .padding(4.dp) - ) { - if (vertical) { - Column { - ElementPreview( - darkTheme = false, - showBackground = showBackground, - content = content, - ) - Spacer(modifier = Modifier.height(4.dp)) - ElementPreview( - darkTheme = true, - showBackground = showBackground, - content = content - ) - } - } else { - Row { - ElementPreview( - darkTheme = false, - showBackground = showBackground, - content = content, - ) - Spacer(modifier = Modifier.width(4.dp)) - ElementPreview( - darkTheme = true, - showBackground = showBackground, - content = content - ) - } - } - } -} - @Composable @Suppress("ModifierMissing") fun ElementPreview( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt new file mode 100644 index 0000000000..595b82214d --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewDark.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 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.libraries.designsystem.preview + +import androidx.compose.runtime.Composable + +@Composable +fun ElementPreviewDark( + showBackground: Boolean = true, + content: @Composable () -> Unit +) { + ElementPreview( + darkTheme = true, + showBackground = showBackground, + content = content + ) +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt new file mode 100644 index 0000000000..fe1c2aa45a --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementPreviewLight.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 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.libraries.designsystem.preview + +import androidx.compose.runtime.Composable + +@Composable +fun ElementPreviewLight( + showBackground: Boolean = true, + content: @Composable () -> Unit +) { + ElementPreview( + darkTheme = false, + showBackground = showBackground, + content = content + ) +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementThemedPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementThemedPreview.kt new file mode 100644 index 0000000000..0a6b9fd46e --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/preview/ElementThemedPreview.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023 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.libraries.designsystem.preview + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp + +@Composable +@Suppress("ModifierMissing") +fun ElementThemedPreview( + showBackground: Boolean = true, + vertical: Boolean = true, + content: @Composable () -> Unit, +) { + Box( + modifier = Modifier + .background(Color.Gray) + .padding(4.dp) + ) { + if (vertical) { + Column { + ElementPreview( + darkTheme = false, + showBackground = showBackground, + content = content, + ) + Spacer(modifier = Modifier.height(4.dp)) + ElementPreview( + darkTheme = true, + showBackground = showBackground, + content = content + ) + } + } else { + Row { + ElementPreview( + darkTheme = false, + showBackground = showBackground, + content = content, + ) + Spacer(modifier = Modifier.width(4.dp)) + ElementPreview( + darkTheme = true, + showBackground = showBackground, + content = content + ) + } + } + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt index c6408b662e..95cf050cc3 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/text/DpScale.kt @@ -52,7 +52,7 @@ fun Dp.applyScaleUp(): Dp = with(LocalDensity.current) { @Preview @Composable -internal fun DpScalePreview_0_75f() = WithFontScale(0.75f) { +internal fun DpScale_0_75f_Preview() = WithFontScale(0.75f) { ElementPreviewLight { val fontSizeInDp = 16.dp Column( @@ -77,7 +77,7 @@ internal fun DpScalePreview_0_75f() = WithFontScale(0.75f) { @Preview @Composable -internal fun DpScalePreview_1_0f() = WithFontScale(1f) { +internal fun DpScale_1_0f_Preview() = WithFontScale(1f) { ElementPreviewLight { val fontSizeInDp = 16.dp Column( @@ -102,7 +102,7 @@ internal fun DpScalePreview_1_0f() = WithFontScale(1f) { @Preview @Composable -internal fun DpScalePreview_1_5f() = WithFontScale(1.5f) { +internal fun DpScale_1_5f_Preview() = WithFontScale(1.5f) { ElementPreviewLight { val fontSizeInDp = 16.dp Column( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt index 7e3cc144ac..fce2cb3eff 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/Button.kt @@ -117,7 +117,7 @@ fun TextButton( ) @Composable -internal fun ButtonInternal( +private fun ButtonInternal( text: String, onClick: () -> Unit, style: ButtonStyle, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSectionHeader.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSectionHeader.kt new file mode 100644 index 0000000000..646c7cc6dd --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSectionHeader.kt @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2023 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.libraries.designsystem.theme.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalTextStyle +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.preview.ElementThemedPreview +import io.element.android.libraries.designsystem.preview.PreviewGroup +import io.element.android.libraries.theme.ElementTheme + +// Designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=425%3A24208&mode=design&t=G5hCfkLB6GgXDuWe-1 + +/** + * List section header. + * @param title The title of the section. + * @param modifier The modifier to be applied to the section. + * @param hasDivider Whether to show a divider above the section or not. Default is `true`. + * @param description A description for the section. It's empty by default. + */ +@Composable +fun ListSectionHeader( + title: String, + modifier: Modifier = Modifier, + hasDivider: Boolean = true, + description: @Composable () -> Unit = {}, +) { + Column(modifier.fillMaxWidth()) { + if (hasDivider) { + HorizontalDivider(modifier = Modifier.padding(top = 16.dp)) + } + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = title, + style = ElementTheme.typography.fontBodyLgMedium, + color = ElementTheme.colors.textPrimary, + ) + CompositionLocalProvider( + LocalTextStyle provides ElementTheme.typography.fontBodySmRegular, + LocalContentColor provides ElementTheme.colors.textSecondary, + ) { + description() + } + } + } +} + +@Preview(group = PreviewGroup.ListSections, name = "List section header") +@Composable +internal fun ListSectionHeaderPreview() { + ElementThemedPreview { + ListSectionHeader( + title = "List section", + hasDivider = false, + ) + } +} + +@Preview(group = PreviewGroup.ListSections, name = "List section header with divider") +@Composable +internal fun ListSectionHeaderWithDividerPreview() { + ElementThemedPreview { + ListSectionHeader( + title = "List section", + hasDivider = true, + ) + } +} + +@Preview(group = PreviewGroup.ListSections, name = "List section header with description") +@Composable +internal fun ListSectionHeaderWithDescriptionPreview() { + ElementThemedPreview { + ListSectionHeader( + title = "List section", + description = { + ListSupportingText( + text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more", + contentPadding = ListSupportingTextDefaults.Padding.None, + ) + }, + hasDivider = false, + ) + } +} + +@Preview(group = PreviewGroup.ListSections, name = "List section header with description and divider") +@Composable +internal fun ListSectionHeaderWithDescriptionAndDividerPreview() { + ElementThemedPreview { + ListSectionHeader( + title = "List section", + description = { + ListSupportingText( + text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more", + contentPadding = ListSupportingTextDefaults.Padding.None, + ) + }, + hasDivider = true, + ) + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSection.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSupportingText.kt similarity index 69% rename from libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSection.kt rename to libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSupportingText.kt index 32cc676c43..f76562f0cd 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSection.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/ListSupportingText.kt @@ -16,15 +16,10 @@ package io.element.android.libraries.designsystem.theme.components -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.LocalTextStyle import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.ExperimentalTextApi @@ -40,43 +35,6 @@ import io.element.android.libraries.theme.ElementTheme // Designs: https://www.figma.com/file/G1xy0HDZKJf5TCRFmKb5d5/Compound-Android-Components?type=design&node-id=425%3A24208&mode=design&t=G5hCfkLB6GgXDuWe-1 -/** - * List section header. - * @param title The title of the section. - * @param modifier The modifier to be applied to the section. - * @param hasDivider Whether to show a divider above the section or not. Default is `true`. - * @param description A description for the section. It's empty by default. - */ -@Composable -fun ListSectionHeader( - title: String, - modifier: Modifier = Modifier, - hasDivider: Boolean = true, - description: @Composable () -> Unit = {}, -) { - Column(modifier.fillMaxWidth()) { - if (hasDivider) { - HorizontalDivider(modifier = Modifier.padding(top = 16.dp)) - } - Column( - modifier = Modifier.padding(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - Text( - text = title, - style = ElementTheme.typography.fontBodyLgMedium, - color = ElementTheme.colors.textPrimary, - ) - CompositionLocalProvider( - LocalTextStyle provides ElementTheme.typography.fontBodySmRegular, - LocalContentColor provides ElementTheme.colors.textSecondary, - ) { - description() - } - } - } -} - /** * List supporting text item. Used to display an explanation in the list with a pre-formatted style. * @param text The text to display. @@ -167,68 +125,6 @@ object ListSupportingTextDefaults { } } -// region: List header previews - -@Preview(group = PreviewGroup.ListSections, name = "List section header") -@Composable -internal fun ListSectionHeaderPreview() { - ElementThemedPreview { - ListSectionHeader( - title = "List section", - hasDivider = false, - ) - } -} - -@Preview(group = PreviewGroup.ListSections, name = "List section header with divider") -@Composable -internal fun ListSectionHeaderWithDividerPreview() { - ElementThemedPreview { - ListSectionHeader( - title = "List section", - hasDivider = true, - ) - } -} - -@Preview(group = PreviewGroup.ListSections, name = "List section header with description") -@Composable -internal fun ListSectionHeaderWithDescriptionPreview() { - ElementThemedPreview { - ListSectionHeader( - title = "List section", - description = { - ListSupportingText( - text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more", - contentPadding = ListSupportingTextDefaults.Padding.None, - ) - }, - hasDivider = false, - ) - } -} - -@Preview(group = PreviewGroup.ListSections, name = "List section header with description and divider") -@Composable -internal fun ListSectionHeaderWithDescriptionAndDividerPreview() { - ElementThemedPreview { - ListSectionHeader( - title = "List section", - description = { - ListSupportingText( - text = "Supporting line text lorem ipsum dolor sit amet, consectetur. Read more", - contentPadding = ListSupportingTextDefaults.Padding.None, - ) - }, - hasDivider = true, - ) - } -} - -// endregion - -// region: List supporting text previews - @Preview(group = PreviewGroup.ListSections, name = "List supporting text - no padding") @Composable internal fun ListSupportingTextNoPaddingPreview() { @@ -298,5 +194,3 @@ internal fun ListSupportingTextCustomPaddingPreview() { } } } - -// endregion diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchBar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchBar.kt index 8e5bcf6f82..65d156fbbc 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchBar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/SearchBar.kt @@ -193,11 +193,11 @@ sealed interface SearchBarResultState { @Preview(group = PreviewGroup.Search) @Composable -internal fun SearchBarPreviewInactive() = ElementThemedPreview { ContentToPreview() } +internal fun SearchBarInactivePreview() = ElementThemedPreview { ContentToPreview() } @Preview(group = PreviewGroup.Search) @Composable -internal fun SearchBarPreviewActiveEmptyQuery() = ElementThemedPreview { +internal fun SearchBarActiveEmptyQueryPreview() = ElementThemedPreview { ContentToPreview( query = "", active = true, @@ -206,7 +206,7 @@ internal fun SearchBarPreviewActiveEmptyQuery() = ElementThemedPreview { @Preview(group = PreviewGroup.Search) @Composable -internal fun SearchBarPreviewActiveWithQuery() = ElementThemedPreview { +internal fun SearchBarActiveWithQueryPreview() = ElementThemedPreview { ContentToPreview( query = "search term", active = true, @@ -215,7 +215,7 @@ internal fun SearchBarPreviewActiveWithQuery() = ElementThemedPreview { @Preview(group = PreviewGroup.Search) @Composable -internal fun SearchBarPreviewActiveWithQueryNoBackButton() = ElementThemedPreview { +internal fun SearchBarActiveWithQueryNoBackButtonPreview() = ElementThemedPreview { ContentToPreview( query = "search term", active = true, @@ -225,7 +225,7 @@ internal fun SearchBarPreviewActiveWithQueryNoBackButton() = ElementThemedPrevie @Preview(group = PreviewGroup.Search) @Composable -internal fun SearchBarPreviewActiveWithNoResults() = ElementThemedPreview { +internal fun SearchBarActiveWithNoResultsPreview() = ElementThemedPreview { ContentToPreview( query = "search term", active = true, @@ -235,7 +235,7 @@ internal fun SearchBarPreviewActiveWithNoResults() = ElementThemedPreview { @Preview(group = PreviewGroup.Search) @Composable -internal fun SearchBarPreviewActiveWithContent() = ElementThemedPreview { +internal fun SearchBarActiveWithContentPreview() = ElementThemedPreview { ContentToPreview( query = "search term", active = true, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/DatePickerPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/DatePickerPreview.kt index e0435ee30e..1b2bfd2188 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/DatePickerPreview.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/DatePickerPreview.kt @@ -30,13 +30,13 @@ import io.element.android.libraries.designsystem.preview.PreviewGroup @Preview(group = PreviewGroup.DateTimePickers) @Composable -internal fun DatePickerPreviewLight() { +internal fun DatePickerLightPreview() { ElementPreviewLight { ContentToPreview() } } @Preview(group = PreviewGroup.DateTimePickers) @Composable -internal fun DatePickerPreviewDark() { +internal fun DatePickerDarkPreview() { ElementPreviewDark { ContentToPreview() } } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/TimePickerPreview.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/TimePickerPreview.kt index d900dd6d8b..9e56a38137 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/TimePickerPreview.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/theme/components/previews/TimePickerPreview.kt @@ -55,7 +55,7 @@ internal fun TimePickerHorizontalPreview() { @OptIn(ExperimentalMaterial3Api::class) @Preview(group = PreviewGroup.DateTimePickers) @Composable -internal fun TimePickerVerticalPreviewLight() { +internal fun TimePickerVerticalLightPreview() { ElementPreviewLight { AlertDialogContent( buttons = { /*TODO*/ }, @@ -77,7 +77,7 @@ internal fun TimePickerVerticalPreviewLight() { @OptIn(ExperimentalMaterial3Api::class) @Preview(group = PreviewGroup.DateTimePickers) @Composable -internal fun TimePickerVerticalPreviewDark() { +internal fun TimePickerVerticalDarkPreview() { val pickerState = rememberTimePickerState( initialHour = 12, initialMinute = 0, diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarDispatcher.kt similarity index 68% rename from libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt rename to libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarDispatcher.kt index 9072c4d8a4..9275ea1a76 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/Snackbar.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarDispatcher.kt @@ -14,11 +14,8 @@ * limitations under the License. */ -package io.element.android.libraries.designsystem.utils +package io.element.android.libraries.designsystem.utils.snackbar -import androidx.annotation.StringRes -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.SnackbarDuration import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -26,11 +23,7 @@ import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import io.element.android.libraries.designsystem.components.button.ButtonVisuals -import io.element.android.libraries.designsystem.theme.components.IconSource import io.element.android.libraries.designsystem.theme.components.Snackbar import kotlinx.coroutines.CancellationException import kotlinx.coroutines.currentCoroutineContext @@ -38,7 +31,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.isActive import kotlinx.coroutines.sync.Mutex -import java.util.concurrent.atomic.AtomicBoolean /** * A global dispatcher of [SnackbarMessage] to be displayed in [Snackbar] via a [SnackbarHostState]. @@ -78,23 +70,6 @@ fun SnackbarDispatcher.collectSnackbarMessageAsState(): State return snackbarMessage.collectAsState(initial = null) } -@Composable -fun SnackbarHost(hostState: SnackbarHostState, modifier: Modifier = Modifier) { - androidx.compose.material3.SnackbarHost(hostState, modifier) { data -> - Snackbar( - modifier = Modifier.padding(12.dp), // Add default padding - message = data.visuals.message, - action = data.visuals.actionLabel?.let { ButtonVisuals.Text(it, data::performAction) }, - dismissAction = if (data.visuals.withDismissAction) { - ButtonVisuals.Icon( - IconSource.Resource(CommonDrawables.ic_compound_close), - data::dismiss - ) - } else null, - ) - } -} - /** * Helper method to display a [SnackbarMessage] in a [SnackbarHostState] handling cancellations. */ @@ -127,19 +102,3 @@ fun rememberSnackbarHostState(snackbarMessage: SnackbarMessage?): SnackbarHostSt } return snackbarHostState } - -/** - * A message to be displayed in a [Snackbar]. - * @param messageResId The message to be displayed. - * @param duration The duration of the message. The default value is [SnackbarDuration.Short]. - * @param actionResId The action text to be displayed. The default value is `null`. - * @param isDisplayed Used to track if the current message is already displayed or not. - * @param action The action to be performed when the action is clicked. - */ -data class SnackbarMessage( - @StringRes val messageResId: Int, - val duration: SnackbarDuration = SnackbarDuration.Short, - @StringRes val actionResId: Int? = null, - val isDisplayed: AtomicBoolean = AtomicBoolean(false), - val action: () -> Unit = {}, -) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarHost.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarHost.kt new file mode 100644 index 0000000000..257c23a2b7 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarHost.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 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.libraries.designsystem.utils.snackbar + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.SnackbarHostState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.components.button.ButtonVisuals +import io.element.android.libraries.designsystem.theme.components.IconSource +import io.element.android.libraries.designsystem.theme.components.Snackbar +import io.element.android.libraries.designsystem.utils.CommonDrawables + +@Composable +fun SnackbarHost(hostState: SnackbarHostState, modifier: Modifier = Modifier) { + androidx.compose.material3.SnackbarHost(hostState, modifier) { data -> + Snackbar( + modifier = Modifier.padding(12.dp), // Add default padding + message = data.visuals.message, + action = data.visuals.actionLabel?.let { ButtonVisuals.Text(it, data::performAction) }, + dismissAction = if (data.visuals.withDismissAction) { + ButtonVisuals.Icon( + IconSource.Resource(CommonDrawables.ic_compound_close), + data::dismiss + ) + } else null, + ) + } +} diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarMessage.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarMessage.kt new file mode 100644 index 0000000000..4c254f9027 --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarMessage.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 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.libraries.designsystem.utils.snackbar + +import androidx.annotation.StringRes +import androidx.compose.material3.SnackbarDuration +import java.util.concurrent.atomic.AtomicBoolean + +/** + * A message to be displayed in a [Snackbar]. + * @param messageResId The message to be displayed. + * @param duration The duration of the message. The default value is [SnackbarDuration.Short]. + * @param actionResId The action text to be displayed. The default value is `null`. + * @param isDisplayed Used to track if the current message is already displayed or not. + * @param action The action to be performed when the action is clicked. + */ +data class SnackbarMessage( + @StringRes val messageResId: Int, + val duration: SnackbarDuration = SnackbarDuration.Short, + @StringRes val actionResId: Int? = null, + val isDisplayed: AtomicBoolean = AtomicBoolean(false), + val action: () -> Unit = {}, +) diff --git a/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/utils/SnackbarDispatcherTests.kt b/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarDispatcherTests.kt similarity index 97% rename from libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/utils/SnackbarDispatcherTests.kt rename to libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarDispatcherTests.kt index 3eb644d800..fbccaa4e75 100644 --- a/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/utils/SnackbarDispatcherTests.kt +++ b/libraries/designsystem/src/test/kotlin/io/element/android/libraries/designsystem/utils/snackbar/SnackbarDispatcherTests.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package io.element.android.libraries.designsystem.utils +package io.element.android.libraries.designsystem.utils.snackbar import app.cash.turbine.test import com.google.common.truth.Truth.assertThat diff --git a/libraries/featureflag/ui/src/main/kotlin/io/element/android/libraries/featureflag/ui/FeatureListView.kt b/libraries/featureflag/ui/src/main/kotlin/io/element/android/libraries/featureflag/ui/FeatureListView.kt index 065746c876..6bf4467de8 100644 --- a/libraries/featureflag/ui/src/main/kotlin/io/element/android/libraries/featureflag/ui/FeatureListView.kt +++ b/libraries/featureflag/ui/src/main/kotlin/io/element/android/libraries/featureflag/ui/FeatureListView.kt @@ -46,7 +46,7 @@ fun FeatureListView( } @Composable -fun FeaturePreferenceView( +private fun FeaturePreferenceView( feature: FeatureUiModel, onCheckedChange: (Boolean) -> Unit, modifier: Modifier = Modifier diff --git a/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/Symbol.kt b/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/Symbol.kt index 36e8cdc34e..bb40c7dfa9 100644 --- a/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/Symbol.kt +++ b/libraries/maplibre-compose/src/main/kotlin/io/element/android/libraries/maplibre/compose/Symbol.kt @@ -50,7 +50,7 @@ internal class SymbolNode( * @param position the initial symbol position */ public class SymbolState( - position: LatLng = LatLng(0.0, 0.0) + position: LatLng ) { /** * Current position of the symbol. diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt index d98a3a83d2..2121670d6b 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomNotificationSettingsState.kt @@ -17,7 +17,7 @@ package io.element.android.libraries.matrix.api.room sealed interface MatrixRoomNotificationSettingsState { - object Unknown : MatrixRoomNotificationSettingsState + data object Unknown : MatrixRoomNotificationSettingsState data class Pending(val prevRoomNotificationSettings: RoomNotificationSettings? = null) : MatrixRoomNotificationSettingsState data class Error(val failure: Throwable, val prevRoomNotificationSettings: RoomNotificationSettings? = null) : MatrixRoomNotificationSettingsState data class Ready(val roomNotificationSettings: RoomNotificationSettings) : MatrixRoomNotificationSettingsState diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableMatrixUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableMatrixUserRow.kt index 1e032de06a..d9bbff4f7d 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableMatrixUserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableMatrixUserRow.kt @@ -16,22 +16,13 @@ package io.element.android.libraries.matrix.ui.components -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.semantics.Role import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.unit.dp -import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.theme.components.Checkbox import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.getBestName @@ -54,41 +45,6 @@ fun CheckableMatrixUserRow( enabled = enabled, ) -@Composable -fun CheckableUserRow( - checked: Boolean, - avatarData: AvatarData, - name: String, - subtext: String?, - modifier: Modifier = Modifier, - onCheckedChange: (Boolean) -> Unit = {}, - enabled: Boolean = true, -) { - Row( - modifier = modifier - .fillMaxWidth() - .clickable(role = Role.Checkbox, enabled = enabled) { - onCheckedChange(!checked) - }, - verticalAlignment = Alignment.CenterVertically, - ) { - UserRow( - modifier = Modifier.weight(1f), - avatarData = avatarData, - name = name, - subtext = subtext, - ) - - Checkbox( - modifier = Modifier - .padding(end = 16.dp), - checked = checked, - onCheckedChange = null, - enabled = enabled, - ) - } -} - @PreviewsDayNight @Composable internal fun CheckableMatrixUserRowPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = ElementPreview { diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUnresolvedUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUnresolvedUserRow.kt new file mode 100644 index 0000000000..b829ff8e47 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUnresolvedUserRow.kt @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2023 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.libraries.matrix.ui.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.preview.ElementThemedPreview +import io.element.android.libraries.designsystem.theme.components.Checkbox +import io.element.android.libraries.designsystem.theme.components.HorizontalDivider +import io.element.android.libraries.matrix.ui.model.getAvatarData + +@Composable +fun CheckableUnresolvedUserRow( + checked: Boolean, + avatarData: AvatarData, + id: String, + modifier: Modifier = Modifier, + onCheckedChange: (Boolean) -> Unit = {}, + enabled: Boolean = true, +) { + Row( + modifier = modifier + .fillMaxWidth() + .clickable(role = Role.Checkbox, enabled = enabled) { + onCheckedChange(!checked) + }, + verticalAlignment = Alignment.CenterVertically, + ) { + UnresolvedUserRow( + modifier = Modifier.weight(1f), + avatarData = avatarData, + id = id, + ) + + Checkbox( + modifier = Modifier.padding(end = 16.dp), + checked = checked, + onCheckedChange = null, + enabled = enabled, + ) + } +} + +@Preview +@Composable +internal fun CheckableUnresolvedUserRowPreview() = ElementThemedPreview { + val matrixUser = aMatrixUser() + Column { + CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value) + HorizontalDivider() + CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value) + HorizontalDivider() + CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value, enabled = false) + HorizontalDivider() + CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value, enabled = false) + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt new file mode 100644 index 0000000000..f6272b9fda --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/CheckableUserRow.kt @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 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.libraries.matrix.ui.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.theme.components.Checkbox + +@Composable +fun CheckableUserRow( + checked: Boolean, + avatarData: AvatarData, + name: String, + subtext: String?, + modifier: Modifier = Modifier, + onCheckedChange: (Boolean) -> Unit = {}, + enabled: Boolean = true, +) { + Row( + modifier = modifier + .fillMaxWidth() + .clickable(role = Role.Checkbox, enabled = enabled) { + onCheckedChange(!checked) + }, + verticalAlignment = Alignment.CenterVertically, + ) { + UserRow( + modifier = Modifier.weight(1f), + avatarData = avatarData, + name = name, + subtext = subtext, + ) + + Checkbox( + modifier = Modifier + .padding(end = 16.dp), + checked = checked, + onCheckedChange = null, + enabled = enabled, + ) + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt index 44144deeb6..1380d15e8b 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserRow.kt @@ -16,28 +16,15 @@ package io.element.android.libraries.matrix.ui.components -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.unit.dp -import io.element.android.libraries.designsystem.components.avatar.Avatar -import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.ElementPreview -import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.getBestName -import io.element.android.libraries.theme.ElementTheme @Composable fun MatrixUserRow( @@ -51,47 +38,6 @@ fun MatrixUserRow( modifier = modifier, ) -@Composable -fun UserRow( - avatarData: AvatarData, - name: String, - subtext: String?, - modifier: Modifier = Modifier, -) { - Row( - modifier = modifier - .fillMaxWidth() - .heightIn(min = 56.dp) - .padding(start = 16.dp, top = 4.dp, end = 16.dp, bottom = 4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Avatar(avatarData) - Column( - modifier = Modifier - .padding(start = 12.dp), - ) { - // Name - Text( - text = name, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - color = MaterialTheme.colorScheme.primary, - style = ElementTheme.typography.fontBodyLgRegular, - ) - // Id - subtext?.let { - Text( - text = subtext, - color = MaterialTheme.colorScheme.secondary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - style = ElementTheme.typography.fontBodySmRegular, - ) - } - } - } -} - @PreviewsDayNight @Composable internal fun MatrixUserRowPreview(@PreviewParameter(MatrixUserProvider::class) matrixUser: MatrixUser) = ElementPreview { diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnresolvedUserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnresolvedUserRow.kt index 20c0ac69bc..2916fa7f06 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnresolvedUserRow.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UnresolvedUserRow.kt @@ -16,7 +16,6 @@ package io.element.android.libraries.matrix.ui.components -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -29,7 +28,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -38,8 +36,6 @@ import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.preview.ElementThemedPreview -import io.element.android.libraries.designsystem.theme.components.Checkbox -import io.element.android.libraries.designsystem.theme.components.HorizontalDivider import io.element.android.libraries.designsystem.theme.components.Icon import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.CommonDrawables @@ -101,58 +97,9 @@ fun UnresolvedUserRow( } } +@Preview @Composable -fun CheckableUnresolvedUserRow( - checked: Boolean, - avatarData: AvatarData, - id: String, - modifier: Modifier = Modifier, - onCheckedChange: (Boolean) -> Unit = {}, - enabled: Boolean = true, -) { - Row( - modifier = modifier - .fillMaxWidth() - .clickable(role = Role.Checkbox, enabled = enabled) { - onCheckedChange(!checked) - }, - verticalAlignment = Alignment.CenterVertically, - ) { - UnresolvedUserRow( - modifier = Modifier.weight(1f), - avatarData = avatarData, - id = id, - ) - - Checkbox( - modifier = Modifier.padding(end = 16.dp), - checked = checked, - onCheckedChange = null, - enabled = enabled, - ) - } +internal fun UnresolvedUserRowPreview() = ElementThemedPreview { + val matrixUser = aMatrixUser() + UnresolvedUserRow(matrixUser.getAvatarData(size = AvatarSize.UserListItem), matrixUser.userId.value) } - -@Preview -@Composable -internal fun UnresolvedUserRowPreview() = - ElementThemedPreview { - val matrixUser = aMatrixUser() - UnresolvedUserRow(matrixUser.getAvatarData(size = AvatarSize.UserListItem), matrixUser.userId.value) - } - -@Preview -@Composable -internal fun CheckableUnresolvedUserRowPreview() = - ElementThemedPreview { - val matrixUser = aMatrixUser() - Column { - CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value) - HorizontalDivider() - CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value) - HorizontalDivider() - CheckableUnresolvedUserRow(false, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value, enabled = false) - HorizontalDivider() - CheckableUnresolvedUserRow(true, matrixUser.getAvatarData(AvatarSize.UserListItem), matrixUser.userId.value, enabled = false) - } - } diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt new file mode 100644 index 0000000000..5e59ce7aef --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/UserRow.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023 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.libraries.matrix.ui.components + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.components.avatar.Avatar +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.theme.ElementTheme + +@Composable +internal fun UserRow( + avatarData: AvatarData, + name: String, + subtext: String?, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .fillMaxWidth() + .heightIn(min = 56.dp) + .padding(start = 16.dp, top = 4.dp, end = 16.dp, bottom = 4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Avatar(avatarData) + Column( + modifier = Modifier + .padding(start = 12.dp), + ) { + // Name + Text( + text = name, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + color = MaterialTheme.colorScheme.primary, + style = ElementTheme.typography.fontBodyLgRegular, + ) + // Id + subtext?.let { + Text( + text = subtext, + color = MaterialTheme.colorScheme.secondary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + style = ElementTheme.typography.fontBodySmRegular, + ) + } + } + } +} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt index 6c9138fb15..cf5b13ce9b 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt @@ -56,7 +56,7 @@ class DefaultPushHandler @Inject constructor( private val coroutineScope = CoroutineScope(SupervisorJob()) // UI handler - private val mUIHandler by lazy { + private val uiHandler by lazy { Handler(Looper.getMainLooper()) } @@ -81,7 +81,7 @@ class DefaultPushHandler @Inject constructor( return } - mUIHandler.post { + uiHandler.post { coroutineScope.launch(Dispatchers.IO) { handleInternal(pushData) } } } diff --git a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt index 81780d1c2d..3b87565271 100644 --- a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt +++ b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ElementTheme.kt @@ -26,7 +26,6 @@ import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.SideEffect import androidx.compose.runtime.remember @@ -138,27 +137,7 @@ fun ElementTheme( } } -/** - * Can be used to force a composable in dark theme. - * It will automatically change the system ui colors back to normal when leaving the composition. - */ -@Composable -fun ForcedDarkElementTheme( - lightStatusBar: Boolean = false, - content: @Composable () -> Unit, -) { - val systemUiController = rememberSystemUiController() - val colorScheme = MaterialTheme.colorScheme - val wasDarkTheme = !ElementTheme.colors.isLight - DisposableEffect(Unit) { - onDispose { - systemUiController.applyTheme(colorScheme, wasDarkTheme) - } - } - ElementTheme(darkTheme = true, lightStatusBar = lightStatusBar, content = content) -} - -private fun SystemUiController.applyTheme( +internal fun SystemUiController.applyTheme( colorScheme: ColorScheme, darkTheme: Boolean, ) { diff --git a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ForcedDarkElementTheme.kt b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ForcedDarkElementTheme.kt new file mode 100644 index 0000000000..c10ea74fc9 --- /dev/null +++ b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/ForcedDarkElementTheme.kt @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 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.libraries.theme + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import com.google.accompanist.systemuicontroller.rememberSystemUiController + +/** + * Can be used to force a composable in dark theme. + * It will automatically change the system ui colors back to normal when leaving the composition. + */ +@Composable +fun ForcedDarkElementTheme( + lightStatusBar: Boolean = false, + content: @Composable () -> Unit, +) { + val systemUiController = rememberSystemUiController() + val colorScheme = MaterialTheme.colorScheme + val wasDarkTheme = !ElementTheme.colors.isLight + DisposableEffect(Unit) { + onDispose { + systemUiController.applyTheme(colorScheme, wasDarkTheme) + } + } + ElementTheme(darkTheme = true, lightStatusBar = lightStatusBar, content = content) +} diff --git a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/MaterialThemeColors.kt b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/MaterialThemeColors.kt index 3d359594e1..9df1db3505 100644 --- a/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/MaterialThemeColors.kt +++ b/libraries/theme/src/main/kotlin/io/element/android/libraries/theme/MaterialThemeColors.kt @@ -91,7 +91,7 @@ internal val materialColorSchemeDark = darkColorScheme( @Preview @Composable -internal fun ColorsSchemePreviewLight() = ColorsSchemePreview( +internal fun ColorsSchemeLightPreview() = ColorsSchemePreview( Color.Black, Color.White, materialColorSchemeLight, @@ -99,7 +99,7 @@ internal fun ColorsSchemePreviewLight() = ColorsSchemePreview( @Preview @Composable -internal fun ColorsSchemePreviewDark() = ColorsSchemePreview( +internal fun ColorsSchemeDarkPreview() = ColorsSchemePreview( Color.White, Color.Black, materialColorSchemeDark, diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt index 425888f003..0c43619f39 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt @@ -31,7 +31,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.dateformatter.impl.DateFormatters import io.element.android.libraries.dateformatter.impl.DefaultLastMessageTimestampFormatter import io.element.android.libraries.dateformatter.impl.LocalDateTimeProvider -import io.element.android.libraries.designsystem.utils.SnackbarDispatcher +import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.eventformatter.impl.DefaultRoomLastMessageFormatter import io.element.android.libraries.eventformatter.impl.ProfileChangeContentFormatter import io.element.android.libraries.eventformatter.impl.RoomMembershipContentFormatter diff --git a/services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt b/services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt index cbc8f53e0b..80ac8d30fc 100644 --- a/services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt +++ b/services/apperror/impl/src/main/kotlin/io/element/android/services/apperror/impl/AppErrorView.kt @@ -37,7 +37,7 @@ fun AppErrorView( } @Composable -fun AppErrorViewContent( +private fun AppErrorViewContent( title: String, body: String, onDismiss: () -> Unit = { }, diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_0_75f_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_0_75f__0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_0_75f_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_0_75f__0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_1_0f_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_1_0f__0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_1_0f_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_1_0f__0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_1_5f_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_1_5f__0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_1_5f_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.text_null_DpScale_1_5f__0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_DatePickerDark_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewDark_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_DatePickerDark_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_DatePickerLight_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_DatePickerPreviewLight_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_DatePickerLight_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalDark_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewDark_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalDark_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalLight_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalPreviewLight_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components.previews_null_DateTimepickers_TimePickerVerticalLight_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewActiveEmptyQuery_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarActiveEmptyQuery_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewActiveEmptyQuery_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarActiveEmptyQuery_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewActiveWithContent_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarActiveWithContent_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewActiveWithContent_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarActiveWithContent_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewActiveWithNoResults_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarActiveWithNoResults_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewActiveWithNoResults_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarActiveWithNoResults_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewActiveWithQueryNoBackButton_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarActiveWithQueryNoBackButton_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewActiveWithQueryNoBackButton_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarActiveWithQueryNoBackButton_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewActiveWithQuery_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarActiveWithQuery_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewActiveWithQuery_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarActiveWithQuery_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewInactive_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarInactive_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarPreviewInactive_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.designsystem.theme.components_null_Searchviews_SearchBarInactive_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.theme_null_ColorsSchemePreviewDark_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.theme_null_ColorsSchemeDark_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.theme_null_ColorsSchemePreviewDark_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.theme_null_ColorsSchemeDark_0_null,NEXUS_5,1.0,en].png diff --git a/tests/uitests/src/test/snapshots/images/ui_S_t[l.theme_null_ColorsSchemePreviewLight_0_null,NEXUS_5,1.0,en].png b/tests/uitests/src/test/snapshots/images/ui_S_t[l.theme_null_ColorsSchemeLight_0_null,NEXUS_5,1.0,en].png similarity index 100% rename from tests/uitests/src/test/snapshots/images/ui_S_t[l.theme_null_ColorsSchemePreviewLight_0_null,NEXUS_5,1.0,en].png rename to tests/uitests/src/test/snapshots/images/ui_S_t[l.theme_null_ColorsSchemeLight_0_null,NEXUS_5,1.0,en].png