feat: Implement avatar handling and display across chat and account screens
This commit is contained in:
@@ -6,6 +6,7 @@ import com.rosetta.messenger.crypto.CryptoManager
|
||||
import com.rosetta.messenger.crypto.MessageCrypto
|
||||
import com.rosetta.messenger.database.*
|
||||
import com.rosetta.messenger.network.*
|
||||
import com.rosetta.messenger.utils.AvatarFileManager
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.json.JSONArray
|
||||
@@ -53,6 +54,7 @@ class MessageRepository private constructor(private val context: Context) {
|
||||
private val database = RosettaDatabase.getDatabase(context)
|
||||
private val messageDao = database.messageDao()
|
||||
private val dialogDao = database.dialogDao()
|
||||
private val avatarDao = database.avatarDao()
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
|
||||
@@ -318,7 +320,10 @@ class MessageRepository private constructor(private val context: Context) {
|
||||
privateKey
|
||||
)
|
||||
|
||||
// 🔒 Шифруем plainMessage с использованием приватного ключа
|
||||
// <EFBFBD> Обрабатываем AVATAR attachments - сохраняем аватар отправителя
|
||||
processAvatarAttachments(packet.attachments, packet.fromPublicKey, packet.chachaKey, privateKey)
|
||||
|
||||
// <20>🔒 Шифруем plainMessage с использованием приватного ключа
|
||||
val encryptedPlainMessage = CryptoManager.encryptWithPassword(plainText, privateKey)
|
||||
|
||||
// Создаем entity для кэша и возможной вставки
|
||||
@@ -719,6 +724,61 @@ class MessageRepository private constructor(private val context: Context) {
|
||||
return jsonArray.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* 📸 Обработка AVATAR attachments - сохранение аватара отправителя в кэш
|
||||
* Как в desktop: при получении attachment с типом AVATAR - сохраняем в avatar_cache
|
||||
*/
|
||||
private suspend fun processAvatarAttachments(
|
||||
attachments: List<MessageAttachment>,
|
||||
fromPublicKey: String,
|
||||
encryptedKey: String,
|
||||
privateKey: String
|
||||
) {
|
||||
Log.d("MessageRepository", "📸 processAvatarAttachments: ${attachments.size} attachments from ${fromPublicKey.take(16)}")
|
||||
|
||||
for (attachment in attachments) {
|
||||
Log.d("MessageRepository", "📸 Attachment type=${attachment.type} (AVATAR=${AttachmentType.AVATAR}), blob size=${attachment.blob.length}")
|
||||
|
||||
if (attachment.type == AttachmentType.AVATAR && attachment.blob.isNotEmpty()) {
|
||||
try {
|
||||
Log.d("MessageRepository", "📸 Found AVATAR attachment! Decrypting...")
|
||||
|
||||
// 1. Расшифровываем blob с ChaCha ключом сообщения
|
||||
val decryptedBlob = MessageCrypto.decryptAttachmentBlob(
|
||||
attachment.blob,
|
||||
encryptedKey,
|
||||
privateKey
|
||||
)
|
||||
|
||||
Log.d("MessageRepository", "📸 Decrypted blob: ${decryptedBlob?.take(50) ?: "NULL"}")
|
||||
|
||||
if (decryptedBlob != null) {
|
||||
// 2. Сохраняем аватар в кэш
|
||||
val filePath = AvatarFileManager.saveAvatar(context, decryptedBlob, fromPublicKey)
|
||||
Log.d("MessageRepository", "📸 Avatar saved to: $filePath")
|
||||
|
||||
val entity = AvatarCacheEntity(
|
||||
publicKey = fromPublicKey,
|
||||
avatar = filePath,
|
||||
timestamp = System.currentTimeMillis()
|
||||
)
|
||||
avatarDao.insertAvatar(entity)
|
||||
Log.d("MessageRepository", "📸 Avatar inserted to DB for ${fromPublicKey.take(16)}")
|
||||
|
||||
// 3. Очищаем старые аватары (оставляем последние 5)
|
||||
avatarDao.deleteOldAvatars(fromPublicKey, 5)
|
||||
|
||||
Log.d("MessageRepository", "📸 ✅ Successfully saved avatar for $fromPublicKey")
|
||||
} else {
|
||||
Log.w("MessageRepository", "📸 ⚠️ Decryption returned null!")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("MessageRepository", "📸 ❌ Failed to process avatar attachment", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Сериализация attachments в JSON с RE-ENCRYPTION для хранения в БД
|
||||
* Для MESSAGES типа:
|
||||
|
||||
Reference in New Issue
Block a user