This commit is contained in:
Халимов Рустам
2026-04-14 10:48:07 +03:00
parent dc051fa9ae
commit d8b0d86534
19 changed files with 504 additions and 184 deletions
@@ -20,6 +20,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import chats.presentation.components.EmojiPicker
import chats.presentation.components.MessageBubble
import core.presentation.components.AppAvatar
import core.utils.VoiceRecorder
import core.utils.copyUriToFile
import java.io.File
@@ -67,14 +68,22 @@ fun ChatDetailScreen(
topBar = {
TopAppBar(
title = {
Column {
Text(chatName, style = MaterialTheme.typography.titleMedium)
if (state.isTyping) {
Text(
stringResource(R.string.typing),
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.primary
)
Row(verticalAlignment = Alignment.CenterVertically) {
AppAvatar(
url = state.chatAvatar,
name = state.chatName ?: chatName,
size = 36.dp,
modifier = Modifier.padding(end = 8.dp)
)
Column {
Text(state.chatName ?: chatName, style = MaterialTheme.typography.titleMedium)
if (state.isTyping) {
Text(
stringResource(R.string.typing),
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.primary
)
}
}
}
},
@@ -116,9 +125,12 @@ fun ChatDetailScreen(
items(state.messages) { message ->
MessageBubble(
message = message,
isCurrentUser = message.senderId == viewModel.getCurrentUserId()
isCurrentUser = message.senderId == viewModel.getCurrentUserId(),
senderAvatar = if (message.senderId == viewModel.getCurrentUserId()) null else message.senderAvatar,
onReactionClick = { emoji -> viewModel.addReaction(message.id, emoji) }
)
}
}
if (state.isLoading) {
@@ -19,6 +19,8 @@ import javax.inject.Inject
data class ChatDetailState(
val messages: List<Message> = emptyList(),
val chatName: String? = null,
val chatAvatar: String? = null,
val isLoading: Boolean = false,
val isTyping: Boolean = false,
val typingUser: String? = null,
@@ -56,10 +58,25 @@ class ChatDetailViewModel @Inject constructor(
fun setChatId(chatId: String) {
currentChatId = chatId
loadChatInfo(chatId)
loadMessages(chatId)
observeSignalREvents()
}
private fun loadChatInfo(chatId: String) {
viewModelScope.launch {
try {
val chats = repository.getChats()
val chat = chats.find { it.id == chatId }
chat?.let { c ->
_state.update { it.copy(chatName = c.name, chatAvatar = c.avatar) }
}
} catch (e: Exception) {
// Ignore info load error
}
}
}
fun loadMessages(chatId: String) {
viewModelScope.launch {
_state.update { it.copy(isLoading = true) }
@@ -88,8 +105,9 @@ class ChatDetailViewModel @Inject constructor(
when (event) {
is ChatEvent.NewMessage -> {
// Avoid adding duplicates if already loaded
val baseUrl = serverConfig.getBaseUrl().removeSuffix("/api/")
_state.update { s ->
val domainMsg = event.message.toDomain()
val domainMsg = event.message.toDomain(baseUrl)
if (s.messages.none { it.id == domainMsg.id }) {
s.copy(messages = s.messages + domainMsg)
} else s