diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 6eae3a6927..f1b256749f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -221,6 +221,11 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="org.thoughtcrime.securesms.home.HomeActivity" />
+
+
) {
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)
+ ResendMessageUtilities.resend(messageRecord)
}
endActionMode()
}
+ override fun showMessageDetail(messages: Set) {
+ val message = messages.first()
+ val intent = Intent(this, MessageDetailActivity::class.java)
+ intent.putExtra(MessageDetailActivity.MESSAGE_TIMESTAMP, message.timestamp)
+ push(intent)
+ endActionMode()
+ }
+
override fun saveAttachment(messages: Set) {
val message = messages.first() as MmsMessageRecord
SaveAttachmentTask.showWarningDialog(this, { _, _ ->
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt
new file mode 100644
index 0000000000..8c870d7b07
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt
@@ -0,0 +1,78 @@
+package org.thoughtcrime.securesms.conversation.v2
+
+import android.os.Bundle
+import android.view.View
+import android.widget.LinearLayout
+import androidx.annotation.DimenRes
+import kotlinx.android.synthetic.main.activity_conversation_v2_action_bar.*
+import kotlinx.android.synthetic.main.activity_message_detail.*
+import network.loki.messenger.R
+import org.session.libsession.messaging.MessagingModuleConfiguration
+import org.session.libsession.messaging.messages.visible.LinkPreview
+import org.session.libsession.messaging.messages.visible.OpenGroupInvitation
+import org.session.libsession.messaging.messages.visible.Quote
+import org.session.libsession.messaging.messages.visible.VisibleMessage
+import org.session.libsession.messaging.sending_receiving.MessageSender
+import org.session.libsession.messaging.utilities.UpdateMessageData
+import org.session.libsession.utilities.Address
+import org.session.libsession.utilities.ExpirationUtil
+import org.session.libsession.utilities.TextSecurePreferences
+import org.session.libsession.utilities.recipients.Recipient
+import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
+import org.thoughtcrime.securesms.conversation.v2.utilities.ResendMessageUtilities
+import org.thoughtcrime.securesms.database.DatabaseFactory
+import org.thoughtcrime.securesms.database.model.MessageRecord
+import org.thoughtcrime.securesms.database.model.MmsMessageRecord
+import org.thoughtcrime.securesms.util.DateUtils
+import java.text.SimpleDateFormat
+import java.util.*
+import kotlin.math.roundToInt
+
+
+class MessageDetailActivity: PassphraseRequiredActionBarActivity() {
+
+ var messageRecord: MessageRecord? = null
+
+ // region Settings
+ companion object {
+ // Extras
+ const val MESSAGE_TIMESTAMP = "message_timestamp"
+ }
+ // endregion
+
+ override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
+ super.onCreate(savedInstanceState, ready)
+ setContentView(R.layout.activity_message_detail)
+ title = resources.getString(R.string.conversation_context__menu_message_details)
+ val timestamp = intent.getLongExtra(MESSAGE_TIMESTAMP, -1L)
+ // We only show this screen for messages fail to send,
+ // so the author of the messages must be the current user.
+ val author = Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)!!)
+ messageRecord = DatabaseFactory.getMmsSmsDatabase (this).getMessageFor(timestamp, author)
+ updateContent()
+ resend_button.setOnClickListener {
+ ResendMessageUtilities.resend(messageRecord!!)
+ finish()
+ }
+ }
+
+ fun updateContent() {
+ val dateLocale = Locale.getDefault()
+ val dateFormatter: SimpleDateFormat = DateUtils.getDetailedDateFormatter(this, dateLocale)
+ sent_time.text = dateFormatter.format(Date(messageRecord!!.dateSent))
+
+ val errorMessage = DatabaseFactory.getLokiMessageDatabase(this).getErrorMessage(messageRecord!!.getId()) ?: "Message failed to send."
+ error_message.text = errorMessage
+
+ if (messageRecord!!.getExpiresIn() <= 0 || messageRecord!!.getExpireStarted() <= 0) {
+ expires_container.visibility = View.GONE
+ } else {
+ expires_container.visibility = View.VISIBLE
+ val elapsed = System.currentTimeMillis() - messageRecord!!.expireStarted
+ val remaining = messageRecord!!.expiresIn - elapsed
+
+ val duration = ExpirationUtil.getExpirationDisplayValue(this, Math.max((remaining / 1000).toInt(), 1))
+ expires_in.text = duration
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt
index 7d3a06e6b1..2372657751 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationActionModeCallback.kt
@@ -58,6 +58,8 @@ class ConversationActionModeCallback(private val adapter: ConversationAdapter, p
// Copy Session ID
menu.findItem(R.id.menu_context_copy_public_key).isVisible =
(thread.isGroupRecipient && selectedItems.size == 1 && firstMessage.recipient.address.toString() != userPublicKey)
+ // Message detail
+ menu.findItem(R.id.menu_message_details).isVisible = (selectedItems.size == 1 && firstMessage.isFailed)
// Resend
menu.findItem(R.id.menu_context_resend).isVisible = (selectedItems.size == 1 && firstMessage.isFailed)
// Save media
@@ -81,6 +83,7 @@ class ConversationActionModeCallback(private val adapter: ConversationAdapter, p
R.id.menu_context_copy -> delegate?.copyMessages(selectedItems)
R.id.menu_context_copy_public_key -> delegate?.copySessionID(selectedItems)
R.id.menu_context_resend -> delegate?.resendMessage(selectedItems)
+ R.id.menu_message_details -> delegate?.showMessageDetail(selectedItems)
R.id.menu_context_save_attachment -> delegate?.saveAttachment(selectedItems)
R.id.menu_context_reply -> delegate?.reply(selectedItems)
}
@@ -101,6 +104,7 @@ interface ConversationActionModeCallbackDelegate {
fun copyMessages(messages: Set)
fun copySessionID(messages: Set)
fun resendMessage(messages: Set)
+ fun showMessageDetail(messages: Set)
fun saveAttachment(messages: Set)
fun reply(messages: Set)
}
\ No newline at end of file
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 b1a0fa38e0..0d54f345c6 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
@@ -52,7 +52,7 @@ class VisibleMessageView : LinearLayout {
var contentViewDelegate: VisibleMessageContentViewDelegate? = null
companion object {
- const val swipeToReplyThreshold = 80.0f // dp
+ const val swipeToReplyThreshold = 64.0f // dp
const val longPressMovementTreshold = 10.0f // dp
const val longPressDurationThreshold = 250L // ms
const val maxDoubleTapInterval = 200L
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt
new file mode 100644
index 0000000000..62004808a0
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt
@@ -0,0 +1,57 @@
+package org.thoughtcrime.securesms.conversation.v2.utilities
+
+import org.session.libsession.messaging.MessagingModuleConfiguration
+import org.session.libsession.messaging.messages.visible.LinkPreview
+import org.session.libsession.messaging.messages.visible.OpenGroupInvitation
+import org.session.libsession.messaging.messages.visible.Quote
+import org.session.libsession.messaging.messages.visible.VisibleMessage
+import org.session.libsession.messaging.sending_receiving.MessageSender
+import org.session.libsession.messaging.utilities.UpdateMessageData
+import org.session.libsession.utilities.recipients.Recipient
+import org.thoughtcrime.securesms.database.model.MessageRecord
+import org.thoughtcrime.securesms.database.model.MmsMessageRecord
+
+object ResendMessageUtilities {
+
+ fun resend(messageRecord: MessageRecord) {
+ val recipient: Recipient = messageRecord.recipient
+ val message = VisibleMessage()
+ message.id = messageRecord.getId()
+ if (messageRecord.isOpenGroupInvitation) {
+ val openGroupInvitation = OpenGroupInvitation()
+ UpdateMessageData.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 = LinkPreview.from(mmsMessageRecord.linkPreviews[0])
+ }
+ if (mmsMessageRecord.quote != null) {
+ message.quote = 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)
+ }
+}
\ No newline at end of file
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 ccb54fc4a6..b76610e815 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
@@ -334,7 +334,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
if (error.localizedMessage != null) {
val message: String
if (error is OnionRequestAPI.HTTPRequestFailedAtDestinationException && error.statusCode == 429) {
- message = "Rate limited."
+ message = "429: Rate limited."
} else {
message = error.localizedMessage!!
}
diff --git a/app/src/main/res/layout/activity_message_detail.xml b/app/src/main/res/layout/activity_message_detail.xml
new file mode 100644
index 0000000000..9847d37e05
--- /dev/null
+++ b/app/src/main/res/layout/activity_message_detail.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_conversation_item_action.xml b/app/src/main/res/menu/menu_conversation_item_action.xml
index 60874fd7b4..1f327ab6ae 100644
--- a/app/src/main/res/menu/menu_conversation_item_action.xml
+++ b/app/src/main/res/menu/menu_conversation_item_action.xml
@@ -21,6 +21,12 @@
android:icon="?menu_trash_icon"
app:showAsAction="always" />
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 540fece291..7610c2e876 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -882,4 +882,5 @@
Failed to prepare attachment for sending.
Media
Tap to download %s
+ Error