mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-23 07:41:28 +00:00
fix: downloads now don't automatically queue for untrusted contacts and UI to handle re-downloading failed attachments
This commit is contained in:
parent
176456c253
commit
bc4f660fb0
@ -60,9 +60,9 @@ class DatabaseAttachmentProvider(context: Context, helper: SQLCipherOpenHelper)
|
|||||||
return databaseAttachment.toSignalAttachmentPointer()
|
return databaseAttachment.toSignalAttachmentPointer()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setAttachmentState(attachmentState: AttachmentState, attachmentId: Long, messageID: Long) {
|
override fun setAttachmentState(attachmentState: AttachmentState, attachmentId: AttachmentId, messageID: Long) {
|
||||||
val attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context)
|
val attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context)
|
||||||
attachmentDatabase.setTransferState(messageID, AttachmentId(attachmentId, 0), attachmentState.value)
|
attachmentDatabase.setTransferState(messageID, attachmentId, attachmentState.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMessageForQuote(timestamp: Long, author: Address): Pair<Long, Boolean>? {
|
override fun getMessageForQuote(timestamp: Long, author: Address): Pair<Long, Boolean>? {
|
||||||
|
@ -13,6 +13,9 @@ import androidx.core.view.children
|
|||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import kotlinx.android.synthetic.main.album_thumbnail_view.view.*
|
import kotlinx.android.synthetic.main.album_thumbnail_view.view.*
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
|
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.ViewUtil
|
import org.session.libsession.utilities.ViewUtil
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.MediaPreviewActivity
|
import org.thoughtcrime.securesms.MediaPreviewActivity
|
||||||
@ -23,6 +26,7 @@ import org.thoughtcrime.securesms.loki.utilities.ActivityDispatcher
|
|||||||
import org.thoughtcrime.securesms.longmessage.LongMessageActivity
|
import org.thoughtcrime.securesms.longmessage.LongMessageActivity
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.mms.Slide
|
import org.thoughtcrime.securesms.mms.Slide
|
||||||
|
import org.thoughtcrime.securesms.video.exo.AttachmentDataSource
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class AlbumThumbnailView : FrameLayout {
|
class AlbumThumbnailView : FrameLayout {
|
||||||
@ -82,6 +86,13 @@ class AlbumThumbnailView : FrameLayout {
|
|||||||
// hit intersects with this particular child
|
// hit intersects with this particular child
|
||||||
val slide = slides.getOrNull(index) ?: return
|
val slide = slides.getOrNull(index) ?: return
|
||||||
// only open to downloaded images
|
// only open to downloaded images
|
||||||
|
if (slide.isPendingDownload) {
|
||||||
|
// restart download here
|
||||||
|
(slide.asAttachment() as? DatabaseAttachment)?.let { attachment ->
|
||||||
|
val attachmentId = attachment.attachmentId.rowId
|
||||||
|
JobQueue.shared.add(AttachmentDownloadJob(attachmentId, mms.getId()))
|
||||||
|
}
|
||||||
|
}
|
||||||
if (slide.isInProgress) return
|
if (slide.isInProgress) return
|
||||||
|
|
||||||
ActivityDispatcher.get(context)?.dispatchIntent { context ->
|
ActivityDispatcher.get(context)?.dispatchIntent { context ->
|
||||||
|
@ -40,6 +40,7 @@ open class KThumbnailView: FrameLayout {
|
|||||||
private val image by lazy { thumbnail_image }
|
private val image by lazy { thumbnail_image }
|
||||||
private val playOverlay by lazy { play_overlay }
|
private val playOverlay by lazy { play_overlay }
|
||||||
val loadIndicator: View by lazy { thumbnail_load_indicator }
|
val loadIndicator: View by lazy { thumbnail_load_indicator }
|
||||||
|
val downloadIndicator: View by lazy { thumbnail_download_icon }
|
||||||
|
|
||||||
private val dimensDelegate = ThumbnailDimensDelegate()
|
private val dimensDelegate = ThumbnailDimensDelegate()
|
||||||
|
|
||||||
@ -108,7 +109,8 @@ open class KThumbnailView: FrameLayout {
|
|||||||
|
|
||||||
this.slide = slide
|
this.slide = slide
|
||||||
|
|
||||||
loadIndicator.isVisible = slide.isInProgress && !mms.isFailed
|
loadIndicator.isVisible = slide.isInProgress && !slide.isPendingDownload
|
||||||
|
downloadIndicator.isVisible = slide.isPendingDownload
|
||||||
|
|
||||||
dimensDelegate.setDimens(naturalWidth, naturalHeight)
|
dimensDelegate.setDimens(naturalWidth, naturalHeight)
|
||||||
invalidate()
|
invalidate()
|
||||||
|
@ -47,6 +47,14 @@ class SessionContactDatabase(context: Context, helper: SQLCipherOpenHelper) : Da
|
|||||||
}.toSet()
|
}.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setContactIsTrusted(contact: Contact, isTrusted: Boolean) {
|
||||||
|
val database = databaseHelper.writableDatabase
|
||||||
|
val contentValues = ContentValues(1)
|
||||||
|
contentValues.put(Companion.isTrusted, if (isTrusted) 1 else 0)
|
||||||
|
database.insertOrUpdate(sessionContactTable, contentValues, "$sessionID = ?", arrayOf( contact.sessionID ))
|
||||||
|
notifyConversationListListeners()
|
||||||
|
}
|
||||||
|
|
||||||
fun setContact(contact: Contact) {
|
fun setContact(contact: Contact) {
|
||||||
val database = databaseHelper.writableDatabase
|
val database = databaseHelper.writableDatabase
|
||||||
val contentValues = ContentValues(8)
|
val contentValues = ContentValues(8)
|
||||||
|
@ -22,6 +22,15 @@
|
|||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:src="@drawable/ic_download_circle_filled_48"
|
||||||
|
android:id="@+id/thumbnail_download_icon"
|
||||||
|
android:layout_width="@dimen/medium_button_height"
|
||||||
|
android:layout_height="@dimen/medium_button_height"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
/>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/play_overlay"
|
android:id="@+id/play_overlay"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
@ -29,8 +38,7 @@
|
|||||||
android:background="@drawable/circle_white"
|
android:background="@drawable/circle_white"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:longClickable="false"
|
android:longClickable="false"
|
||||||
android:visibility="gone"
|
android:visibility="gone">
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="19dp"
|
android:layout_width="19dp"
|
||||||
|
@ -18,7 +18,7 @@ interface MessageDataProvider {
|
|||||||
fun getSignalAttachmentStream(attachmentId: Long): SignalServiceAttachmentStream?
|
fun getSignalAttachmentStream(attachmentId: Long): SignalServiceAttachmentStream?
|
||||||
fun getScaledSignalAttachmentStream(attachmentId: Long): SignalServiceAttachmentStream?
|
fun getScaledSignalAttachmentStream(attachmentId: Long): SignalServiceAttachmentStream?
|
||||||
fun getSignalAttachmentPointer(attachmentId: Long): SignalServiceAttachmentPointer?
|
fun getSignalAttachmentPointer(attachmentId: Long): SignalServiceAttachmentPointer?
|
||||||
fun setAttachmentState(attachmentState: AttachmentState, attachmentId: Long, messageID: Long)
|
fun setAttachmentState(attachmentState: AttachmentState, attachmentId: AttachmentId, messageID: Long)
|
||||||
fun insertAttachment(messageId: Long, attachmentId: AttachmentId, stream : InputStream)
|
fun insertAttachment(messageId: Long, attachmentId: AttachmentId, stream : InputStream)
|
||||||
fun updateAudioAttachmentDuration(attachmentId: AttachmentId, durationMs: Long, threadId: Long)
|
fun updateAudioAttachmentDuration(attachmentId: AttachmentId, durationMs: Long, threadId: Long)
|
||||||
fun isOutgoingMessage(timestamp: Long): Boolean
|
fun isOutgoingMessage(timestamp: Long): Boolean
|
||||||
|
@ -3,6 +3,7 @@ package org.session.libsession.messaging.jobs
|
|||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
||||||
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentId
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentState
|
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentState
|
||||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||||
import org.session.libsession.messaging.utilities.Data
|
import org.session.libsession.messaging.utilities.Data
|
||||||
@ -41,10 +42,14 @@ class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long)
|
|||||||
override fun execute() {
|
override fun execute() {
|
||||||
val storage = MessagingModuleConfiguration.shared.storage
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider
|
val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider
|
||||||
val handleFailure: (java.lang.Exception) -> Unit = { exception ->
|
val handleFailure: (java.lang.Exception, attachmentId: AttachmentId?) -> Unit = { exception, attachment ->
|
||||||
if (exception == Error.NoAttachment
|
if (exception == Error.NoAttachment
|
||||||
|| (exception is OnionRequestAPI.HTTPRequestFailedAtDestinationException && exception.statusCode == 400)) {
|
|| (exception is OnionRequestAPI.HTTPRequestFailedAtDestinationException && exception.statusCode == 400)) {
|
||||||
messageDataProvider.setAttachmentState(AttachmentState.FAILED, attachmentID, databaseMessageID)
|
attachment?.let { id ->
|
||||||
|
messageDataProvider.setAttachmentState(AttachmentState.FAILED, id, databaseMessageID)
|
||||||
|
} ?: run {
|
||||||
|
messageDataProvider.setAttachmentState(AttachmentState.FAILED, AttachmentId(attachmentID,0), databaseMessageID)
|
||||||
|
}
|
||||||
this.handlePermanentFailure(exception)
|
this.handlePermanentFailure(exception)
|
||||||
} else {
|
} else {
|
||||||
this.handleFailure(exception)
|
this.handleFailure(exception)
|
||||||
@ -53,8 +58,8 @@ class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long)
|
|||||||
var tempFile: File? = null
|
var tempFile: File? = null
|
||||||
try {
|
try {
|
||||||
val attachment = messageDataProvider.getDatabaseAttachment(attachmentID)
|
val attachment = messageDataProvider.getDatabaseAttachment(attachmentID)
|
||||||
?: return handleFailure(Error.NoAttachment)
|
?: return handleFailure(Error.NoAttachment, null)
|
||||||
messageDataProvider.setAttachmentState(AttachmentState.STARTED, attachmentID, this.databaseMessageID)
|
messageDataProvider.setAttachmentState(AttachmentState.STARTED, attachment.attachmentId, this.databaseMessageID)
|
||||||
tempFile = createTempFile()
|
tempFile = createTempFile()
|
||||||
val threadID = storage.getThreadIdForMms(databaseMessageID)
|
val threadID = storage.getThreadIdForMms(databaseMessageID)
|
||||||
val openGroupV2 = storage.getV2OpenGroup(threadID)
|
val openGroupV2 = storage.getV2OpenGroup(threadID)
|
||||||
|
@ -221,10 +221,17 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage, proto: SignalS
|
|||||||
val messageID = storage.persist(message, quoteModel, linkPreviews, message.groupPublicKey, openGroupID, attachments) ?: throw MessageReceiver.Error.DuplicateMessage
|
val messageID = storage.persist(message, quoteModel, linkPreviews, message.groupPublicKey, openGroupID, attachments) ?: throw MessageReceiver.Error.DuplicateMessage
|
||||||
// Parse & persist attachments
|
// Parse & persist attachments
|
||||||
// Start attachment downloads if needed
|
// Start attachment downloads if needed
|
||||||
|
val contact = message.sender?.let { address -> storage.getContactWithSessionID(address) }
|
||||||
storage.getAttachmentsForMessage(messageID).forEach { attachment ->
|
storage.getAttachmentsForMessage(messageID).forEach { attachment ->
|
||||||
attachment.attachmentId?.let { id ->
|
attachment.attachmentId?.let { id ->
|
||||||
val downloadJob = AttachmentDownloadJob(id.rowId, messageID)
|
// if open group or self-send, then always download attachment
|
||||||
JobQueue.shared.add(downloadJob)
|
val immediatelyDownload = !openGroupID.isNullOrEmpty() // open group
|
||||||
|
|| userPublicKey == message.sender // self-send
|
||||||
|
|| contact?.isTrusted == true // trusted contact
|
||||||
|
if (immediatelyDownload) {
|
||||||
|
val downloadJob = AttachmentDownloadJob(id.rowId, messageID)
|
||||||
|
JobQueue.shared.add(downloadJob)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val openGroupServerID = message.openGroupServerMessageID
|
val openGroupServerID = message.openGroupServerMessageID
|
||||||
|
Loading…
x
Reference in New Issue
Block a user