From 5fe2c86e1d5e8862169474d5f085b7bcc1066c0f Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Wed, 5 Nov 2025 17:04:19 +0000 Subject: [PATCH 1/5] feat: Convert `ComposerAlertMolecule` to use alert levels. --- .../features/messages/impl/MessagesView.kt | 1 - .../identity/IdentityChangeStateView.kt | 3 +- .../virtual/TimelineItemRoomBeginningView.kt | 1 - .../atomic/molecules/ComposerAlertMolecule.kt | 88 ++++++++++++++++--- 4 files changed, 78 insertions(+), 15 deletions(-) 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 0221bf2c94..23dca9467f 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 @@ -522,7 +522,6 @@ private fun SuccessorRoomBanner( content = stringResource(R.string.screen_room_timeline_tombstoned_room_message).toAnnotatedString(), onSubmitClick = { onRoomSuccessorClick(roomSuccessor.roomId) }, modifier = modifier, - isCritical = false, submitText = stringResource(R.string.screen_room_timeline_tombstoned_room_action) ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateView.kt index 0f55985740..f5f81a3b64 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/crypto/identity/IdentityChangeStateView.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.tooling.preview.PreviewParameter import io.element.android.appconfig.LearnMoreConfig import io.element.android.compound.theme.ElementTheme +import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertLevel import io.element.android.libraries.designsystem.atomic.molecules.ComposerAlertMolecule import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight @@ -113,7 +114,7 @@ private fun ViolationAlert( }, submitText = stringResource(submitTextId), onSubmitClick = onSubmitClick, - isCritical = isCritical, + level = if (isCritical) ComposerAlertLevel.Critical else ComposerAlertLevel.Default, ) } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemRoomBeginningView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemRoomBeginningView.kt index a3cab8610f..65667041c3 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemRoomBeginningView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/virtual/TimelineItemRoomBeginningView.kt @@ -45,7 +45,6 @@ fun TimelineItemRoomBeginningView( avatar = null, content = stringResource(R.string.screen_room_timeline_upgraded_room_message).toAnnotatedString(), onSubmitClick = { onPredecessorRoomClick(predecessorRoom.roomId) }, - isCritical = false, submitText = stringResource(R.string.screen_room_timeline_upgraded_room_action) ) } diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt index 07e2454dbc..b898871a6b 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt @@ -18,12 +18,15 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme +import io.element.android.compound.tokens.generated.CompoundIcons 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 @@ -34,8 +37,8 @@ import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.toAnnotatedString import io.element.android.libraries.designsystem.theme.components.Button import io.element.android.libraries.designsystem.theme.components.ButtonSize +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.BooleanProvider import io.element.android.libraries.ui.strings.CommonStrings @Composable @@ -44,20 +47,37 @@ fun ComposerAlertMolecule( content: AnnotatedString, onSubmitClick: () -> Unit, modifier: Modifier = Modifier, - isCritical: Boolean = false, + level: ComposerAlertLevel = ComposerAlertLevel.Default, + showIcon: Boolean = false, submitText: String = stringResource(CommonStrings.action_ok), ) { Column( modifier.fillMaxWidth() ) { - val lineColor = if (isCritical) ElementTheme.colors.borderCriticalSubtle else ElementTheme.colors.borderInfoSubtle + val lineColor = when (level) { + ComposerAlertLevel.Default -> ElementTheme.colors.borderInfoSubtle + ComposerAlertLevel.Info -> ElementTheme.colors.borderInfoSubtle + ComposerAlertLevel.Critical -> ElementTheme.colors.borderCriticalSubtle + } + + val startColor = when (level) { + ComposerAlertLevel.Default -> ElementTheme.colors.bgInfoSubtle + ComposerAlertLevel.Info -> ElementTheme.colors.bgInfoSubtle + ComposerAlertLevel.Critical -> ElementTheme.colors.bgCriticalSubtle + } + + val textColor = when (level) { + ComposerAlertLevel.Default -> ElementTheme.colors.textPrimary + ComposerAlertLevel.Info -> ElementTheme.colors.textInfoPrimary + ComposerAlertLevel.Critical -> ElementTheme.colors.textCriticalPrimary + } + Box( modifier = Modifier .fillMaxWidth() .height(1.dp) .background(lineColor) ) - val startColor = if (isCritical) ElementTheme.colors.bgCriticalSubtle else ElementTheme.colors.bgInfoSubtle val brush = Brush.verticalGradient( listOf(startColor, ElementTheme.colors.bgCanvasDefault), ) @@ -77,16 +97,28 @@ fun ComposerAlertMolecule( avatarData = avatar, avatarType = AvatarType.User, ) + } else if (showIcon) { + val icon = when (level) { + ComposerAlertLevel.Default -> CompoundIcons.Info() + ComposerAlertLevel.Info -> CompoundIcons.Info() + ComposerAlertLevel.Critical -> CompoundIcons.Error() + } + val iconTint = when (level) { + ComposerAlertLevel.Default -> ElementTheme.colors.iconPrimary + ComposerAlertLevel.Info -> ElementTheme.colors.iconInfoPrimary + ComposerAlertLevel.Critical -> ElementTheme.colors.iconCriticalPrimary + } + Icon( + painter = rememberVectorPainter(icon), + tint = iconTint, + contentDescription = null, + ) } Text( text = content, modifier = Modifier.weight(1f), style = ElementTheme.typography.fontBodyMdRegular, - color = if (isCritical) { - ElementTheme.colors.textCriticalPrimary - } else { - ElementTheme.colors.textPrimary - }, + color = textColor, textAlign = TextAlign.Start, ) } @@ -101,13 +133,45 @@ fun ComposerAlertMolecule( } } +enum class ComposerAlertLevel { + Default, + Info, + Critical +} + +internal data class ComposerAlertMoleculeParams( + val level: ComposerAlertLevel, + val avatar: AvatarData? = null, + val showIcon: Boolean = false, +) + +internal class ComposerAlertMoleculeParamsProvider : PreviewParameterProvider { + private val allLevels = sequenceOf( + ComposerAlertLevel.Default, + ComposerAlertLevel.Info, + ComposerAlertLevel.Critical + ) + + override val values: Sequence + get() = allLevels.flatMap { level -> + sequenceOf( + ComposerAlertMoleculeParams(level = level), + ComposerAlertMoleculeParams(level = level, avatar = anAvatarData(size = AvatarSize.ComposerAlert)), + ComposerAlertMoleculeParams(level = level, showIcon = true), + ) + } +} + @PreviewsDayNight @Composable -internal fun ComposerAlertMoleculePreview(@PreviewParameter(BooleanProvider::class) isCritical: Boolean) = ElementPreview { +internal fun ComposerAlertMoleculePreview( + @PreviewParameter(ComposerAlertMoleculeParamsProvider::class) params: ComposerAlertMoleculeParams, +) = ElementPreview { ComposerAlertMolecule( - avatar = anAvatarData(size = AvatarSize.ComposerAlert), + avatar = params.avatar, content = "Alice’s verified identity has changed. Learn more".toAnnotatedString(), - isCritical = isCritical, + level = params.level, + showIcon = params.showIcon, onSubmitClick = {}, ) } From b1639592413882dd4f46d79f41b225c960fcfd98 Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Fri, 7 Nov 2025 15:13:47 +0000 Subject: [PATCH 2/5] refactor: Extract `ComposerAlertMoleculeParamsProvider` to new file. --- .../atomic/molecules/ComposerAlertMolecule.kt | 26 -------------- .../ComposerAlertMoleculeParamsProvider.kt | 36 +++++++++++++++++++ 2 files changed, 36 insertions(+), 26 deletions(-) create mode 100644 libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMoleculeParamsProvider.kt diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt index b898871a6b..e156c4d9d0 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt @@ -23,15 +23,12 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons 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.avatar.AvatarType -import io.element.android.libraries.designsystem.components.avatar.anAvatarData import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.toAnnotatedString @@ -139,29 +136,6 @@ enum class ComposerAlertLevel { Critical } -internal data class ComposerAlertMoleculeParams( - val level: ComposerAlertLevel, - val avatar: AvatarData? = null, - val showIcon: Boolean = false, -) - -internal class ComposerAlertMoleculeParamsProvider : PreviewParameterProvider { - private val allLevels = sequenceOf( - ComposerAlertLevel.Default, - ComposerAlertLevel.Info, - ComposerAlertLevel.Critical - ) - - override val values: Sequence - get() = allLevels.flatMap { level -> - sequenceOf( - ComposerAlertMoleculeParams(level = level), - ComposerAlertMoleculeParams(level = level, avatar = anAvatarData(size = AvatarSize.ComposerAlert)), - ComposerAlertMoleculeParams(level = level, showIcon = true), - ) - } -} - @PreviewsDayNight @Composable internal fun ComposerAlertMoleculePreview( diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMoleculeParamsProvider.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMoleculeParamsProvider.kt new file mode 100644 index 0000000000..8aedf6b26b --- /dev/null +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMoleculeParamsProvider.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.designsystem.atomic.molecules + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import io.element.android.libraries.designsystem.components.avatar.AvatarData +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.components.avatar.anAvatarData + +internal data class ComposerAlertMoleculeParams( + val level: ComposerAlertLevel, + val avatar: AvatarData? = null, + val showIcon: Boolean = false, +) + +internal class ComposerAlertMoleculeParamsProvider : PreviewParameterProvider { + private val allLevels = sequenceOf( + ComposerAlertLevel.Default, + ComposerAlertLevel.Info, + ComposerAlertLevel.Critical + ) + + override val values: Sequence + get() = allLevels.flatMap { level -> + sequenceOf( + ComposerAlertMoleculeParams(level = level), + ComposerAlertMoleculeParams(level = level, avatar = anAvatarData(size = AvatarSize.ComposerAlert)), + ComposerAlertMoleculeParams(level = level, showIcon = true), + ) + } +} From 7595a0be35b180f94bab9dae0a538ef86b7e0c73 Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Fri, 7 Nov 2025 15:18:08 +0000 Subject: [PATCH 3/5] fix: Use `Icon(imageVector = icon)` over `rememberVectorPainter(icon)` --- .../designsystem/atomic/molecules/ComposerAlertMolecule.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt index e156c4d9d0..59c2eb40ab 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt @@ -106,7 +106,7 @@ fun ComposerAlertMolecule( ComposerAlertLevel.Critical -> ElementTheme.colors.iconCriticalPrimary } Icon( - painter = rememberVectorPainter(icon), + imageVector = icon, tint = iconTint, contentDescription = null, ) From d4dba4b0fc2d740f47653969e701d2f4d0a11e78 Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Fri, 7 Nov 2025 15:24:24 +0000 Subject: [PATCH 4/5] chore: Remove unused import. --- .idea/markdown.xml | 8 ++++++++ .../atomic/molecules/ComposerAlertMolecule.kt | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .idea/markdown.xml diff --git a/.idea/markdown.xml b/.idea/markdown.xml new file mode 100644 index 0000000000..c61ea3346e --- /dev/null +++ b/.idea/markdown.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt index 59c2eb40ab..79f248f4b9 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/atomic/molecules/ComposerAlertMolecule.kt @@ -18,7 +18,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.style.TextAlign From b3812544cb7597f2cef78bc60622ac19a3666abc Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Fri, 7 Nov 2025 16:08:17 +0000 Subject: [PATCH 5/5] chore: Remove `.idea/markdown.xml` and add to `.gitignore`. --- .gitignore | 1 + .idea/markdown.xml | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 .idea/markdown.xml diff --git a/.gitignore b/.gitignore index e1b1c5c8ab..5ed296ab80 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,7 @@ captures/ .idea/deviceManager.xml .idea/gradle.xml .idea/jarRepositories.xml +.idea/markdown.xml .idea/misc.xml .idea/modules.xml # Comment next line if keeping position of elements in Navigation Editor is relevant for you diff --git a/.idea/markdown.xml b/.idea/markdown.xml deleted file mode 100644 index c61ea3346e..0000000000 --- a/.idea/markdown.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - \ No newline at end of file