mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-24 02:25:19 +00:00
commit
d22704e264
@ -149,9 +149,5 @@ public class AlbumThumbnailView extends FrameLayout {
|
||||
}
|
||||
|
||||
private void setSlide(@NonNull GlideRequests glideRequests, @NonNull Slide slide, @IdRes int id) {
|
||||
KThumbnailView cell = findViewById(id);
|
||||
cell.setImageResource(glideRequests, slide, false);
|
||||
cell.setThumbnailClickListener(defaultThumbnailClickListener);
|
||||
cell.setOnLongClickListener(defaultLongClickListener);
|
||||
}
|
||||
}
|
||||
|
@ -50,13 +50,17 @@ import org.session.libsession.messaging.mentions.MentionsManager
|
||||
import org.session.libsession.messaging.messages.control.DataExtractionNotification
|
||||
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage
|
||||
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage
|
||||
import org.session.libsession.messaging.messages.visible.LinkPreview.Companion.from
|
||||
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation
|
||||
import org.session.libsession.messaging.messages.visible.Quote.Companion.from
|
||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageData
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageData.Companion.fromJSON
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.Address.Companion.fromSerialized
|
||||
import org.session.libsession.utilities.MediaTypes
|
||||
@ -1143,7 +1147,48 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
}
|
||||
|
||||
override fun resendMessage(messages: Set<MessageRecord>) {
|
||||
// TODO: Implement
|
||||
messages.forEach { messageRecord ->
|
||||
val recipient: Recipient = messageRecord.recipient
|
||||
val message = VisibleMessage()
|
||||
message.id = messageRecord.getId()
|
||||
if (messageRecord.isOpenGroupInvitation) {
|
||||
val openGroupInvitation = OpenGroupInvitation()
|
||||
fromJSON(messageRecord.body)?.let { updateMessageData ->
|
||||
val kind = updateMessageData.kind
|
||||
if (kind is UpdateMessageData.Kind.OpenGroupInvitation) {
|
||||
openGroupInvitation.name = kind.groupName
|
||||
openGroupInvitation.url = kind.groupUrl
|
||||
}
|
||||
}
|
||||
message.openGroupInvitation = openGroupInvitation
|
||||
} else {
|
||||
message.text = messageRecord.body
|
||||
}
|
||||
message.sentTimestamp = messageRecord.timestamp
|
||||
if (recipient.isGroupRecipient) {
|
||||
message.groupPublicKey = recipient.address.toGroupString()
|
||||
} else {
|
||||
message.recipient = messageRecord.recipient.address.serialize()
|
||||
}
|
||||
message.threadID = messageRecord.threadId
|
||||
if (messageRecord.isMms) {
|
||||
val mmsMessageRecord = messageRecord as MmsMessageRecord
|
||||
if (mmsMessageRecord.linkPreviews.isNotEmpty()) {
|
||||
message.linkPreview = from(mmsMessageRecord.linkPreviews[0])
|
||||
}
|
||||
if (mmsMessageRecord.quote != null) {
|
||||
message.quote = from(mmsMessageRecord.quote!!.quoteModel)
|
||||
}
|
||||
message.addSignalAttachments(mmsMessageRecord.slideDeck.asAttachments())
|
||||
}
|
||||
val sentTimestamp = message.sentTimestamp
|
||||
val sender = MessagingModuleConfiguration.shared.storage.getUserPublicKey()
|
||||
if (sentTimestamp != null && sender != null) {
|
||||
MessagingModuleConfiguration.shared.storage.markAsSending(sentTimestamp, sender)
|
||||
}
|
||||
MessageSender.send(message, recipient.address)
|
||||
}
|
||||
endActionMode()
|
||||
}
|
||||
|
||||
override fun saveAttachment(messages: Set<MessageRecord>) {
|
||||
|
@ -115,7 +115,7 @@ class AlbumThumbnailView : FrameLayout {
|
||||
// iterate binding
|
||||
slides.take(5).forEachIndexed { position, slide ->
|
||||
val thumbnailView = getThumbnailView(position)
|
||||
thumbnailView.setImageResource(glideRequests, slide, isPreview = false)
|
||||
thumbnailView.setImageResource(glideRequests, slide, isPreview = false, mms = message)
|
||||
}
|
||||
albumCellBodyParent.isVisible = message.body.isNotEmpty()
|
||||
albumCellBodyText.text = message.body
|
||||
|
@ -48,7 +48,7 @@ class LinkPreviewView : LinearLayout {
|
||||
// Thumbnail
|
||||
if (linkPreview.getThumbnail().isPresent) {
|
||||
// This internally fetches the thumbnail
|
||||
thumbnailImageView.setImageResource(glide, ImageSlide(context, linkPreview.getThumbnail().get()), isPreview = false)
|
||||
thumbnailImageView.setImageResource(glide, ImageSlide(context, linkPreview.getThumbnail().get()), isPreview = false, message)
|
||||
thumbnailImageView.loadIndicator.isVisible = false
|
||||
}
|
||||
// Title
|
||||
|
@ -131,9 +131,13 @@ class VisibleMessageView : LinearLayout {
|
||||
val gravity = if (message.isOutgoing) Gravity.END else Gravity.START
|
||||
mainContainer.gravity = gravity or Gravity.BOTTOM
|
||||
// Message status indicator
|
||||
val iconID = getMessageStatusImage(message)
|
||||
val (iconID, iconColor) = getMessageStatusImage(message)
|
||||
if (iconID != null) {
|
||||
messageStatusImageView.setImageResource(iconID)
|
||||
val drawable = ContextCompat.getDrawable(context, iconID)?.mutate()
|
||||
if (iconColor != null) {
|
||||
drawable?.setTint(iconColor)
|
||||
}
|
||||
messageStatusImageView.setImageDrawable(drawable)
|
||||
}
|
||||
if (message.isOutgoing) {
|
||||
val lastMessageID = DatabaseFactory.getMmsSmsDatabase(context).getLastMessageID(message.threadId)
|
||||
@ -179,13 +183,13 @@ class VisibleMessageView : LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getMessageStatusImage(message: MessageRecord): Int? {
|
||||
when {
|
||||
!message.isOutgoing -> return null
|
||||
message.isFailed -> return R.drawable.ic_error
|
||||
message.isPending -> return R.drawable.ic_circle_dot_dot_dot
|
||||
message.isRead -> return R.drawable.ic_filled_circle_check
|
||||
else -> return R.drawable.ic_circle_check
|
||||
private fun getMessageStatusImage(message: MessageRecord): Pair<Int?,Int?> {
|
||||
return when {
|
||||
!message.isOutgoing -> null to null
|
||||
message.isFailed -> R.drawable.ic_error to resources.getColor(R.color.destructive, context.theme)
|
||||
message.isPending -> R.drawable.ic_circle_dot_dot_dot to null
|
||||
message.isRead -> R.drawable.ic_filled_circle_check to null
|
||||
else -> R.drawable.ic_circle_check to null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,9 @@ import org.session.libsignal.utilities.ListenableFuture
|
||||
import org.session.libsignal.utilities.SettableFuture
|
||||
import org.thoughtcrime.securesms.components.GlideBitmapListeningTarget
|
||||
import org.thoughtcrime.securesms.components.GlideDrawableListeningTarget
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.mms.*
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
|
||||
open class KThumbnailView: FrameLayout {
|
||||
|
||||
@ -43,8 +43,6 @@ open class KThumbnailView: FrameLayout {
|
||||
|
||||
private val dimensDelegate = ThumbnailDimensDelegate()
|
||||
|
||||
var thumbnailClickListener: SlideClickListener? = null
|
||||
|
||||
private var slide: Slide? = null
|
||||
private var radius: Int = 0
|
||||
|
||||
@ -84,13 +82,13 @@ open class KThumbnailView: FrameLayout {
|
||||
// endregion
|
||||
|
||||
// region Interaction
|
||||
fun setImageResource(glide: GlideRequests, slide: Slide, isPreview: Boolean): ListenableFuture<Boolean> {
|
||||
return setImageResource(glide, slide, isPreview, 0, 0)
|
||||
fun setImageResource(glide: GlideRequests, slide: Slide, isPreview: Boolean, mms: MmsMessageRecord): ListenableFuture<Boolean> {
|
||||
return setImageResource(glide, slide, isPreview, 0, 0, mms)
|
||||
}
|
||||
|
||||
fun setImageResource(glide: GlideRequests, slide: Slide,
|
||||
isPreview: Boolean, naturalWidth: Int,
|
||||
naturalHeight: Int): ListenableFuture<Boolean> {
|
||||
naturalHeight: Int, mms: MmsMessageRecord): ListenableFuture<Boolean> {
|
||||
|
||||
val currentSlide = this.slide
|
||||
|
||||
@ -110,7 +108,7 @@ open class KThumbnailView: FrameLayout {
|
||||
|
||||
this.slide = slide
|
||||
|
||||
loadIndicator.isVisible = slide.isInProgress
|
||||
loadIndicator.isVisible = slide.isInProgress && !mms.isFailed
|
||||
|
||||
dimensDelegate.setDimens(naturalWidth, naturalHeight)
|
||||
invalidate()
|
||||
|
@ -27,6 +27,7 @@ import org.session.libsignal.utilities.KeyHelper
|
||||
import org.session.libsignal.utilities.guava.Optional
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
||||
import org.thoughtcrime.securesms.loki.api.OpenGroupManager
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase
|
||||
@ -303,6 +304,19 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
}
|
||||
}
|
||||
|
||||
override fun markAsSending(timestamp: Long, author: String) {
|
||||
val database = DatabaseFactory.getMmsSmsDatabase(context)
|
||||
val messageRecord = database.getMessageFor(timestamp, author) ?: return
|
||||
if (messageRecord.isMms) {
|
||||
val mmsDatabase = DatabaseFactory.getMmsDatabase(context)
|
||||
mmsDatabase.markAsSending(messageRecord.getId())
|
||||
} else {
|
||||
val smsDatabase = DatabaseFactory.getSmsDatabase(context)
|
||||
smsDatabase.markAsSending(messageRecord.getId())
|
||||
messageRecord.isPending
|
||||
}
|
||||
}
|
||||
|
||||
override fun markUnidentified(timestamp: Long, author: String) {
|
||||
val database = DatabaseFactory.getMmsSmsDatabase(context)
|
||||
val messageRecord = database.getMessageFor(timestamp, author) ?: return
|
||||
|
@ -8,6 +8,7 @@ import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.android.synthetic.main.view_conversation.view.*
|
||||
@ -73,7 +74,11 @@ class ConversationView : LinearLayout {
|
||||
statusIndicatorImageView.visibility = View.VISIBLE
|
||||
when {
|
||||
!thread.isOutgoing -> statusIndicatorImageView.visibility = View.GONE
|
||||
thread.isFailed -> statusIndicatorImageView.setImageResource(R.drawable.ic_error)
|
||||
thread.isFailed -> {
|
||||
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_error)?.mutate()
|
||||
drawable?.setTint(ContextCompat.getColor(context,R.color.destructive))
|
||||
statusIndicatorImageView.setImageDrawable(drawable)
|
||||
}
|
||||
thread.isPending -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_dot_dot_dot)
|
||||
thread.isRead -> statusIndicatorImageView.setImageResource(R.drawable.ic_filled_circle_check)
|
||||
else -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_check)
|
||||
|
@ -89,6 +89,7 @@ interface StorageProtocol {
|
||||
fun persistAttachments(messageID: Long, attachments: List<Attachment>): List<Long>
|
||||
fun getAttachmentsForMessage(messageID: Long): List<DatabaseAttachment>
|
||||
fun getMessageIdInDatabase(timestamp: Long, author: String): Long? // TODO: This is a weird name
|
||||
fun markAsSending(timestamp: Long, author: String)
|
||||
fun markAsSent(timestamp: Long, author: String)
|
||||
fun markUnidentified(timestamp: Long, author: String)
|
||||
fun setErrorMessage(timestamp: Long, author: String, error: Exception)
|
||||
|
@ -122,7 +122,7 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
||||
private fun handleFailure(e: Exception) {
|
||||
Log.w(TAG, "Attachment upload failed due to error: $this.")
|
||||
delegate?.handleJobFailed(this, e)
|
||||
if (failureCount + 1 == maxFailureCount) {
|
||||
if (failureCount + 1 >= maxFailureCount) {
|
||||
failAssociatedMessageSendJob(e)
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package org.session.libsession.messaging.jobs
|
||||
import com.esotericsoftware.kryo.Kryo
|
||||
import com.esotericsoftware.kryo.io.Input
|
||||
import com.esotericsoftware.kryo.io.Output
|
||||
import nl.komponents.kovenant.FailedException
|
||||
import nl.komponents.kovenant.Promise
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.jobs.Job.Companion.MAX_BUFFER_SIZE
|
||||
import org.session.libsession.messaging.messages.Destination
|
||||
@ -34,6 +36,14 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
||||
override fun execute() {
|
||||
val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider
|
||||
val message = message as? VisibleMessage
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
|
||||
val sentTimestamp = this.message.sentTimestamp
|
||||
val sender = storage.getUserPublicKey()
|
||||
if (sentTimestamp != null && sender != null) {
|
||||
storage.markAsSending(sentTimestamp, sender)
|
||||
}
|
||||
|
||||
if (message != null) {
|
||||
if (!messageDataProvider.isOutgoingMessage(message.sentTimestamp!!)) return // The message has been deleted
|
||||
val attachmentIDs = mutableListOf<Long>()
|
||||
@ -43,7 +53,7 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
||||
val attachments = attachmentIDs.mapNotNull { messageDataProvider.getDatabaseAttachment(it) }
|
||||
val attachmentsToUpload = attachments.filter { it.url.isNullOrEmpty() }
|
||||
attachmentsToUpload.forEach {
|
||||
if (MessagingModuleConfiguration.shared.storage.getAttachmentUploadJob(it.attachmentId.rowId) != null) {
|
||||
if (storage.getAttachmentUploadJob(it.attachmentId.rowId) != null) {
|
||||
// Wait for it to finish
|
||||
} else {
|
||||
val job = AttachmentUploadJob(it.attachmentId.rowId, message.threadID!!.toString(), message, id!!)
|
||||
@ -55,7 +65,7 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
||||
return
|
||||
} // Wait for all attachments to upload before continuing
|
||||
}
|
||||
MessageSender.send(this.message, this.destination).success {
|
||||
val promise = MessageSender.send(this.message, this.destination).success {
|
||||
this.handleSuccess()
|
||||
}.fail { exception ->
|
||||
Log.e(TAG, "Couldn't send message due to error: $exception.")
|
||||
@ -64,6 +74,11 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
||||
}
|
||||
this.handleFailure(exception)
|
||||
}
|
||||
try {
|
||||
promise.get()
|
||||
} catch (e: Exception) {
|
||||
Log.d(TAG, "Promise failed to resolve successfully", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSuccess() {
|
||||
|
Loading…
Reference in New Issue
Block a user