diff --git a/app/src/main/kotlin/dev/meloda/fast/presentation/MainActivity.kt b/app/src/main/kotlin/dev/meloda/fast/presentation/MainActivity.kt index 07d28e3c..bcc8ce50 100644 --- a/app/src/main/kotlin/dev/meloda/fast/presentation/MainActivity.kt +++ b/app/src/main/kotlin/dev/meloda/fast/presentation/MainActivity.kt @@ -24,6 +24,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalResources import androidx.core.content.ContextCompat import androidx.lifecycle.compose.LifecycleResumeEffect import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -88,7 +89,7 @@ class MainActivity : AppCompatActivity() { requestNotificationPermissions() setContent { - val context = LocalContext.current + val resources = LocalResources.current val userSettings: UserSettings = koinInject() val longPollController: LongPollController = koinInject() @@ -164,10 +165,10 @@ class MainActivity : AppCompatActivity() { } val deviceWidthDp = remember(true) { - context.resources.displayMetrics.widthPixels.pxToDp() + resources.displayMetrics.widthPixels.pxToDp() } val deviceHeightDp = remember(true) { - context.resources.displayMetrics.heightPixels.pxToDp() + resources.displayMetrics.heightPixels.pxToDp() } val deviceWidthSize by remember(deviceWidthDp) { diff --git a/core/data/src/main/kotlin/dev/meloda/fast/data/VkUsersMap.kt b/core/data/src/main/kotlin/dev/meloda/fast/data/VkUsersMap.kt index ba46bf11..73b1af67 100644 --- a/core/data/src/main/kotlin/dev/meloda/fast/data/VkUsersMap.kt +++ b/core/data/src/main/kotlin/dev/meloda/fast/data/VkUsersMap.kt @@ -36,7 +36,7 @@ class VkUsersMap( if (message.fromId > 0) map[message.fromId] else null - fun user(userid: Long): VkUser? = map[userId] + fun user(userId: Long): VkUser? = map[userId] companion object { diff --git a/core/data/src/main/kotlin/dev/meloda/fast/data/api/conversations/ConversationsRepositoryImpl.kt b/core/data/src/main/kotlin/dev/meloda/fast/data/api/conversations/ConversationsRepositoryImpl.kt index 28b1141d..0872cefa 100644 --- a/core/data/src/main/kotlin/dev/meloda/fast/data/api/conversations/ConversationsRepositoryImpl.kt +++ b/core/data/src/main/kotlin/dev/meloda/fast/data/api/conversations/ConversationsRepositoryImpl.kt @@ -75,7 +75,13 @@ class ConversationsRepositoryImpl( user = usersMap.messageUser(message), group = groupsMap.messageGroup(message), actionUser = usersMap.messageActionUser(message), - actionGroup = groupsMap.messageActionGroup(message) + actionGroup = groupsMap.messageActionGroup(message), + replyMessage = message.replyMessage?.copy( + user = usersMap.messageUser(message), + group = groupsMap.messageGroup(message), + actionUser = usersMap.messageActionUser(message), + actionGroup = groupsMap.messageActionGroup(message), + ) ).also { VkMemoryCache[message.id] = it } } item.conversation.asDomain(lastMessage).let { conversation -> diff --git a/core/data/src/main/kotlin/dev/meloda/fast/data/api/messages/MessagesRepositoryImpl.kt b/core/data/src/main/kotlin/dev/meloda/fast/data/api/messages/MessagesRepositoryImpl.kt index a5170aaa..37e84d96 100644 --- a/core/data/src/main/kotlin/dev/meloda/fast/data/api/messages/MessagesRepositoryImpl.kt +++ b/core/data/src/main/kotlin/dev/meloda/fast/data/api/messages/MessagesRepositoryImpl.kt @@ -90,7 +90,13 @@ class MessagesRepositoryImpl( user = usersMap.messageUser(message), group = groupsMap.messageGroup(message), actionUser = usersMap.messageActionUser(message), - actionGroup = groupsMap.messageActionGroup(message) + actionGroup = groupsMap.messageActionGroup(message), + replyMessage = message.replyMessage?.copy( + user = usersMap.messageUser(message), + group = groupsMap.messageGroup(message), + actionUser = usersMap.messageActionUser(message), + actionGroup = groupsMap.messageActionGroup(message), + ) ).also { VkMemoryCache[message.id] = it } } } @@ -159,7 +165,13 @@ class MessagesRepositoryImpl( user = usersMap.messageUser(message), group = groupsMap.messageGroup(message), actionUser = usersMap.messageActionUser(message), - actionGroup = groupsMap.messageActionGroup(message) + actionGroup = groupsMap.messageActionGroup(message), + replyMessage = message.replyMessage?.asDomain()?.copy( + user = usersMap.messageUser(message), + group = groupsMap.messageGroup(message), + actionUser = usersMap.messageActionUser(message), + actionGroup = groupsMap.messageActionGroup(message), + ) ) } diff --git a/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkMessageData.kt b/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkMessageData.kt index fa393cdc..d6ef7650 100644 --- a/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkMessageData.kt +++ b/core/model/src/main/kotlin/dev/meloda/fast/model/api/data/VkMessageData.kt @@ -105,7 +105,7 @@ fun VkMessageData.asDomain(): VkMessage = VkMessage( actionConversationMessageId = action?.conversationMessageId, actionMessage = action?.message, geoType = geo?.type, - isImportant = important ?: false, + isImportant = important == true, updateTime = updateTime, forwards = fwdMessages.orEmpty().map(VkMessageData::asDomain), attachments = attachments.map(VkAttachmentItemData::toDomain), diff --git a/core/model/src/main/kotlin/dev/meloda/fast/model/api/domain/VkMessage.kt b/core/model/src/main/kotlin/dev/meloda/fast/model/api/domain/VkMessage.kt index c86f0f46..cedf9a8e 100644 --- a/core/model/src/main/kotlin/dev/meloda/fast/model/api/domain/VkMessage.kt +++ b/core/model/src/main/kotlin/dev/meloda/fast/model/api/domain/VkMessage.kt @@ -35,7 +35,7 @@ data class VkMessage( val user: VkUser?, val group: VkGroupDomain?, val actionUser: VkUser?, - val actionGroup: VkGroupDomain? + val actionGroup: VkGroupDomain?, ) { fun isPeerChat() = peerId > 2_000_000_000 diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryViewModel.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryViewModel.kt index 67d55474..2eeb09f9 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryViewModel.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/MessagesHistoryViewModel.kt @@ -923,7 +923,9 @@ class MessagesHistoryViewModelImpl( isImportant = false, forwards = null, attachments = null, - replyMessage = null, + replyMessage = when { + else -> null + }, geoType = null, user = VkMemoryCache.getUser(UserConfig.userId), group = null, @@ -932,8 +934,6 @@ class MessagesHistoryViewModelImpl( isPinned = false, isSpam = false, pinnedAt = null, - - // TODO: 04-Apr-25, Danil Nikolaev: implement formatData = formatData, ) formatData = formatData.copy(items = emptyList()) diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/model/UiItem.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/model/UiItem.kt index 1588e6b2..80f3ae42 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/model/UiItem.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/model/UiItem.kt @@ -29,7 +29,10 @@ sealed class UiItem( val isSelected: Boolean, val isPinned: Boolean, val isImportant: Boolean, - val attachments: List? + val attachments: List?, + val replyCmId: Long?, + val replyTitle: String?, + val replySummary: String? ) : UiItem(id, cmId) data class ActionMessage( diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/IncomingMessageBubble.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/IncomingMessageBubble.kt index 09c720be..62adcd91 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/IncomingMessageBubble.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/IncomingMessageBubble.kt @@ -30,24 +30,26 @@ import coil.compose.rememberAsyncImagePainter import coil.imageLoader import dev.meloda.fast.messageshistory.model.UiItem import dev.meloda.fast.model.api.domain.VkAttachment -import dev.meloda.fast.ui.theme.LocalThemeConfig import dev.meloda.fast.ui.util.ImmutableList.Companion.toImmutableList @Composable fun IncomingMessageBubble( + enableAnimations: Boolean, modifier: Modifier = Modifier, message: UiItem.Message, onClick: (VkAttachment) -> Unit = {}, - onLongClick: (VkAttachment) -> Unit = {} + onLongClick: (VkAttachment) -> Unit = {}, + onReplyClick: () -> Unit = {} ) { val currentOnClick by rememberUpdatedState(onClick) val currentOnLongClick by rememberUpdatedState(onLongClick) + val currentOnReplyClick by rememberUpdatedState(onReplyClick) Row( modifier = modifier .fillMaxWidth() .then( - if (LocalThemeConfig.current.enableAnimations) Modifier.animateContentSize() + if (enableAnimations) Modifier.animateContentSize() else Modifier ), ) { @@ -103,8 +105,11 @@ fun IncomingMessageBubble( isImportant = message.isImportant, isSelected = message.isSelected, attachments = message.attachments?.toImmutableList(), + replyTitle = message.replyTitle, + replySummary = message.replySummary, onClick = currentOnClick, - onLongClick = currentOnLongClick + onLongClick = currentOnLongClick, + onReplyClick = currentOnReplyClick ) } } diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageBubble.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageBubble.kt index bba9f51c..de9b3562 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageBubble.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageBubble.kt @@ -7,7 +7,9 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme @@ -25,11 +27,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import dev.meloda.fast.messageshistory.model.SendingStatus import dev.meloda.fast.messageshistory.presentation.attachments.Attachments +import dev.meloda.fast.messageshistory.presentation.attachments.Reply import dev.meloda.fast.model.api.domain.VkAttachment import dev.meloda.fast.ui.theme.LocalThemeConfig import dev.meloda.fast.ui.util.ImmutableList @@ -48,9 +52,14 @@ fun MessageBubble( isImportant: Boolean, isSelected: Boolean, attachments: ImmutableList?, + replyTitle: String?, + replySummary: String? = null, onClick: (VkAttachment) -> Unit = {}, - onLongClick: (VkAttachment) -> Unit = {} + onLongClick: (VkAttachment) -> Unit = {}, + onReplyClick: () -> Unit = {} ) { + val density = LocalDensity.current + val currentOnClick by rememberUpdatedState(onClick) val currentOnLongClick by rememberUpdatedState(onLongClick) @@ -60,6 +69,11 @@ fun MessageBubble( } else { MaterialTheme.colorScheme.primaryContainer } + val replyBackgroundColor = if (!isOut) { + MaterialTheme.colorScheme.primaryContainer + } else { + MaterialTheme.colorScheme.inversePrimary + } val contentColor = if (!isOut) { MaterialTheme.colorScheme.onSurface @@ -101,8 +115,38 @@ fun MessageBubble( } } + var containerWidth by remember { + mutableIntStateOf(0) + } + CompositionLocalProvider(LocalContentColor provides contentColor) { - Column { + Column( + modifier = modifier + .wrapContentWidth() + .onGloballyPositioned { + containerWidth = it.size.width + } + ) { + if (replyTitle != null) { + Reply( + modifier = Modifier + .padding(if (attachments == null || text != null) 0.dp else 4.dp) + .width(with(density) { containerWidth.toDp() }), + bottomPadding = if (attachments == null || text != null) 0.dp else 4.dp, + shape = RoundedCornerShape( + topStart = 16.dp, + topEnd = 16.dp, + bottomStart = if (attachments == null || text != null) 0.dp else 16.dp, + bottomEnd = if (attachments == null || text != null) 0.dp else 16.dp + ), + onClick = onReplyClick, + title = replyTitle, + summary = replySummary, + backgroundColor = backgroundColor, + innerBackgroundColor = replyBackgroundColor + ) + } + if (shouldShowBubble) { Box( modifier = modifier @@ -111,18 +155,19 @@ fun MessageBubble( } .widthIn(min = if (shouldFill) attachmentsContainerWidth.dp else 56.dp) .clip( - if (attachments == null) RoundedCornerShape(24.dp) - else RoundedCornerShape( - topStart = 24.dp, - topEnd = 24.dp, - bottomStart = 0.dp, - bottomEnd = 0.dp + RoundedCornerShape( + topStart = if (replyTitle == null) 24.dp else 0.dp, + topEnd = if (replyTitle == null) 24.dp else 0.dp, + bottomStart = if (attachments != null) 0.dp else 24.dp, + bottomEnd = if (attachments != null) 0.dp else 24.dp ) ) .background(backgroundColor) .padding( - horizontal = 8.dp, - vertical = 6.dp + start = 8.dp, + end = 8.dp, + top = if (replyTitle != null) 0.dp else 6.dp, + bottom = if (replyTitle != null) 4.dp else 6.dp ) .then(if (theme.enableAnimations) Modifier.animateContentSize() else Modifier), ) { @@ -223,6 +268,10 @@ private fun Bubble() { isPinned = true, isImportant = true, isSelected = false, - attachments = emptyImmutableList() + attachments = emptyImmutableList(), + replyTitle = "Danil Nikolaev", + replySummary = "2 photos", + onClick = {}, + onLongClick = {}, ) } diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageText.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageText.kt index 6ff7fd33..d542f5be 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageText.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessageText.kt @@ -17,22 +17,22 @@ fun MessageTextContainer( isOut: Boolean, isSelected: Boolean, ) { - if (text != null) { - if (isSelected) { - SelectionContainer { - MessageText( - modifier = modifier, - text = text, - isOut = isOut, - ) - } - } else { + if (text == null) return + + if (isSelected) { + SelectionContainer { MessageText( modifier = modifier, text = text, isOut = isOut, ) } + } else { + MessageText( + modifier = modifier, + text = text, + isOut = isOut, + ) } } diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessagesList.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessagesList.kt index 74be64a1..ff19d0ca 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessagesList.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/MessagesList.kt @@ -209,13 +209,18 @@ fun MessagesList( ) else Modifier ), + enableAnimations = theme.enableAnimations, message = item, onClick = { attachment -> - onAttachmentClick(item, attachment) }, onLongClick = { attachment -> onAttachmentLongClick(item, attachment) + }, + onReplyClick = { + if (item.replyCmId != null) { + onRequestScrollToCmId(item.replyCmId) + } } ) } else { @@ -230,12 +235,18 @@ fun MessagesList( ) else Modifier ), + enableAnimations = theme.enableAnimations, message = item, onClick = { attachment -> onAttachmentClick(item, attachment) }, onLongClick = { attachment -> onAttachmentLongClick(item, attachment) + }, + onReplyClick = { + if (item.replyCmId != null) { + onRequestScrollToCmId(item.replyCmId) + } } ) } diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/OutgoingMessageBubble.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/OutgoingMessageBubble.kt index d6c1f213..c8f4e953 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/OutgoingMessageBubble.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/OutgoingMessageBubble.kt @@ -2,42 +2,48 @@ package dev.meloda.fast.messageshistory.presentation import androidx.compose.animation.animateContentSize import androidx.compose.foundation.layout.Arrangement -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.runtime.getValue +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import dev.meloda.fast.messageshistory.model.UiItem import dev.meloda.fast.model.api.domain.VkAttachment -import dev.meloda.fast.ui.theme.LocalThemeConfig import dev.meloda.fast.ui.util.ImmutableList.Companion.toImmutableList @Composable fun OutgoingMessageBubble( modifier: Modifier = Modifier, + enableAnimations: Boolean, message: UiItem.Message, onClick: (VkAttachment) -> Unit = {}, - onLongClick: (VkAttachment) -> Unit = {} + onLongClick: (VkAttachment) -> Unit = {}, + onReplyClick: () -> Unit = {} ) { + val currentOnClick by rememberUpdatedState(onClick) + val currentOnLongClick by rememberUpdatedState(onLongClick) + val currentOnReplyClick by rememberUpdatedState(onReplyClick) + Row( modifier = modifier .fillMaxWidth() .then( - if (LocalThemeConfig.current.enableAnimations) Modifier.animateContentSize() + if (enableAnimations) Modifier.animateContentSize() else Modifier ), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End ) { - Column( + Row( modifier = Modifier .padding(end = 16.dp) .fillMaxWidth(0.85f), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.End, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.End ) { MessageBubble( modifier = Modifier, @@ -51,8 +57,11 @@ fun OutgoingMessageBubble( isImportant = message.isImportant, isSelected = message.isSelected, attachments = message.attachments?.toImmutableList(), - onClick = onClick, - onLongClick = onLongClick + replyTitle = message.replyTitle, + replySummary = message.replySummary, + onClick = currentOnClick, + onLongClick = currentOnLongClick, + onReplyClick = currentOnReplyClick ) } } diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Reply.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Reply.kt new file mode 100644 index 00000000..b1cd61b3 --- /dev/null +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/presentation/attachments/Reply.kt @@ -0,0 +1,128 @@ +package dev.meloda.fast.messageshistory.presentation.attachments + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +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.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.surfaceColorAtElevation +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +@Composable +fun Reply( + modifier: Modifier = Modifier, + bottomPadding: Dp, + shape: Shape, + onClick: () -> Unit, + backgroundColor: Color, + innerBackgroundColor: Color, + title: String, + summary: String? +) { + Box( + modifier = modifier + .background( + color = backgroundColor, + shape = shape + ) + .height(40.dp) + .padding( + top = 4.dp, + start = 4.dp, + end = 4.dp, + bottom = bottomPadding + ) + ) { + + Row( + modifier = Modifier + .clip(RoundedCornerShape(12.dp)) + .clickable(onClick = onClick) + .fillMaxSize() + .background(innerBackgroundColor) + ) { + Box( + modifier = Modifier + .width(3.dp) + .fillMaxHeight() + .background(MaterialTheme.colorScheme.onBackground) + ) + + Spacer(modifier = Modifier.width(6.dp)) + + Column( + modifier = Modifier.fillMaxHeight(), + verticalArrangement = Arrangement.Center + ) { + Text( + text = title, + style = MaterialTheme.typography.labelMedium, + maxLines = 1 + ) + + summary?.let { + Text( + text = summary, + style = MaterialTheme.typography.labelSmall, + maxLines = 1 + ) + } + } + } + } +} + +@Composable +private fun ReplyBasePreview( + backgroundColor: Color, + innerBackgroundColor: Color +) { + Reply( + modifier = Modifier.width(120.dp), + shape = RoundedCornerShape( + topStart = 12.dp, + topEnd = 12.dp + ), + onClick = {}, + title = "Danil Nikolaev", + summary = "2 photos", + backgroundColor = backgroundColor, + innerBackgroundColor = innerBackgroundColor, + bottomPadding = 0.dp + ) +} + +@Preview +@Composable +private fun IncomingReplyPreview() { + ReplyBasePreview( + backgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp), + innerBackgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(20.dp) + ) +} + +@Preview +@Composable +private fun OutgoingReplyPreview() { + ReplyBasePreview( + backgroundColor = MaterialTheme.colorScheme.primaryContainer, + innerBackgroundColor = MaterialTheme.colorScheme.inversePrimary + ) +} diff --git a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/util/MessageMapper.kt b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/util/MessageMapper.kt index 508fc13b..c49d8b9c 100644 --- a/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/util/MessageMapper.kt +++ b/feature/messageshistory/src/main/kotlin/dev/meloda/fast/messageshistory/util/MessageMapper.kt @@ -57,6 +57,19 @@ fun VkMessage.extractTitle(): String = when { else -> throw IllegalStateException("Message is not from user nor group. fromId: $fromId") } +fun VkMessage.extractReplyTitle(): String? = replyMessage?.extractTitle() + +// TODO: 24-Jun-25, Danil Nikolaev: improve +fun VkMessage.extractReplySummary(): String? = when (val message = replyMessage) { + null -> null + else -> { + when { + message.text != null -> message.text + else -> null + } + } +} + fun VkConversation.extractAvatar(): UiImage = when (peerType) { PeerType.USER -> { if (isAccount(id)) null @@ -144,7 +157,10 @@ fun VkMessage.asPresentation( isSelected = isSelected, isPinned = isPinned, isImportant = isImportant, - attachments = attachments?.ifEmpty { null } + attachments = attachments?.ifEmpty { null }, + replyCmId = replyMessage?.cmId, + replyTitle = extractReplyTitle(), + replySummary = extractReplySummary() ) }