Заготовка
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
package chats.data.local.mappers
|
||||
|
||||
import chats.data.local.database.ChatEntity
|
||||
import chats.domain.model.Chat
|
||||
|
||||
/**
|
||||
* Преобразует Domain Chat в Entity
|
||||
*/
|
||||
fun Chat.toEntity(): ChatEntity {
|
||||
return ChatEntity(
|
||||
localId = this.id.takeIf { it.isNotBlank() } ?: java.util.UUID.randomUUID().toString(),
|
||||
remoteId = this.id,
|
||||
type = this.type,
|
||||
name = this.name,
|
||||
avatar = this.avatar,
|
||||
unreadCount = this.unreadCount,
|
||||
lastMessageText = this.lastMessage?.content,
|
||||
lastMessageTimestamp = this.lastMessage?.createdAt
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Преобразует Entity в Domain Chat
|
||||
*/
|
||||
fun ChatEntity.toDomain(): Chat {
|
||||
return Chat(
|
||||
id = this.remoteId ?: this.localId,
|
||||
type = this.type,
|
||||
name = this.name,
|
||||
avatar = this.avatar,
|
||||
unreadCount = this.unreadCount,
|
||||
lastMessage = null // lastMessage загружается отдельно
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package chats.data.local.mappers
|
||||
|
||||
import chats.data.local.database.MessageEntity
|
||||
import chats.domain.model.Message
|
||||
import chats.domain.model.MessageStatus
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
||||
private val gson = Gson()
|
||||
|
||||
/**
|
||||
* Преобразует Domain Message в Entity для сохранения в Room
|
||||
*/
|
||||
fun Message.toEntity(status: MessageStatus = MessageStatus.SENT): MessageEntity {
|
||||
return MessageEntity(
|
||||
localId = this.id.takeIf { it.isNotBlank() } ?: java.util.UUID.randomUUID().toString(),
|
||||
serverId = if (status == MessageStatus.SENT || status == MessageStatus.DELIVERED || status == MessageStatus.READ) this.id else null,
|
||||
idempotencyKey = java.util.UUID.randomUUID().toString(),
|
||||
chatId = this.chatId,
|
||||
senderId = this.senderId,
|
||||
senderName = this.senderName,
|
||||
senderAvatar = this.senderAvatar,
|
||||
content = this.content,
|
||||
sequenceId = this.sequenceId.toLong(),
|
||||
createdAt = this.createdAt,
|
||||
mediaType = this.mediaType.name,
|
||||
mediaJson = gson.toJson(this.media),
|
||||
reactionsJson = gson.toJson(this.reactions),
|
||||
status = status,
|
||||
isPinned = this.isPinned,
|
||||
isForwarded = this.isForwarded,
|
||||
forwardedFromName = this.forwardedFromName,
|
||||
replyToServerId = this.replyTo?.id,
|
||||
createdAtMillis = parseTimestamp(this.createdAt),
|
||||
updatedAtMillis = System.currentTimeMillis()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Преобразует Entity в Domain Message для отображения в UI
|
||||
*/
|
||||
fun MessageEntity.toDomain(): Message {
|
||||
val mediaListType = object : TypeToken<List<chats.domain.model.Media>>() {}.type
|
||||
val reactionsMapType = object : TypeToken<Map<String, Int>>() {}.type
|
||||
|
||||
return Message(
|
||||
id = this.serverId ?: this.localId,
|
||||
chatId = this.chatId,
|
||||
senderId = this.senderId,
|
||||
senderName = this.senderName,
|
||||
senderAvatar = this.senderAvatar,
|
||||
content = this.content,
|
||||
sequenceId = this.sequenceId.toInt(),
|
||||
createdAt = this.createdAt,
|
||||
media = try {
|
||||
gson.fromJson<List<chats.domain.model.Media>>(this.mediaJson, mediaListType) ?: emptyList()
|
||||
} catch (e: Exception) {
|
||||
emptyList()
|
||||
},
|
||||
mediaType = try {
|
||||
chats.domain.model.MediaType.valueOf(this.mediaType)
|
||||
} catch (e: Exception) {
|
||||
chats.domain.model.MediaType.TEXT
|
||||
},
|
||||
reactions = try {
|
||||
gson.fromJson<Map<String, Int>>(this.reactionsJson, reactionsMapType) ?: emptyMap()
|
||||
} catch (e: Exception) {
|
||||
emptyMap()
|
||||
},
|
||||
isRead = this.status == MessageStatus.READ,
|
||||
isPinned = this.isPinned,
|
||||
isForwarded = this.isForwarded,
|
||||
forwardedFromName = this.forwardedFromName,
|
||||
replyTo = null, // replyTo загружается отдельно если нужно
|
||||
status = this.status
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает новое локальное сообщение со статусом PENDING
|
||||
*/
|
||||
fun createPendingMessageEntity(
|
||||
chatId: String,
|
||||
senderId: String,
|
||||
senderName: String,
|
||||
content: String?,
|
||||
mediaType: String = "TEXT",
|
||||
mediaJson: String = "[]",
|
||||
replyToId: String? = null
|
||||
): MessageEntity {
|
||||
val localId = java.util.UUID.randomUUID().toString()
|
||||
return MessageEntity(
|
||||
localId = localId,
|
||||
serverId = null,
|
||||
idempotencyKey = localId, // Используем localId как idempotency key
|
||||
chatId = chatId,
|
||||
senderId = senderId,
|
||||
senderName = senderName,
|
||||
content = content,
|
||||
sequenceId = -1, // Будет обновлено после получения с сервера
|
||||
createdAt = java.time.ZonedDateTime.now().toString(),
|
||||
mediaType = mediaType,
|
||||
mediaJson = mediaJson,
|
||||
status = MessageStatus.PENDING,
|
||||
replyToServerId = replyToId,
|
||||
createdAtMillis = System.currentTimeMillis(),
|
||||
updatedAtMillis = System.currentTimeMillis()
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseTimestamp(createdAt: String): Long {
|
||||
return try {
|
||||
java.time.ZonedDateTime.parse(createdAt).toInstant().toEpochMilli()
|
||||
} catch (e: Exception) {
|
||||
System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user