Прочтение

This commit is contained in:
Халимов Рустам
2026-04-14 15:09:44 +03:00
parent 8165b74e43
commit 118f8b8971
24 changed files with 422 additions and 64 deletions
@@ -16,7 +16,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.unit.dp
import chats.presentation.components.MediaPicker
import chats.presentation.components.MessageBubble
@@ -28,7 +31,7 @@ import java.io.File
import ru.knot.messager.R
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class, androidx.compose.ui.ExperimentalComposeUiApi::class, androidx.compose.foundation.ExperimentalFoundationApi::class)
@Composable
fun ChatDetailScreen(
chatId: String,
@@ -45,6 +48,9 @@ fun ChatDetailScreen(
var isEmojiPickerVisible by remember { mutableStateOf(false) }
var isRecording by remember { mutableStateOf(false) }
val keyboardController = LocalSoftwareKeyboardController.current
val focusManager = LocalFocusManager.current
var autoPlayingMessageId by remember { mutableStateOf<String?>(null) }
var currentPlaybackSpeed by remember { mutableFloatStateOf(1.0f) }
@@ -89,10 +95,27 @@ fun ChatDetailScreen(
viewModel.setChatId(chatId)
}
// Автопрокрутка к последнему сообщению
// Автопрокрутка к первому непрочитанному или к самому низу
LaunchedEffect(state.initialScrollIndex) {
state.initialScrollIndex?.let { index ->
if (index < state.messages.size) {
listState.scrollToItem(index)
}
}
}
// Автопрокрутка к новому сообщению, если мы внизу
LaunchedEffect(state.messages.size) {
if (state.messages.isNotEmpty()) {
listState.animateScrollToItem(state.messages.size - 1)
val isAtBottom = listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index == state.messages.size - 2
if (isAtBottom || state.initialScrollIndex == null) {
listState.animateScrollToItem(state.messages.size - 1)
}
// Если пришли новые сообщения и мы их видим — помечаем как прочитанные
if (isAtBottom) {
viewModel.markAsRead()
}
}
}
@@ -141,6 +164,7 @@ fun ChatDetailScreen(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.imePadding()
) {
// Список сообщений
Box(
@@ -193,7 +217,15 @@ fun ChatDetailScreen(
.padding(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
IconButton(onClick = { isEmojiPickerVisible = !isEmojiPickerVisible }) {
IconButton(
onClick = {
isEmojiPickerVisible = !isEmojiPickerVisible
if (isEmojiPickerVisible) {
keyboardController?.hide()
focusManager.clearFocus()
}
}
) {
Icon(
Icons.Default.EmojiEmotions,
contentDescription = stringResource(R.string.emoji),
@@ -207,7 +239,13 @@ fun ChatDetailScreen(
TextField(
value = textInput,
onValueChange = { textInput = it },
modifier = Modifier.weight(1f),
modifier = Modifier
.weight(1f)
.onFocusChanged {
if (it.isFocused) {
isEmojiPickerVisible = false
}
},
placeholder = { Text(stringResource(R.string.message_placeholder)) },
maxLines = 4,
colors = TextFieldDefaults.colors(