mirror of
https://github.com/oxen-io/session-android.git
synced 2023-12-14 02:53:01 +01:00
refactor: auto attachment downloads for specific threads, manual attachment downloads triggered from UI and correct visual state representation
This commit is contained in:
parent
5860c0b961
commit
995ac45ed9
8 changed files with 80 additions and 74 deletions
|
@ -10,11 +10,12 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
import network.loki.messenger.R
|
||||
import network.loki.messenger.databinding.DialogDownloadBinding
|
||||
import org.session.libsession.messaging.contacts.Contact
|
||||
import org.session.libsession.messaging.jobs.AttachmentDownloadJob
|
||||
import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
||||
import org.thoughtcrime.securesms.database.SessionContactDatabase
|
||||
import org.thoughtcrime.securesms.util.createAndStartAttachmentDownload
|
||||
import org.thoughtcrime.securesms.util.displaySize
|
||||
import javax.inject.Inject
|
||||
|
||||
|
@ -47,7 +48,7 @@ class DownloadDialog(private val recipient: Recipient,
|
|||
|
||||
private fun download() {
|
||||
// TODO: add attachment download job trigger with attachmentID and databaseMessageID
|
||||
val downloadJob = AttachmentDownloadJob()
|
||||
JobQueue.shared.createAndStartAttachmentDownload(databaseAttachment)
|
||||
dismiss()
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import androidx.annotation.ColorInt
|
|||
import androidx.core.content.ContextCompat
|
||||
import network.loki.messenger.R
|
||||
import network.loki.messenger.databinding.ViewPendingAttachmentBinding
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.conversation.v2.dialogs.DownloadDialog
|
||||
import org.thoughtcrime.securesms.util.ActivityDispatcher
|
||||
|
@ -21,8 +21,6 @@ class PendingAttachmentView: LinearLayout {
|
|||
MEDIA
|
||||
}
|
||||
|
||||
private var attachmentId: AttachmentId? = null
|
||||
|
||||
// region Lifecycle
|
||||
constructor(context: Context) : super(context)
|
||||
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
||||
|
@ -31,7 +29,7 @@ class PendingAttachmentView: LinearLayout {
|
|||
// endregion
|
||||
|
||||
// region Updating
|
||||
fun bind(attachmentType: AttachmentType, @ColorInt textColor: Int, attachmentId: AttachmentId) {
|
||||
fun bind(attachmentType: AttachmentType, @ColorInt textColor: Int, attachment: DatabaseAttachment) {
|
||||
val (iconRes, stringRes) = when (attachmentType) {
|
||||
AttachmentType.AUDIO -> R.drawable.ic_microphone to R.string.Slide_audio
|
||||
AttachmentType.DOCUMENT -> R.drawable.ic_document_large_light to R.string.document
|
||||
|
@ -43,15 +41,12 @@ class PendingAttachmentView: LinearLayout {
|
|||
|
||||
binding.untrustedAttachmentIcon.setImageDrawable(iconDrawable)
|
||||
binding.untrustedAttachmentTitle.text = text
|
||||
this.attachmentId = attachmentId
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Interaction
|
||||
fun showDownloadDialog(threadRecipient: Recipient) {
|
||||
attachmentId?.let { attachmentId ->
|
||||
ActivityDispatcher.get(context)?.showDialog(DownloadDialog(threadRecipient, attachmentId))
|
||||
}
|
||||
fun showDownloadDialog(threadRecipient: Recipient, attachment: DatabaseAttachment) {
|
||||
ActivityDispatcher.get(context)?.showDialog(DownloadDialog(threadRecipient, attachment))
|
||||
}
|
||||
|
||||
}
|
|
@ -26,9 +26,6 @@ import androidx.core.view.isVisible
|
|||
import network.loki.messenger.R
|
||||
import network.loki.messenger.databinding.ViewVisibleMessageContentBinding
|
||||
import okhttp3.HttpUrl
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.jobs.AttachmentDownloadJob
|
||||
import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||
import org.session.libsession.utilities.getColorFromAttr
|
||||
|
@ -65,7 +62,7 @@ class VisibleMessageContentView : LinearLayout {
|
|||
|
||||
// region Updating
|
||||
fun bind(message: MessageRecord, isStartOfMessageCluster: Boolean, isEndOfMessageCluster: Boolean,
|
||||
glide: GlideRequests, thread: Recipient, searchQuery: String?, autoDownloadAttachments: Boolean) {
|
||||
glide: GlideRequests, thread: Recipient, searchQuery: String?) {
|
||||
// Background
|
||||
val background = getBackground(message.isOutgoing)
|
||||
val color = if (message.isOutgoing) context.getAccentColor()
|
||||
|
@ -75,6 +72,7 @@ class VisibleMessageContentView : LinearLayout {
|
|||
binding.contentParent.background = background
|
||||
|
||||
val mediaDownloaded = message is MmsMessageRecord && message.slideDeck.asAttachments().all { it.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_DONE }
|
||||
val mediaInProgress = message is MmsMessageRecord && message.slideDeck.asAttachments().any { it.isInProgress }
|
||||
val mediaThumbnailMessage = message is MmsMessageRecord && message.slideDeck.thumbnailSlide != null
|
||||
|
||||
// reset visibilities / containers
|
||||
|
@ -89,7 +87,7 @@ class VisibleMessageContentView : LinearLayout {
|
|||
} else {
|
||||
binding.deletedMessageView.root.isVisible = false
|
||||
}
|
||||
// clear the
|
||||
// clear the body
|
||||
binding.bodyTextView.text = null
|
||||
|
||||
|
||||
|
@ -97,9 +95,9 @@ class VisibleMessageContentView : LinearLayout {
|
|||
|
||||
binding.linkPreviewView.isVisible = message is MmsMessageRecord && message.linkPreviews.isNotEmpty()
|
||||
|
||||
binding.pendingAttachmentView.root.isVisible = !mediaDownloaded && message is MmsMessageRecord && message.quote == null && message.linkPreviews.isEmpty()
|
||||
binding.voiceMessageView.root.isVisible = mediaDownloaded && message is MmsMessageRecord && message.slideDeck.audioSlide != null
|
||||
binding.documentView.root.isVisible = mediaDownloaded && message is MmsMessageRecord && message.slideDeck.documentSlide != null
|
||||
binding.pendingAttachmentView.root.isVisible = !mediaDownloaded && !mediaInProgress && message is MmsMessageRecord && message.quote == null && message.linkPreviews.isEmpty()
|
||||
binding.voiceMessageView.root.isVisible = (mediaDownloaded || mediaInProgress) && message is MmsMessageRecord && message.slideDeck.audioSlide != null
|
||||
binding.documentView.root.isVisible = (mediaDownloaded || mediaInProgress) && message is MmsMessageRecord && message.slideDeck.documentSlide != null
|
||||
binding.albumThumbnailView.isVisible = mediaThumbnailMessage
|
||||
binding.openGroupInvitationView.root.isVisible = message.isOpenGroupInvitation
|
||||
|
||||
|
@ -125,36 +123,18 @@ class VisibleMessageContentView : LinearLayout {
|
|||
}
|
||||
}
|
||||
|
||||
if (message is MmsMessageRecord) {
|
||||
message.slideDeck.asAttachments().forEach { attach ->
|
||||
val dbAttachment = attach as? DatabaseAttachment ?: return@forEach
|
||||
val attachmentId = dbAttachment.attachmentId.rowId
|
||||
if (attach.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING
|
||||
&& MessagingModuleConfiguration.shared.storage.getAttachmentUploadJob(attachmentId) == null) {
|
||||
// start download
|
||||
JobQueue.shared.add(AttachmentDownloadJob(attachmentId, dbAttachment.mmsId))
|
||||
}
|
||||
}
|
||||
message.linkPreviews.forEach { preview ->
|
||||
val previewThumbnail = preview.getThumbnail().orNull() as? DatabaseAttachment ?: return@forEach
|
||||
val attachmentId = previewThumbnail.attachmentId.rowId
|
||||
if (previewThumbnail.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING
|
||||
&& MessagingModuleConfiguration.shared.storage.getAttachmentUploadJob(attachmentId) == null) {
|
||||
JobQueue.shared.add(AttachmentDownloadJob(attachmentId, previewThumbnail.mmsId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when {
|
||||
// LINK PREVIEW
|
||||
message is MmsMessageRecord && message.linkPreviews.isNotEmpty() -> {
|
||||
binding.linkPreviewView.bind(message, glide, isStartOfMessageCluster, isEndOfMessageCluster)
|
||||
onContentClick.add { event -> binding.linkPreviewView.calculateHit(event) }
|
||||
// Body text view is inside the link preview for layout convenience
|
||||
}
|
||||
// AUDIO
|
||||
message is MmsMessageRecord && message.slideDeck.audioSlide != null -> {
|
||||
hideBody = true
|
||||
// Audio attachment
|
||||
if (mediaDownloaded || message.isOutgoing) {
|
||||
if (mediaDownloaded || mediaInProgress || message.isOutgoing) {
|
||||
binding.voiceMessageView.root.indexInAdapter = indexInAdapter
|
||||
binding.voiceMessageView.root.delegate = context as? ConversationActivityV2
|
||||
binding.voiceMessageView.root.bind(message, isStartOfMessageCluster, isEndOfMessageCluster)
|
||||
|
@ -163,33 +143,36 @@ class VisibleMessageContentView : LinearLayout {
|
|||
onContentClick.add { binding.voiceMessageView.root.togglePlayback() }
|
||||
onContentDoubleTap = { binding.voiceMessageView.root.handleDoubleTap() }
|
||||
} else {
|
||||
(message.slideDeck.audioSlide?.asAttachment() as? DatabaseAttachment)?.let { attachment ->
|
||||
binding.pendingAttachmentView.root.bind(
|
||||
PendingAttachmentView.AttachmentType.AUDIO,
|
||||
getTextColor(context,message),
|
||||
|
||||
attachment
|
||||
)
|
||||
onContentClick.add { binding.pendingAttachmentView.root.showDownloadDialog(message.recipient) }
|
||||
onContentClick.add { binding.pendingAttachmentView.root.showDownloadDialog(message.recipient, attachment) }
|
||||
}
|
||||
}
|
||||
}
|
||||
// DOCUMENT
|
||||
message is MmsMessageRecord && message.slideDeck.documentSlide != null -> {
|
||||
hideBody = true
|
||||
// Document attachment
|
||||
if (mediaDownloaded || message.isOutgoing) {
|
||||
if (mediaDownloaded || mediaInProgress || message.isOutgoing) {
|
||||
binding.documentView.root.bind(message, getTextColor(context, message))
|
||||
} else {
|
||||
(message.slideDeck.documentSlide?.asAttachment() as? DatabaseAttachment)?.let { attachment ->
|
||||
binding.pendingAttachmentView.root.bind(
|
||||
PendingAttachmentView.AttachmentType.DOCUMENT,
|
||||
getTextColor(context,message),
|
||||
|
||||
attachment
|
||||
)
|
||||
onContentClick.add { binding.pendingAttachmentView.root.showDownloadDialog(message.recipient) }
|
||||
onContentClick.add { binding.pendingAttachmentView.root.showDownloadDialog(message.recipient, attachment) }
|
||||
}
|
||||
}
|
||||
}
|
||||
// IMAGE / VIDEO
|
||||
message is MmsMessageRecord && message.slideDeck.asAttachments().isNotEmpty() -> {
|
||||
/*
|
||||
* Images / Video attachment
|
||||
*/
|
||||
if (mediaDownloaded || message.isOutgoing) {
|
||||
if (mediaDownloaded || mediaInProgress || message.isOutgoing) {
|
||||
// isStart and isEnd of cluster needed for calculating the mask for full bubble image groups
|
||||
// bind after add view because views are inflated and calculated during bind
|
||||
binding.albumThumbnailView.bind(
|
||||
|
@ -207,12 +190,17 @@ class VisibleMessageContentView : LinearLayout {
|
|||
} else {
|
||||
hideBody = true
|
||||
binding.albumThumbnailView.clearViews()
|
||||
val firstAttachment = message.slideDeck.asAttachments().first() as? DatabaseAttachment
|
||||
firstAttachment?.let { attachment ->
|
||||
binding.pendingAttachmentView.root.bind(
|
||||
PendingAttachmentView.AttachmentType.MEDIA,
|
||||
getTextColor(context,message),
|
||||
|
||||
attachment
|
||||
)
|
||||
onContentClick.add { binding.pendingAttachmentView.root.showDownloadDialog(message.recipient) }
|
||||
onContentClick.add {
|
||||
binding.pendingAttachmentView.root.showDownloadDialog(message.recipient, attachment)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
message.isOpenGroupInvitation -> {
|
||||
|
|
|
@ -229,8 +229,7 @@ class VisibleMessageView : LinearLayout {
|
|||
isEndOfMessageCluster,
|
||||
glide,
|
||||
thread,
|
||||
searchQuery,
|
||||
message.isOutgoing || (thread.autoDownloadAttachments)
|
||||
searchQuery
|
||||
)
|
||||
binding.messageContentView.delegate = delegate
|
||||
onDoubleTap = { binding.messageContentView.onContentDoubleTap?.invoke() }
|
||||
|
|
|
@ -1,18 +1,35 @@
|
|||
package org.thoughtcrime.securesms.util
|
||||
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.jobs.AttachmentDownloadJob
|
||||
import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||
|
||||
private const val ZERO_SIZE = "0.00"
|
||||
private const val KILO_SIZE = 1024
|
||||
private const val KILO_SIZE = 1024f
|
||||
private const val MB_SUFFIX = "MB"
|
||||
private const val KB_SUFFIX = "KB"
|
||||
|
||||
fun Attachment.displaySize(): String {
|
||||
|
||||
val kbSize = size / KILO_SIZE
|
||||
val needsMb = kbSize > KILO_SIZE
|
||||
val sizeText = "%.2f".format(if (needsMb) kbSize / KILO_SIZE else kbSize)
|
||||
return when {
|
||||
val displaySize = when {
|
||||
sizeText == ZERO_SIZE -> "0.01"
|
||||
sizeText.endsWith(".00") -> sizeText.takeWhile { it != '.' }
|
||||
else -> sizeText
|
||||
}
|
||||
return "$displaySize${if (needsMb) MB_SUFFIX else KB_SUFFIX}"
|
||||
}
|
||||
|
||||
fun JobQueue.createAndStartAttachmentDownload(attachment: DatabaseAttachment) {
|
||||
val attachmentId = attachment.attachmentId.rowId
|
||||
if (attachment.transferState == AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING
|
||||
&& MessagingModuleConfiguration.shared.storage.getAttachmentUploadJob(attachmentId) == null) {
|
||||
// start download
|
||||
add(AttachmentDownloadJob(attachmentId, attachment.mmsId))
|
||||
}
|
||||
}
|
|
@ -99,12 +99,6 @@ class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long)
|
|||
handleFailure(Error.NoSender, null)
|
||||
return
|
||||
}
|
||||
if (!threadRecipient.isGroupRecipient && (!threadRecipient.autoDownloadAttachments && storage.getUserPublicKey() != sender)) {
|
||||
// if we aren't receiving a group message, a message from ourselves (self-send) and the thread does not auto-download:
|
||||
// do not continue, but do not fail (it will be restarted later)
|
||||
// TODO: probably remove this logic and just re-trigger based on attachment ID in future
|
||||
return
|
||||
}
|
||||
|
||||
var tempFile: File? = null
|
||||
try {
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.session.libsession.messaging.sending_receiving
|
|||
import android.text.TextUtils
|
||||
import org.session.libsession.avatars.AvatarHelper
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.jobs.AttachmentDownloadJob
|
||||
import org.session.libsession.messaging.jobs.BackgroundGroupAddJob
|
||||
import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.messages.Message
|
||||
|
@ -325,6 +326,16 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage,
|
|||
storage.persist(message, quoteModel, linkPreviews, message.groupPublicKey, openGroupID,
|
||||
attachments, runIncrement, runThreadUpdate
|
||||
) ?: return null
|
||||
// Parse & persist attachments
|
||||
// Start attachment downloads if needed
|
||||
if (threadRecipient?.autoDownloadAttachments == true || messageSender == userPublicKey) {
|
||||
storage.getAttachmentsForMessage(messageID).iterator().forEach { attachment ->
|
||||
attachment.attachmentId?.let { id ->
|
||||
val downloadJob = AttachmentDownloadJob(id.rowId, messageID)
|
||||
JobQueue.shared.add(downloadJob)
|
||||
}
|
||||
}
|
||||
}
|
||||
val openGroupServerID = message.openGroupServerMessageID
|
||||
if (openGroupServerID != null) {
|
||||
val isSms = !(message.isMediaMessage() || attachments.isNotEmpty())
|
||||
|
|
|
@ -76,7 +76,8 @@ public abstract class Attachment {
|
|||
|
||||
public boolean isInProgress() {
|
||||
return transferState != AttachmentTransferProgress.TRANSFER_PROGRESS_DONE &&
|
||||
transferState != AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED;
|
||||
transferState != AttachmentTransferProgress.TRANSFER_PROGRESS_FAILED &&
|
||||
transferState != AttachmentTransferProgress.TRANSFER_PROGRESS_PENDING;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
|
|
Loading…
Reference in a new issue