diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpanTheme.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpanTheme.kt index 323c1f0a9a..4edbb8bf38 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpanTheme.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/mentions/MentionSpanTheme.kt @@ -13,11 +13,17 @@ import android.net.Uri import android.text.Spanned import android.view.ViewGroup import android.widget.TextView +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection @@ -28,6 +34,9 @@ import io.element.android.compound.theme.ElementTheme import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.rememberTypeface +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.messageFromMeBackground +import io.element.android.libraries.designsystem.theme.messageFromOtherBackground import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SingleIn import io.element.android.libraries.matrix.api.MatrixClient @@ -48,7 +57,8 @@ import javax.inject.Inject @Stable @SingleIn(SessionScope::class) class MentionSpanTheme(val currentUserId: UserId) { - @Inject constructor(matrixClient: MatrixClient) : this(matrixClient.sessionId) + @Inject + constructor(matrixClient: MatrixClient) : this(matrixClient.sessionId) internal var currentUserTextColor: Int = 0 internal var currentUserBackgroundColor: Int = Color.WHITE @@ -162,3 +172,115 @@ internal fun MentionSpanThemePreview() { }) } } + +@Composable +private fun MentionSpanThemeInTimelineContent( + bgColor: Int, + modifier: Modifier = Modifier, +) { + val mentionSpanTheme = remember { MentionSpanTheme(UserId("@me:matrix.org")) } + val provider = remember { + MentionSpanProvider( + mentionSpanTheme = mentionSpanTheme, + mentionSpanFormatter = object : MentionSpanFormatter { + override fun formatDisplayText(mentionType: MentionType): CharSequence { + return when (mentionType) { + is MentionType.User -> mentionType.userId.value + else -> throw AssertionError("Unexpected value $mentionType") + } + } + }, + permalinkParser = object : PermalinkParser { + override fun parse(uriString: String): PermalinkData { + return when (uriString) { + "https://matrix.to/#/@me:matrix.org" -> PermalinkData.UserLink(UserId("@me:matrix.org")) + "https://matrix.to/#/@other:matrix.org" -> PermalinkData.UserLink(UserId("@other:matrix.org")) + else -> throw AssertionError("Unexpected value $uriString") + } + } + }, + ) + } + + val textColor = ElementTheme.colors.textPrimary.toArgb() + fun mentionSpanMe() = provider.getMentionSpanFor("mention", "https://matrix.to/#/@me:matrix.org") + fun mentionSpanOther() = provider.getMentionSpanFor("mention", "https://matrix.to/#/@other:matrix.org") + mentionSpanTheme.updateStyles() + + AndroidView( + modifier = modifier, + factory = { context -> + TextView(context).apply { + includeFontPadding = false + layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + text = buildSpannedString { + append("Hello ") + append("@mention", mentionSpanMe(), 0) + append(" ") + append("@mention", mentionSpanOther(), 0) + } + setTextColor(textColor) + setBackgroundColor(bgColor) + } + } + ) +} + +@PreviewsDayNight +@Composable +internal fun MentionSpanThemeInTimelinePreview() = ElementPreview { + Column( + modifier = Modifier.padding(8.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + // Message from me + Text( + text = "Message from me", + style = ElementTheme.typography.fontBodySmMedium, + ) + ElementTheme.colors.messageFromMeBackground.let { color -> + MentionSpanThemeInTimelineContent( + modifier = Modifier + .padding(start = 60.dp, end = 8.dp) + .background( + color = color, + shape = RoundedCornerShape(12.dp), + ) + .padding(8.dp), + bgColor = color.toArgb() + ) + } + // Message from other + ElementTheme.colors.messageFromOtherBackground.let { color -> + Text( + text = "Message from other", + style = ElementTheme.typography.fontBodySmMedium, + ) + MentionSpanThemeInTimelineContent( + modifier = Modifier + .padding(start = 8.dp, end = 60.dp) + .padding(4.dp) + .background( + color = color, + shape = RoundedCornerShape(12.dp) + ) + .padding(8.dp), + bgColor = color.toArgb() + ) + } + // Composer + ElementTheme.colors.bgSubtleSecondary.let { color -> + Text( + text = "Composer", + style = ElementTheme.typography.fontBodySmMedium, + ) + MentionSpanThemeInTimelineContent( + modifier = Modifier + .padding(start = 4.dp, end = 4.dp) + .background(color) + .padding(8.dp), + bgColor = color.toArgb() + ) + } + } +} diff --git a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt index 5b0454040c..a45791a6d0 100644 --- a/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt +++ b/tests/konsist/src/test/kotlin/io/element/android/tests/konsist/KonsistPreviewTest.kt @@ -73,6 +73,7 @@ class KonsistPreviewTest { "MatrixBadgeAtomNegativePreview", "MatrixBadgeAtomNeutralPreview", "MatrixBadgeAtomPositivePreview", + "MentionSpanThemeInTimelinePreview", "MessageComposerViewVoicePreview", "MessagesReactionButtonAddPreview", "MessagesReactionButtonExtraPreview",