feat: Enhance image attachment handling with local file management and download status logic
This commit is contained in:
@@ -45,6 +45,7 @@ import com.rosetta.messenger.R
|
||||
import com.rosetta.messenger.repository.AvatarRepository
|
||||
import com.rosetta.messenger.ui.chats.models.MessageStatus
|
||||
import com.rosetta.messenger.ui.onboarding.PrimaryBlue
|
||||
import com.rosetta.messenger.utils.AttachmentFileManager
|
||||
import com.rosetta.messenger.utils.AvatarFileManager
|
||||
import com.vanniktech.blurhash.BlurHash
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -98,6 +99,7 @@ fun MessageAttachments(
|
||||
attachments = imageAttachments,
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -152,6 +154,7 @@ fun ImageCollage(
|
||||
attachments: List<MessageAttachment>,
|
||||
chachaKey: String,
|
||||
privateKey: String,
|
||||
senderPublicKey: String,
|
||||
isOutgoing: Boolean,
|
||||
isDarkTheme: Boolean,
|
||||
timestamp: java.util.Date,
|
||||
@@ -175,6 +178,7 @@ fun ImageCollage(
|
||||
attachment = attachments[0],
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -194,6 +198,7 @@ fun ImageCollage(
|
||||
attachment = attachment,
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -219,6 +224,7 @@ fun ImageCollage(
|
||||
attachment = attachments[0],
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -237,6 +243,7 @@ fun ImageCollage(
|
||||
attachment = attachments[1],
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -250,6 +257,7 @@ fun ImageCollage(
|
||||
attachment = attachments[2],
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -276,6 +284,7 @@ fun ImageCollage(
|
||||
attachment = attachments[0],
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -289,6 +298,7 @@ fun ImageCollage(
|
||||
attachment = attachments[1],
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -307,6 +317,7 @@ fun ImageCollage(
|
||||
attachment = attachments[2],
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -320,6 +331,7 @@ fun ImageCollage(
|
||||
attachment = attachments[3],
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -347,6 +359,7 @@ fun ImageCollage(
|
||||
attachment = attachments[0],
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -360,6 +373,7 @@ fun ImageCollage(
|
||||
attachment = attachments[1],
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -384,6 +398,7 @@ fun ImageCollage(
|
||||
attachment = attachment,
|
||||
chachaKey = chachaKey,
|
||||
privateKey = privateKey,
|
||||
senderPublicKey = senderPublicKey,
|
||||
isOutgoing = isOutgoing,
|
||||
isDarkTheme = isDarkTheme,
|
||||
timestamp = timestamp,
|
||||
@@ -407,12 +422,19 @@ fun ImageCollage(
|
||||
|
||||
/**
|
||||
* Image attachment - Telegram style с blurhash placeholder
|
||||
*
|
||||
* Логика определения статуса (как в Desktop):
|
||||
* 1. Если preview НЕ содержит UUID → это локальный файл → DOWNLOADED
|
||||
* 2. Если есть UUID (download tag) → проверяем файловую систему через AttachmentFileManager
|
||||
* 3. Если файл есть локально → DOWNLOADED (загружаем из файла)
|
||||
* 4. Иначе → NOT_DOWNLOADED (нужно скачать с CDN)
|
||||
*/
|
||||
@Composable
|
||||
fun ImageAttachment(
|
||||
attachment: MessageAttachment,
|
||||
chachaKey: String,
|
||||
privateKey: String,
|
||||
senderPublicKey: String,
|
||||
isOutgoing: Boolean,
|
||||
isDarkTheme: Boolean,
|
||||
timestamp: java.util.Date,
|
||||
@@ -439,19 +461,36 @@ fun ImageAttachment(
|
||||
label = "progress"
|
||||
)
|
||||
|
||||
// Определяем начальный статус и декодируем blurhash
|
||||
// Определяем начальный статус и декодируем blurhash (как в Desktop calcDownloadStatus)
|
||||
LaunchedEffect(attachment.id) {
|
||||
// Определяем статус
|
||||
// Определяем статус (логика из Desktop useAttachment.ts)
|
||||
withContext(Dispatchers.IO) {
|
||||
downloadStatus = when {
|
||||
attachment.blob.isNotEmpty() && !isDownloadTag(attachment.preview) -> {
|
||||
// Blob уже есть в сообщении (локальный файл)
|
||||
// 1. Если blob уже есть в памяти → DOWNLOADED
|
||||
attachment.blob.isNotEmpty() -> {
|
||||
Log.d(TAG, "📦 Blob already in memory for ${attachment.id}")
|
||||
DownloadStatus.DOWNLOADED
|
||||
}
|
||||
isDownloadTag(attachment.preview) -> {
|
||||
// Нужно скачать с CDN
|
||||
// 2. Если preview НЕ содержит UUID → это наш локальный файл → DOWNLOADED
|
||||
!isDownloadTag(attachment.preview) -> {
|
||||
Log.d(TAG, "📦 No download tag, local file for ${attachment.id}")
|
||||
DownloadStatus.DOWNLOADED
|
||||
}
|
||||
// 3. Есть UUID (download tag) → проверяем файловую систему
|
||||
else -> {
|
||||
// Проверяем есть ли файл локально (как в Desktop: readFile(`m/${md5hash}`))
|
||||
val hasLocal = AttachmentFileManager.hasAttachment(
|
||||
context, attachment.id, senderPublicKey
|
||||
)
|
||||
if (hasLocal) {
|
||||
Log.d(TAG, "📦 Found local file for ${attachment.id}")
|
||||
DownloadStatus.DOWNLOADED
|
||||
} else {
|
||||
Log.d(TAG, "📥 Need to download ${attachment.id}")
|
||||
DownloadStatus.NOT_DOWNLOADED
|
||||
}
|
||||
else -> DownloadStatus.DOWNLOADED
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Декодируем blurhash для placeholder (если есть)
|
||||
@@ -473,10 +512,27 @@ fun ImageAttachment(
|
||||
Log.d(TAG, "⚠️ No valid blurhash preview (preview='${preview.take(20)}...', isDownloadTag=${isDownloadTag(preview)})")
|
||||
}
|
||||
|
||||
// Декодируем изображение если уже скачано
|
||||
if (downloadStatus == DownloadStatus.DOWNLOADED && attachment.blob.isNotEmpty()) {
|
||||
// Загружаем изображение если статус DOWNLOADED
|
||||
if (downloadStatus == DownloadStatus.DOWNLOADED) {
|
||||
withContext(Dispatchers.IO) {
|
||||
// 1. Сначала пробуем blob из памяти
|
||||
if (attachment.blob.isNotEmpty()) {
|
||||
Log.d(TAG, "🖼️ Loading image from blob")
|
||||
imageBitmap = base64ToBitmap(attachment.blob)
|
||||
} else {
|
||||
// 2. Читаем из файловой системы (как в Desktop getBlob)
|
||||
Log.d(TAG, "🖼️ Loading image from local file")
|
||||
val localBlob = AttachmentFileManager.readAttachment(
|
||||
context, attachment.id, senderPublicKey, privateKey
|
||||
)
|
||||
if (localBlob != null) {
|
||||
imageBitmap = base64ToBitmap(localBlob)
|
||||
Log.d(TAG, "✅ Image loaded from local file")
|
||||
} else {
|
||||
Log.w(TAG, "⚠️ Failed to read local file, need to download")
|
||||
downloadStatus = DownloadStatus.NOT_DOWNLOADED
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -511,6 +567,16 @@ fun ImageAttachment(
|
||||
if (decrypted != null) {
|
||||
withContext(Dispatchers.IO) {
|
||||
imageBitmap = base64ToBitmap(decrypted)
|
||||
|
||||
// 💾 Сохраняем в файловую систему (как в Desktop)
|
||||
AttachmentFileManager.saveAttachment(
|
||||
context = context,
|
||||
blob = decrypted,
|
||||
attachmentId = attachment.id,
|
||||
publicKey = senderPublicKey,
|
||||
privateKey = privateKey
|
||||
)
|
||||
Log.d(TAG, "💾 Image saved to local storage")
|
||||
}
|
||||
downloadProgress = 1f
|
||||
downloadStatus = DownloadStatus.DOWNLOADED
|
||||
|
||||
Reference in New Issue
Block a user