android: add reply and forwarded blocks to chat bubbles
Some checks failed
CI / test (push) Failing after 2m9s

This commit is contained in:
Codex
2026-03-09 13:57:41 +03:00
parent 98e8ac8dfb
commit ade92e4a86
3 changed files with 49 additions and 8 deletions

View File

@@ -195,3 +195,8 @@
- Added Room self-relation in `MessageLocalModel` to resolve reply preview fallback from referenced message.
- Updated message mappers and repository/realtime temporary entity creation for new model fields.
- Bumped Room schema version to `7`.
### Step 31 - Chat UI / reply-forward bubble blocks
- Added inline forwarded header rendering in message bubbles with display-name fallback.
- Added inline reply preview block in message bubbles (author + snippet) based on new preview fields/fallbacks.
- Updated Telegram UI batch-2 checklist items for reply-preview and forwarded header.

View File

@@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
@@ -399,16 +400,51 @@ private fun MessageBubble(
fontWeight = FontWeight.SemiBold,
)
}
if (message.forwardedFromMessageId != null || !message.forwardedFromDisplayName.isNullOrBlank()) {
Text(
text = "Forwarded from ${message.forwardedFromDisplayName?.takeIf { it.isNotBlank() } ?: "#${message.forwardedFromMessageId ?: "?"}"}",
style = MaterialTheme.typography.labelSmall,
color = if (isOutgoing) {
MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.78f)
} else {
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.78f)
},
)
}
if (message.replyToMessageId != null) {
val replyAuthor = message.replyPreviewSenderName?.takeIf { it.isNotBlank() }
?: "#${message.replyToMessageId}"
val replySnippet = message.replyPreviewText?.takeIf { it.isNotBlank() } ?: "[media]"
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp)
.background(
color = if (isOutgoing) {
MaterialTheme.colorScheme.onPrimaryContainer.copy(alpha = 0.16f)
} else {
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.16f)
},
shape = RoundedCornerShape(8.dp),
)
.padding(horizontal = 8.dp, vertical = 6.dp),
) {
Text(
text = replyAuthor,
style = MaterialTheme.typography.labelSmall,
fontWeight = FontWeight.SemiBold,
)
Text(
text = replySnippet,
style = MaterialTheme.typography.labelSmall,
maxLines = 2,
)
}
}
Text(
text = message.text ?: "[${message.type}]",
style = MaterialTheme.typography.bodyMedium,
)
if (message.forwardedFromMessageId != null) {
Text(
text = "Forwarded from #${message.forwardedFromMessageId}",
style = MaterialTheme.typography.labelSmall,
)
}
if (reactions.isNotEmpty()) {
Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
reactions.forEach { reaction ->

View File

@@ -11,8 +11,8 @@
- [ ] Иконка emoji слева, поле ввода, скрепка, кнопка отправки/голосового.
- [ ] Корректные отступы от nav bar + IME.
- [ ] Сообщения вход/выход: плотные пузыри, время и delivery статус внизу справа.
- [ ] Reply-preview внутри outgoing bubble (вертикальная полоска, автор, snippet).
- [ ] Forwarded header в сообщении ("Переслано от ...") + мини-аватар.
- [x] Reply-preview внутри outgoing bubble (вертикальная полоска, автор, snippet).
- [x] Forwarded header в сообщении ("Переслано от ...") + мини-аватар.
- [ ] Поддержка chat wallpaper (обои в фоне, читабельный контраст поверх).
## P0 — Voice/Audio Message UI