Forward: фикс размера пузыря и отправки. Дубли дат убраны.
- Forward пузырь подстраивается под размер контента (как Telegram) - Длинные имена обрезаются "Forwarded from Alex M..." вместо растяжения - Исправлена отправка forward — consumeForwardMessagesForChat при открытии чата - Floating date header показывается только при активном скролле (убраны дубли дат) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1388,6 +1388,14 @@ fun ChatDetailScreen(
|
|||||||
com.rosetta.messenger.ui.components.EmojiCache.preload(context)
|
com.rosetta.messenger.ui.components.EmojiCache.preload(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Consume pending forward messages for this chat
|
||||||
|
LaunchedEffect(user.publicKey, forwardTrigger) {
|
||||||
|
val pendingForwards = ForwardManager.consumeForwardMessagesForChat(user.publicKey)
|
||||||
|
if (pendingForwards.isNotEmpty()) {
|
||||||
|
viewModel.sendForwardDirectly(user.publicKey, pendingForwards)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Отмечаем сообщения как прочитанные только когда экран активен (RESUMED)
|
// Отмечаем сообщения как прочитанные только когда экран активен (RESUMED)
|
||||||
LaunchedEffect(messages, isScreenActive) {
|
LaunchedEffect(messages, isScreenActive) {
|
||||||
if (messages.isNotEmpty() && isScreenActive) {
|
if (messages.isNotEmpty() && isScreenActive) {
|
||||||
@@ -1440,8 +1448,7 @@ fun ChatDetailScreen(
|
|||||||
messagesWithDates.isNotEmpty() &&
|
messagesWithDates.isNotEmpty() &&
|
||||||
floatingDateText != null &&
|
floatingDateText != null &&
|
||||||
!isAtBottom &&
|
!isAtBottom &&
|
||||||
(listState.isScrollInProgress ||
|
listState.isScrollInProgress
|
||||||
listState.firstVisibleItemIndex > 0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2383,6 +2383,7 @@ fun ForwardedMessagesBubble(
|
|||||||
onMentionClick: (username: String) -> Unit = {},
|
onMentionClick: (username: String) -> Unit = {},
|
||||||
onTextSpanPressStart: (() -> Unit)? = null
|
onTextSpanPressStart: (() -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
|
val configuration = androidx.compose.ui.platform.LocalConfiguration.current
|
||||||
val backgroundColor =
|
val backgroundColor =
|
||||||
if (isOutgoing) Color.Black.copy(alpha = 0.1f)
|
if (isOutgoing) Color.Black.copy(alpha = 0.1f)
|
||||||
else Color.Black.copy(alpha = 0.05f)
|
else Color.Black.copy(alpha = 0.05f)
|
||||||
@@ -2406,9 +2407,11 @@ fun ForwardedMessagesBubble(
|
|||||||
}.toMap()
|
}.toMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val maxBubbleWidth = (configuration.screenWidthDp * 0.65f).dp
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.widthIn(max = maxBubbleWidth)
|
||||||
.clip(RoundedCornerShape(4.dp))
|
.clip(RoundedCornerShape(4.dp))
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
) {
|
) {
|
||||||
@@ -2439,29 +2442,24 @@ fun ForwardedMessagesBubble(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "Forwarded from [Name]" — clickable to open profile
|
// "Forwarded from [Name]" — clickable to open profile
|
||||||
Row(
|
Text(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
text = buildAnnotatedString {
|
||||||
|
withStyle(SpanStyle(
|
||||||
|
color = nameColor.copy(alpha = 0.7f),
|
||||||
|
fontWeight = FontWeight.Normal
|
||||||
|
)) { append("Forwarded from ") }
|
||||||
|
withStyle(SpanStyle(
|
||||||
|
color = nameColor,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)) { append(fwd.forwardedFromName.ifEmpty { "User" }) }
|
||||||
|
},
|
||||||
|
fontSize = 13.sp,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier.clickable(enabled = fwd.senderPublicKey.isNotEmpty()) {
|
modifier = Modifier.clickable(enabled = fwd.senderPublicKey.isNotEmpty()) {
|
||||||
onForwardedSenderClick(fwd.senderPublicKey)
|
onForwardedSenderClick(fwd.senderPublicKey)
|
||||||
}
|
}
|
||||||
) {
|
)
|
||||||
Text(
|
|
||||||
text = "Forwarded from ",
|
|
||||||
color = nameColor.copy(alpha = 0.7f),
|
|
||||||
fontSize = 13.sp,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
maxLines = 1
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = fwd.forwardedFromName.ifEmpty { "User" },
|
|
||||||
color = nameColor,
|
|
||||||
fontSize = 13.sp,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
modifier = Modifier.weight(1f, fill = false)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attachments (images) — before text (text acts as caption)
|
// Attachments (images) — before text (text acts as caption)
|
||||||
val imageAttachments = fwd.attachments.filter { it.type == AttachmentType.IMAGE }
|
val imageAttachments = fwd.attachments.filter { it.type == AttachmentType.IMAGE }
|
||||||
@@ -2611,10 +2609,11 @@ private fun ForwardedImagePreview(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val maxPhotoWidthDp = TelegramBubbleSpec.maxPhotoWidth(configuration.screenWidthDp).dp
|
// Forwarded images use smaller max size to fit inside the forward bubble
|
||||||
val minPhotoWidthDp = TelegramBubbleSpec.minPhotoWidth.dp
|
val maxPhotoWidthDp = (configuration.screenWidthDp * 0.55f).toInt().dp
|
||||||
val minPhotoHeightDp = TelegramBubbleSpec.minPhotoHeight.dp
|
val minPhotoWidthDp = 100.dp
|
||||||
val maxPhotoHeightDp = TelegramBubbleSpec.maxPhotoHeight.dp
|
val minPhotoHeightDp = 80.dp
|
||||||
|
val maxPhotoHeightDp = 280.dp
|
||||||
val (previewWidth, previewHeight) =
|
val (previewWidth, previewHeight) =
|
||||||
remember(
|
remember(
|
||||||
attachment.width,
|
attachment.width,
|
||||||
|
|||||||
Reference in New Issue
Block a user