Browse Source

Timeline: start handling multiple contents

feature/bma/flipper
ganfra 2 years ago
parent
commit
0573ea547e
  1. 34
      features/messages/src/main/java/io/element/android/x/features/messages/MessageTimelineItemStateMapper.kt
  2. 62
      features/messages/src/main/java/io/element/android/x/features/messages/MessagesScreen.kt
  3. 20
      features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemEncryptedView.kt
  4. 41
      features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemInformativeView.kt
  5. 20
      features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemRedactedView.kt
  6. 17
      features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemTextView.kt
  7. 20
      features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemUnknownView.kt
  8. 5
      features/messages/src/main/java/io/element/android/x/features/messages/model/MessagesTimelineItemState.kt
  9. 3
      features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemContent.kt
  10. 8
      features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemEmoteContent.kt
  11. 7
      features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemEncryptedContent.kt
  12. 8
      features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemNoticeContent.kt
  13. 3
      features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemRedactedContent.kt
  14. 8
      features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemTextBasedContent.kt
  15. 8
      features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemTextContent.kt
  16. 3
      features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemUnknownContent.kt

34
features/messages/src/main/java/io/element/android/x/features/messages/MessageTimelineItemStateMapper.kt

@ -4,6 +4,7 @@ import io.element.android.x.designsystem.components.avatar.AvatarData @@ -4,6 +4,7 @@ import io.element.android.x.designsystem.components.avatar.AvatarData
import io.element.android.x.designsystem.components.avatar.AvatarSize
import io.element.android.x.features.messages.model.MessagesItemGroupPosition
import io.element.android.x.features.messages.model.MessagesTimelineItemState
import io.element.android.x.features.messages.model.content.*
import io.element.android.x.matrix.MatrixClient
import io.element.android.x.matrix.media.MediaResolver
import io.element.android.x.matrix.room.MatrixRoom
@ -61,15 +62,30 @@ class MessageTimelineItemStateMapper( @@ -61,15 +62,30 @@ class MessageTimelineItemStateMapper(
)
}
private fun MatrixTimelineItem.Event.computeContent(): String? {
val messageType =
event.content().asMessage()?.msgtype()
return when (messageType) {
is MessageType.Emote -> messageType.content.body
is MessageType.Image -> messageType.content.body
is MessageType.Notice -> messageType.content.body
is MessageType.Text -> messageType.content.body
null -> null
private fun MatrixTimelineItem.Event.computeContent(): MessagesTimelineItemContent {
val content = event.content()
content.asUnableToDecrypt()?.let { encryptedMessage ->
return MessagesTimelineItemEncryptedContent(encryptedMessage)
}
if (content.isRedactedMessage()) {
return MessagesTimelineItemRedactedContent
}
val contentAsMessage = content.asMessage()
return when (val messageType = contentAsMessage?.msgtype()) {
is MessageType.Emote -> MessagesTimelineItemEmoteContent(
body = messageType.content.body,
formattedBody = messageType.content.formatted
)
is MessageType.Image -> MessagesTimelineItemUnknownContent
is MessageType.Notice -> MessagesTimelineItemNoticeContent(
body = messageType.content.body,
formattedBody = messageType.content.formatted
)
is MessageType.Text -> MessagesTimelineItemTextContent(
body = messageType.content.body,
formattedBody = messageType.content.formatted
)
null -> MessagesTimelineItemUnknownContent
}
}

62
features/messages/src/main/java/io/element/android/x/features/messages/MessagesScreen.kt

@ -36,9 +36,17 @@ import com.airbnb.mvrx.compose.mavericksViewModel @@ -36,9 +36,17 @@ import com.airbnb.mvrx.compose.mavericksViewModel
import io.element.android.x.core.data.LogCompositions
import io.element.android.x.core.data.StableCharSequence
import io.element.android.x.designsystem.components.avatar.AvatarData
import io.element.android.x.features.messages.components.MessagesTimelineItemEncryptedView
import io.element.android.x.features.messages.components.MessagesTimelineItemRedactedView
import io.element.android.x.features.messages.components.MessagesTimelineItemTextView
import io.element.android.x.features.messages.components.MessagesTimelineItemUnknownView
import io.element.android.x.features.messages.model.MessagesItemGroupPosition
import io.element.android.x.features.messages.model.MessagesTimelineItemState
import io.element.android.x.features.messages.model.MessagesViewState
import io.element.android.x.features.messages.model.content.MessagesTimelineItemEncryptedContent
import io.element.android.x.features.messages.model.content.MessagesTimelineItemRedactedContent
import io.element.android.x.features.messages.model.content.MessagesTimelineItemTextBasedContent
import io.element.android.x.features.messages.model.content.MessagesTimelineItemUnknownContent
import io.element.android.x.features.messages.textcomposer.MessageComposerViewModel
import io.element.android.x.features.messages.textcomposer.MessageComposerViewState
import io.element.android.x.textcomposer.TextComposer
@ -231,7 +239,32 @@ fun MessageEventRow( @@ -231,7 +239,32 @@ fun MessageEventRow(
Modifier.zIndex(1f)
)
}
MessageEventBubble(messageEvent, Modifier.zIndex(-1f))
MessageEventBubble(
groupPosition = messageEvent.groupPosition,
isMine = messageEvent.isMine,
modifier = Modifier
.zIndex(-1f)
) {
val contentModifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp)
when (messageEvent.content) {
is MessagesTimelineItemEncryptedContent -> MessagesTimelineItemEncryptedView(
content = messageEvent.content,
modifier = contentModifier
)
is MessagesTimelineItemRedactedContent -> MessagesTimelineItemRedactedView(
content = messageEvent.content,
modifier = contentModifier
)
is MessagesTimelineItemTextBasedContent -> MessagesTimelineItemTextView(
content = messageEvent.content,
modifier = contentModifier
)
is MessagesTimelineItemUnknownContent -> MessagesTimelineItemUnknownView(
content = messageEvent.content,
modifier = contentModifier
)
}
}
}
if (messageEvent.isMine) {
Spacer(modifier = Modifier.width(16.dp))
@ -267,10 +300,12 @@ private fun MessageSenderInformation( @@ -267,10 +300,12 @@ private fun MessageSenderInformation(
@Composable
fun MessageEventBubble(
messageEvent: MessagesTimelineItemState.MessageEvent,
groupPosition: MessagesItemGroupPosition,
isMine: Boolean,
modifier: Modifier = Modifier,
content: @Composable () -> Unit,
) {
fun MessagesTimelineItemState.MessageEvent.bubbleShape(): Shape {
fun bubbleShape(): Shape {
return when (groupPosition) {
MessagesItemGroupPosition.First -> if (isMine) {
RoundedCornerShape(BUBBLE_RADIUS, BUBBLE_RADIUS, 0.dp, BUBBLE_RADIUS)
@ -297,15 +332,15 @@ fun MessageEventBubble( @@ -297,15 +332,15 @@ fun MessageEventBubble(
}
}
fun Modifier.offsetForItem(messageEvent: MessagesTimelineItemState.MessageEvent): Modifier {
return if (messageEvent.isMine) {
fun Modifier.offsetForItem(): Modifier {
return if (isMine) {
offset(y = -(12.dp))
} else {
offset(x = 20.dp, y = -(12.dp))
}
}
val (backgroundBubbleColor, border) = if (messageEvent.isMine) {
val (backgroundBubbleColor, border) = if (isMine) {
Pair(MaterialTheme.colorScheme.surfaceVariant, null)
} else {
Pair(
@ -313,12 +348,11 @@ fun MessageEventBubble( @@ -313,12 +348,11 @@ fun MessageEventBubble(
BorderStroke(1.dp, MaterialTheme.colorScheme.surfaceVariant)
)
}
val bubbleShape = messageEvent.bubbleShape()
val bubbleShape = bubbleShape()
Surface(
modifier = modifier
.widthIn(min = 80.dp)
.offsetForItem(messageEvent)
.offsetForItem()
.clip(bubbleShape)
.clickable(
onClick = { },
@ -327,13 +361,9 @@ fun MessageEventBubble( @@ -327,13 +361,9 @@ fun MessageEventBubble(
),
color = backgroundBubbleColor,
shape = bubbleShape,
border = border
) {
Text(
modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp),
text = messageEvent.content ?: "",
)
}
border = border,
content = content
)
}
@Composable

20
features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemEncryptedView.kt

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
package io.element.android.x.features.messages.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Warning
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import io.element.android.x.features.messages.model.content.MessagesTimelineItemEncryptedContent
@Composable
fun MessagesTimelineItemEncryptedView(
content: MessagesTimelineItemEncryptedContent,
modifier: Modifier = Modifier
) {
MessagesTimelineItemInformativeView(
text = "Decryption error",
iconDescription = "Warning",
icon = Icons.Default.Warning,
modifier = modifier
)
}

41
features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemInformativeView.kt

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
package io.element.android.x.features.messages.components
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun MessagesTimelineItemInformativeView(
text: String,
iconDescription: String,
icon: ImageVector,
modifier: Modifier = Modifier
) {
Row(
modifier = modifier,
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = icon,
tint = MaterialTheme.colorScheme.secondary,
contentDescription = iconDescription
)
Spacer(modifier = Modifier.width(4.dp))
Text(
fontStyle = FontStyle.Italic,
color = MaterialTheme.colorScheme.secondary,
fontSize = 12.sp,
text = text
)
}
}

20
features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemRedactedView.kt

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
package io.element.android.x.features.messages.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import io.element.android.x.features.messages.model.content.MessagesTimelineItemRedactedContent
@Composable
fun MessagesTimelineItemRedactedView(
content: MessagesTimelineItemRedactedContent,
modifier: Modifier = Modifier
) {
MessagesTimelineItemInformativeView(
text = "This message has been deleted",
iconDescription = "Delete",
icon = Icons.Default.Delete,
modifier = modifier
)
}

17
features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemTextView.kt

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
package io.element.android.x.features.messages.components
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import io.element.android.x.features.messages.model.content.MessagesTimelineItemTextBasedContent
@Composable
fun MessagesTimelineItemTextView(
content: MessagesTimelineItemTextBasedContent,
modifier: Modifier = Modifier
) {
Box(modifier) {
Text(text = content.body)
}
}

20
features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemUnknownView.kt

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
package io.element.android.x.features.messages.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Info
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import io.element.android.x.features.messages.model.content.MessagesTimelineItemUnknownContent
@Composable
fun MessagesTimelineItemUnknownView(
content: MessagesTimelineItemUnknownContent,
modifier: Modifier = Modifier
) {
MessagesTimelineItemInformativeView(
text = "Event not handled by EAX",
iconDescription = "Info",
icon = Icons.Default.Info,
modifier = modifier
)
}

5
features/messages/src/main/java/io/element/android/x/features/messages/model/MessagesTimelineItemState.kt

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
package io.element.android.x.features.messages.model
import io.element.android.x.designsystem.components.avatar.AvatarData
import io.element.android.x.features.messages.model.content.MessagesTimelineItemContent
sealed interface MessagesTimelineItemState {
data class Virtual(
@ -12,10 +13,10 @@ sealed interface MessagesTimelineItemState { @@ -12,10 +13,10 @@ sealed interface MessagesTimelineItemState {
val senderId: String,
val senderDisplayName: String?,
val senderAvatar: AvatarData,
val content: String? = null,
val content: MessagesTimelineItemContent,
val sentTime: String = "",
val isMine: Boolean = false,
val groupPosition: MessagesItemGroupPosition = MessagesItemGroupPosition.None
val groupPosition: MessagesItemGroupPosition = MessagesItemGroupPosition.None,
) : MessagesTimelineItemState {
val showSenderInformation = groupPosition.isNew() && !isMine

3
features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemContent.kt

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
package io.element.android.x.features.messages.model.content
sealed interface MessagesTimelineItemContent

8
features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemEmoteContent.kt

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
package io.element.android.x.features.messages.model.content
import org.matrix.rustcomponents.sdk.FormattedBody
data class MessagesTimelineItemEmoteContent(
override val body: String,
override val formattedBody: FormattedBody?,
) : MessagesTimelineItemTextBasedContent

7
features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemEncryptedContent.kt

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
package io.element.android.x.features.messages.model.content
import org.matrix.rustcomponents.sdk.EncryptedMessage
data class MessagesTimelineItemEncryptedContent(
val encryptedMessage: EncryptedMessage
) : MessagesTimelineItemContent

8
features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemNoticeContent.kt

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
package io.element.android.x.features.messages.model.content
import org.matrix.rustcomponents.sdk.FormattedBody
data class MessagesTimelineItemNoticeContent(
override val body: String,
override val formattedBody: FormattedBody?,
) : MessagesTimelineItemTextBasedContent

3
features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemRedactedContent.kt

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
package io.element.android.x.features.messages.model.content
object MessagesTimelineItemRedactedContent : MessagesTimelineItemContent

8
features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemTextBasedContent.kt

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
package io.element.android.x.features.messages.model.content
import org.matrix.rustcomponents.sdk.FormattedBody
sealed interface MessagesTimelineItemTextBasedContent : MessagesTimelineItemContent {
val body: String
val formattedBody: FormattedBody?
}

8
features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemTextContent.kt

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
package io.element.android.x.features.messages.model.content
import org.matrix.rustcomponents.sdk.FormattedBody
data class MessagesTimelineItemTextContent(
override val body: String,
override val formattedBody: FormattedBody?,
) : MessagesTimelineItemTextBasedContent

3
features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemUnknownContent.kt

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
package io.element.android.x.features.messages.model.content
object MessagesTimelineItemUnknownContent : MessagesTimelineItemContent
Loading…
Cancel
Save