diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index afe28b15ae..3065ca13cc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -3,15 +3,14 @@ package org.thoughtcrime.securesms.conversation.v2 import android.Manifest import android.animation.FloatEvaluator import android.animation.ValueAnimator -import android.content.Context import android.content.ClipData import android.content.ClipboardManager +import android.content.Context import android.content.Intent import android.content.res.Resources import android.database.Cursor import android.graphics.Rect import android.graphics.Typeface -import android.os.Bundle import android.net.Uri import android.os.* import android.text.TextUtils @@ -47,13 +46,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.Companion.fromSerialized import org.session.libsession.utilities.MediaTypes import org.session.libsession.utilities.TextSecurePreferences @@ -84,11 +87,11 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel.LinkPreviewState -import org.thoughtcrime.securesms.loki.utilities.ActivityDispatcher -import org.thoughtcrime.securesms.loki.utilities.push import org.thoughtcrime.securesms.loki.activities.SelectContactsActivity import org.thoughtcrime.securesms.loki.activities.SelectContactsActivity.Companion.selectedContactsKey +import org.thoughtcrime.securesms.loki.utilities.ActivityDispatcher import org.thoughtcrime.securesms.loki.utilities.MentionUtilities +import org.thoughtcrime.securesms.loki.utilities.push import org.thoughtcrime.securesms.loki.utilities.toPx import org.thoughtcrime.securesms.mediasend.Media import org.thoughtcrime.securesms.mediasend.MediaSendActivity @@ -1034,7 +1037,48 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe } override fun resendMessage(messages: Set) { - // 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) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt index ad74e47a61..356a9e2fbb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt @@ -14,7 +14,6 @@ import android.widget.LinearLayout import androidx.core.content.ContextCompat import androidx.core.view.isVisible import kotlinx.android.synthetic.main.view_visible_message.view.* -import kotlinx.android.synthetic.main.view_visible_message.view.profilePictureView import network.loki.messenger.R import org.session.libsession.messaging.contacts.Contact.ContactContext import org.session.libsession.messaging.open_groups.OpenGroupAPIV2 @@ -124,9 +123,13 @@ class VisibleMessageView : LinearLayout { val gravity = if (message.isOutgoing) Gravity.RIGHT else Gravity.LEFT 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) @@ -169,13 +172,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 { + 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 } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 1c67eac4e3..75db53493b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -28,6 +28,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 @@ -304,6 +305,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 diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/views/ConversationView.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/views/ConversationView.kt index cff2096de7..893c73019e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/views/ConversationView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/views/ConversationView.kt @@ -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) diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt index 94a19ff072..8a21e61513 100644 --- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt @@ -89,6 +89,7 @@ interface StorageProtocol { fun persistAttachments(messageID: Long, attachments: List): List fun getAttachmentsForMessage(messageID: Long): List 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) diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt index 87fead7c58..b4b04c9ed3 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt @@ -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 @@ -55,7 +57,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 +66,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() {