feat: Implement AttachmentFileManager for handling image attachments; add methods for saving, reading, and managing attachment files

This commit is contained in:
2026-01-26 17:43:23 +05:00
parent 44c0151294
commit 0f652bea86
3 changed files with 265 additions and 5 deletions

View File

@@ -12,6 +12,7 @@ import com.rosetta.messenger.database.MessageEntity
import com.rosetta.messenger.database.RosettaDatabase
import com.rosetta.messenger.network.*
import com.rosetta.messenger.ui.chats.models.*
import com.rosetta.messenger.utils.AttachmentFileManager
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.json.JSONArray
@@ -770,6 +771,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
/**
* Парсинг всех attachments из JSON (кроме MESSAGES который обрабатывается отдельно)
* 💾 Для IMAGE - загружает blob из файловой системы если пустой в БД
*/
private fun parseAllAttachments(attachmentsJson: String): List<MessageAttachment> {
if (attachmentsJson.isEmpty() || attachmentsJson == "[]") {
@@ -779,6 +781,8 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
return try {
val attachments = JSONArray(attachmentsJson)
val result = mutableListOf<MessageAttachment>()
val publicKey = myPublicKey ?: ""
val privateKey = myPrivateKey ?: ""
for (i in 0 until attachments.length()) {
val attachment = attachments.getJSONObject(i)
@@ -787,11 +791,28 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
// Пропускаем MESSAGES (1) - это reply, обрабатывается отдельно
if (type == 1) continue
var blob = attachment.optString("blob", "")
val attachmentId = attachment.optString("id", "")
val attachmentType = AttachmentType.fromInt(type)
// 💾 Для IMAGE - пробуем загрузить blob из файла если пустой
if (attachmentType == AttachmentType.IMAGE && blob.isEmpty() && attachmentId.isNotEmpty()) {
val fileBlob = AttachmentFileManager.readAttachment(
context = getApplication(),
attachmentId = attachmentId,
publicKey = publicKey,
privateKey = privateKey
)
if (fileBlob != null) {
blob = fileBlob
}
}
result.add(
MessageAttachment(
id = attachment.optString("id", ""),
blob = attachment.optString("blob", ""),
type = AttachmentType.fromInt(type),
id = attachmentId,
blob = blob,
type = attachmentType,
preview = attachment.optString("preview", ""),
width = attachment.optInt("width", 0),
height = attachment.optInt("height", 0)
@@ -1404,8 +1425,18 @@ class ChatViewModel(application: Application) : AndroidViewModel(application) {
updateMessageStatus(messageId, MessageStatus.SENT)
}
// 💾 Сохраняем изображение в файл (как в desktop)
// Файлы НЕ сохраняем - они слишком большие, загружаются с CDN
AttachmentFileManager.saveAttachment(
context = getApplication(),
blob = imageBase64,
attachmentId = imageAttachment.id,
publicKey = sender,
privateKey = privateKey
)
// ⚠️ НЕ сохраняем blob в БД - он слишком большой (SQLite CursorWindow 2MB limit)
// Изображение должно храниться в файловой системе или загружаться с сервера при необходимости
// Изображение хранится в файловой системе
val attachmentsJson = JSONArray().apply {
put(JSONObject().apply {
put("id", imageAttachment.id)