Добавлено автоматическое прокручивание к новым сообщениям и кнопка "Прокрутить вниз" в ChatDetailScreen
This commit is contained in:
@@ -8,6 +8,7 @@ import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
@@ -721,6 +722,15 @@ fun ChatDetailScreen(
|
||||
.maxWithOrNull(compareBy<ChatMessage>({ it.timestamp.time }, { it.id }))
|
||||
?.id
|
||||
var lastNewestMessageId by remember { mutableStateOf<String?>(null) }
|
||||
val isAtBottom by remember(listState) {
|
||||
derivedStateOf {
|
||||
listState.firstVisibleItemIndex == 0 &&
|
||||
listState.firstVisibleItemScrollOffset <= 12
|
||||
}
|
||||
}
|
||||
val showScrollToBottomButton by remember(messagesWithDates, isAtBottom) {
|
||||
derivedStateOf { messagesWithDates.isNotEmpty() && !isAtBottom }
|
||||
}
|
||||
|
||||
// Telegram-style: Прокрутка ТОЛЬКО при новых сообщениях (не при пагинации)
|
||||
// 🔥 Скроллим только если изменился ID самого нового сообщения
|
||||
@@ -730,10 +740,15 @@ fun ChatDetailScreen(
|
||||
lastNewestMessageId != null &&
|
||||
newestMessageId != lastNewestMessageId
|
||||
) {
|
||||
// Новое сообщение пришло - скроллим вниз
|
||||
delay(50) // Debounce - ждём стабилизации
|
||||
listState.animateScrollToItem(0)
|
||||
wasManualScroll = false
|
||||
val newestMessage = messages.firstOrNull { it.id == newestMessageId }
|
||||
val isOwnOutgoingMessage = newestMessage?.isOutgoing == true
|
||||
val shouldAutoScroll = isAtBottom || isOwnOutgoingMessage
|
||||
|
||||
if (shouldAutoScroll) {
|
||||
delay(50) // Debounce - ждём стабилизации
|
||||
listState.animateScrollToItem(0)
|
||||
wasManualScroll = false
|
||||
}
|
||||
}
|
||||
lastNewestMessageId = newestMessageId
|
||||
}
|
||||
@@ -2465,6 +2480,50 @@ fun ChatDetailScreen(
|
||||
}
|
||||
} // Конец Column внутри Scaffold content
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = showScrollToBottomButton && !isLoading && !isSelectionMode,
|
||||
enter = fadeIn(animationSpec = tween(140)) + expandVertically(expandFrom = Alignment.Bottom),
|
||||
exit = fadeOut(animationSpec = tween(120)) + shrinkVertically(shrinkTowards = Alignment.Bottom),
|
||||
modifier =
|
||||
Modifier.align(Alignment.BottomEnd)
|
||||
.padding(
|
||||
end = 14.dp,
|
||||
bottom = if (isSystemAccount) 24.dp else 86.dp
|
||||
)
|
||||
) {
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.size(38.dp)
|
||||
.clip(CircleShape)
|
||||
.background(
|
||||
if (isDarkTheme) Color(0xFF2D2E31)
|
||||
else Color.White
|
||||
)
|
||||
.clickable(
|
||||
indication = null,
|
||||
interactionSource =
|
||||
remember {
|
||||
MutableInteractionSource()
|
||||
}
|
||||
) {
|
||||
scope.launch {
|
||||
listState.animateScrollToItem(0)
|
||||
wasManualScroll = false
|
||||
}
|
||||
},
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
imageVector = TablerIcons.ChevronDown,
|
||||
contentDescription = "Scroll to bottom",
|
||||
tint =
|
||||
if (isDarkTheme) Color(0xFFF2F2F3)
|
||||
else Color(0xFF2D3138),
|
||||
modifier = Modifier.size(21.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 📎 Media Picker — new tab-based ChatAttachAlert (Telegram-style)
|
||||
// Feature flag: set USE_NEW_ATTACH_ALERT to false to use old MediaPickerBottomSheet
|
||||
val USE_NEW_ATTACH_ALERT = true
|
||||
|
||||
Reference in New Issue
Block a user