Вот как настройка проекта:
model -> usererservice -> userapi -> repo -> viewModel -> Ui < /p>
if. чат -экран. Я до сих пор успешно создал чат-экран, и он работает, отправляя сообщения двунаправленные. Недавно я добавил функцию удара, чтобы иметь возможность отслеживать скидные сообщения и добавлять их в чат -экран в качестве ответов. Я протестировал, установив ответ_TO_ID в базе данных, и он правильно отображается внутри чата. Я пытался выяснить эту проблему сейчас в течение 4 дней, но без удачи. Цените любую помощь! /> модель: < /strong>
Вот код: < /p>
@Serializable
data class SendMessageResponse(
val status: String, // e.g., "Message sent"
val reply_to_id: Int? = null, // the ID of the message being replied to, if any
val reply_to: ReplyModel? = null // full original message object if it's a reply
)
@Serializable
data class ReplyModel(
val id: Int? = null,
val sender_email: String? = "",
val message: String? = ""
)
@Serializable
data class MessageModel(
val id: Int? = null,
val sender_email: String? = "",
val receiver_email: String? = "",
val message: String? = "",
val timestamp: String? = null,
val isReceived: Boolean = false,
val reply_to_id: Int? = null,
val reply_to: ReplyModel? = null
)
userservice:
@FormUrlEncoded
@POST("send_message")
suspend fun sendMessage(
@Field("receiver_email") receiverEmail: String,
@Field("sender_email") senderEmail: String,
@Field("message") message: String,
@Field("timestamp") timestamp: String,
@Field("reply_to_id") reply_to_id: Int? = null
): Response
userapi:
suspend fun sendMessage(messageModel: MessageModel): Response {
return userService.sendMessage(
receiverEmail = messageModel.receiver_email ?: "",
senderEmail = messageModel.sender_email ?: "",
message = messageModel.message ?: "",
timestamp = messageModel.timestamp ?: "",
reply_to_id = messageModel.reply_to_id
)
}
Repo:
suspend fun sendMessage(message: MessageModel) {
Log.d("ChatFeatureRepo", "Repo sending MessageModel: reply_to_id=${message.reply_to_id}, full=$message")
try {
val response = userApi.sendMessage(message) // Now returns Response
if (response.isSuccessful) {
val sentMessage = response.body()
Log.d("ChatFeatureRepo", "Message sent successfully: $sentMessage")
sentMessage?.reply_to?.let { reply ->
Log.d("ChatFeatureRepo", "Message was a reply to: $reply")
}
} else {
Log.e("ChatFeatureRepo", "Failed to send message: ${response.code()} - ${response.message()}")
Log.e("ChatFeatureRepo", "Request body: $message")
}
} catch (e: Exception) {
Log.e("ChatFeatureRepo", "Exception sending message: ${e.message}", e)
}
}
viewmodel:
var replyingTo: MessageModel? = null
private val _replyTo = MutableLiveData()
val replyTo: LiveData = _replyTo
fun setReplyTo(message: MessageModel?) {
replyingTo = message
_replyTo.value = message // keeps LiveData in sync for UI
}
fun clearReply() {
setReplyTo(null)
}
fun sendMessage(message: MessageModel) {
viewModelScope.launch {
try {
val messageToSend = message.copy(
reply_to = message.reply_to ?: replyingTo?.let { repliedMsg ->
ReplyModel(
id = repliedMsg.id,
sender_email = repliedMsg.sender_email,
message = repliedMsg.message
)
},
reply_to_id = message.reply_to_id ?: replyingTo?.id
)
Log.d("DatingViewModel", "Prepared MessageModel: reply_to_id=${messageToSend.reply_to_id}, reply_to=${messageToSend.reply_to}")
// Optimistic UI
_messages.value = _messages.value + messageToSend
// Send to backend
repo.sendMessage(messageToSend)
// Reset reply state
clearReply()
} catch (e: Exception) {
Log.e("chat_feature", "Error sending message: ${e.message}", e)
}
}
}
custommodalbottomsheetforchatscreen:
CustomModalBottomSheetForChatScreen(
datingViewModel = datingViewModel,
matchedUser = matchedUser,
isLoading = loading,
chatMessages = chatMessages,
onSendMessage = { text, replyToMessage ->
Log.d("CustomModalBottomSheet", "onSendMessage invoked: text=$text replyToMessage=$replyToMessage replyToId=${replyToMessage?.id}")
datingViewModel.sendMessage(
MessageModel(
receiver_email = matchedUser.email ?: "",
sender_email = loggedInUser?.email ?: "",
message = text,
reply_to = replyToMessage?.let { repliedMsg ->
ReplyModel(
id = repliedMsg.id,
sender_email = repliedMsg.sender_email,
message = repliedMsg.message
)
},
reply_to_id = replyToMessage?.id
)
)
}
) {
chatWithUser = null
}
Внутри CustomModalBottomSheetForChatScreen Я передаю чат -экран:
Sheet(
modifier = Modifier
.shadow(4.dp, RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp))
.clip(RoundedCornerShape(topStart = 50.dp, topEnd = 50.dp))
.fillMaxWidth()
.fillMaxHeight()
.imePadding(),
) {
ChatScreen(
matchedUser,
datingViewModel,
isLoading,
chatMessages,
onSendMessage,
onCloseClick = {
scope.launch {
modalSheetState.animateTo(Hidden)
isSheetVisible = false
}
}
)
Внутри чата у меня есть sendmessageclick:
val replyTo by datingViewModel.replyTo.observeAsState()
Box(
modifier = Modifier
.size(50.dp)
.clip(CircleShape)
.background(WhatsappOrange)
.clickable {
if (message.isNotBlank()) {
Log.d("ChatScreen", "Sending with reply_to_id = ${replyTo?.id}")
Log.d("ChatScreen", "Sending message text=$message replyTo=$replyTo replyToId=${replyTo?.id}")
onSendMessage(
message,
replyTo, //
)
// Clear input + reply state
message = ""
datingViewModel.clearReply()
}
}
) {
Icon(
imageVector = Icons.AutoMirrored.Sharp.Send,
contentDescription = "Send",
tint = Color.White,
modifier = Modifier.align(Alignment.Center)
)
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... ck-compose
Мобильная версия