feat: Add timestamp and message status to MessageBubble and ImageAttachment components

This commit is contained in:
k1ngsterr1
2026-01-25 02:54:56 +05:00
parent c8214cdfa3
commit 3608af99c3
2 changed files with 102 additions and 5 deletions

View File

@@ -3,13 +3,14 @@ package com.rosetta.messenger.ui.chats.components
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.util.Base64
import android.util.Log
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
@@ -23,18 +24,23 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.geometry.CornerRadius
import compose.icons.TablerIcons
import compose.icons.tablericons.*
import com.rosetta.messenger.crypto.CryptoManager
import com.rosetta.messenger.crypto.MessageCrypto
import com.rosetta.messenger.network.AttachmentType
import com.rosetta.messenger.network.MessageAttachment
import com.rosetta.messenger.network.TransportManager
import com.rosetta.messenger.repository.AvatarRepository
import com.rosetta.messenger.ui.chats.models.MessageStatus
import com.rosetta.messenger.ui.onboarding.PrimaryBlue
import com.rosetta.messenger.utils.AvatarFileManager
import com.vanniktech.blurhash.BlurHash
@@ -67,6 +73,8 @@ fun MessageAttachments(
isOutgoing: Boolean,
isDarkTheme: Boolean,
senderPublicKey: String,
timestamp: java.util.Date,
messageStatus: MessageStatus = MessageStatus.READ,
avatarRepository: AvatarRepository? = null,
modifier: Modifier = Modifier
) {
@@ -84,7 +92,9 @@ fun MessageAttachments(
chachaKey = chachaKey,
privateKey = privateKey,
isOutgoing = isOutgoing,
isDarkTheme = isDarkTheme
isDarkTheme = isDarkTheme,
timestamp = timestamp,
messageStatus = messageStatus
)
}
AttachmentType.FILE -> {
@@ -124,7 +134,9 @@ fun ImageAttachment(
chachaKey: String,
privateKey: String,
isOutgoing: Boolean,
isDarkTheme: Boolean
isDarkTheme: Boolean,
timestamp: java.util.Date,
messageStatus: MessageStatus = MessageStatus.READ
) {
val context = LocalContext.current
val scope = rememberCoroutineScope()
@@ -224,12 +236,20 @@ fun ImageAttachment(
}
}
// Telegram-style image с blurhash placeholder
// Telegram-style image с blurhash placeholder и тонким бордером
val timeFormat = remember { java.text.SimpleDateFormat("HH:mm", java.util.Locale.getDefault()) }
val borderColor = if (isOutgoing) {
Color.White.copy(alpha = 0.15f)
} else {
if (isDarkTheme) Color.White.copy(alpha = 0.1f) else Color.Black.copy(alpha = 0.08f)
}
Box(
modifier = Modifier
.widthIn(min = 180.dp, max = 260.dp)
.heightIn(min = 140.dp, max = 300.dp)
.clip(RoundedCornerShape(12.dp))
.background(Color.Transparent)
.clickable {
when (downloadStatus) {
DownloadStatus.NOT_DOWNLOADED -> download()
@@ -272,6 +292,81 @@ fun ImageAttachment(
}
}
// Тонкий бордер как в Telegram (просто через border modifier)
Box(
modifier = Modifier
.fillMaxSize()
.border(
width = 1.dp,
color = borderColor,
shape = RoundedCornerShape(12.dp)
)
)
// Время в правом нижнем углу (только если изображение загружено)
if (downloadStatus == DownloadStatus.DOWNLOADED) {
Box(
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(8.dp)
.background(
Color.Black.copy(alpha = 0.5f),
shape = RoundedCornerShape(10.dp)
)
.padding(horizontal = 6.dp, vertical = 3.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(2.dp)
) {
Text(
text = timeFormat.format(timestamp),
color = Color.White,
fontSize = 11.sp,
fontWeight = FontWeight.Medium
)
if (isOutgoing) {
// Статус доставки для исходящих
when (messageStatus) {
MessageStatus.SENDING -> {
Icon(
compose.icons.TablerIcons.Clock,
contentDescription = null,
tint = Color.White.copy(alpha = 0.7f),
modifier = Modifier.size(14.dp)
)
}
MessageStatus.SENT -> {
Icon(
compose.icons.TablerIcons.Check,
contentDescription = null,
tint = Color.White.copy(alpha = 0.7f),
modifier = Modifier.size(14.dp)
)
}
MessageStatus.DELIVERED -> {
Icon(
compose.icons.TablerIcons.Checks,
contentDescription = null,
tint = Color.White.copy(alpha = 0.7f),
modifier = Modifier.size(14.dp)
)
}
MessageStatus.READ -> {
Icon(
compose.icons.TablerIcons.Checks,
contentDescription = null,
tint = Color(0xFF4FC3F7),
modifier = Modifier.size(14.dp)
)
}
else -> {}
}
}
}
}
}
// Оверлей для статуса скачивания
if (downloadStatus != DownloadStatus.DOWNLOADED) {
Box(

View File

@@ -345,7 +345,9 @@ fun MessageBubble(
privateKey = privateKey,
isOutgoing = message.isOutgoing,
isDarkTheme = isDarkTheme,
senderPublicKey = senderPublicKey
senderPublicKey = senderPublicKey,
timestamp = message.timestamp,
messageStatus = message.status
)
if (message.text.isNotEmpty()) {
Spacer(modifier = Modifier.height(8.dp))