diff --git a/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt b/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt
index 44c30741ef..a99b40f36f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/SessionDialogBuilder.kt
@@ -105,7 +105,7 @@ class SessionDialogBuilder(val context: Context) {
fun destructiveButton(
@StringRes text: Int,
- @StringRes contentDescription: Int,
+ @StringRes contentDescription: Int = text,
listener: () -> Unit = {}
) = button(
text,
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/ControlMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/ControlMessageView.kt
index a9f2263a46..5d49f1a78d 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/ControlMessageView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/ControlMessageView.kt
@@ -10,7 +10,13 @@ import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView
import network.loki.messenger.R
import network.loki.messenger.databinding.ViewControlMessageBinding
+import org.session.libsession.messaging.messages.ExpirationConfiguration
+import org.session.libsession.utilities.ExpirationUtil.getExpirationDisplayValue
+import org.session.libsession.utilities.getExpirationTypeDisplayValue
import org.thoughtcrime.securesms.database.model.MessageRecord
+import org.thoughtcrime.securesms.showSessionDialog
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
class ControlMessageView : LinearLayout {
@@ -31,15 +37,33 @@ class ControlMessageView : LinearLayout {
binding.expirationTimerView.isGone = true
binding.followSetting.isGone = true
var messageBody: CharSequence = message.getDisplayBody(context)
- binding.root.contentDescription= null
+ binding.root.contentDescription = null
when {
message.isExpirationTimerUpdate -> {
- binding.expirationTimerView.apply {
- isVisible = true
- setExpirationTime(message.expireStarted, message.expiresIn)
+ binding.apply {
+ expirationTimerView.isVisible = true
+ expirationTimerView.setExpirationTime(message.expireStarted, message.expiresIn)
+ followSetting.isVisible = ExpirationConfiguration.isNewConfigEnabled && !message.isOutgoing
+ followSetting.setOnClickListener {
+ context.showSessionDialog {
+ val isOff = message.expiresIn == 0L
+ title(R.string.dialog_disappearing_messages_follow_setting_title)
+ if (isOff) {
+ text(R.string.dialog_disappearing_messages_follow_setting_off_body)
+ } else {
+ text(
+ context.getString(
+ R.string.dialog_disappearing_messages_follow_setting_on_body,
+ getExpirationDisplayValue(context, message.expiresIn.milliseconds),
+ context.getExpirationTypeDisplayValue(message.expireStarted == message.timestamp)
+ )
+ )
+ }
+ destructiveButton(if (isOff) R.string.dialog_disappearing_messages_follow_setting_confirm else R.string.dialog_disappearing_messages_follow_setting_set) { }
+ cancelButton()
+ }
+ }
}
-
- binding.followSetting.isGone = message.isOutgoing
}
message.isMediaSavedNotification -> {
binding.iconImageView.apply {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt
index af682bd1ed..dac078bc9e 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt
@@ -25,6 +25,7 @@ import com.google.android.mms.pdu_alt.PduHeaders
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
+import org.session.libsession.messaging.messages.ExpirationConfiguration
import org.session.libsession.messaging.messages.signal.IncomingMediaMessage
import org.session.libsession.messaging.messages.signal.OutgoingGroupMediaMessage
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage
@@ -1170,7 +1171,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
* @param outgoing if true only delete outgoing messages, if false only delete incoming messages, if null delete both.
*/
private fun deleteExpirationTimerMessages(threadId: Long, outgoing: Boolean? = null) {
- val outgoingClause = outgoing?.let {
+ val outgoingClause = outgoing?.takeIf { ExpirationConfiguration.isNewConfigEnabled }?.let {
val comparison = if (it) "IN" else "NOT IN"
" AND $MESSAGE_BOX & ${MmsSmsColumns.Types.BASE_TYPE_MASK} $comparison (${MmsSmsColumns.Types.OUTGOING_MESSAGE_TYPES.joinToString()})"
} ?: ""
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java
index 80501c9a2c..fbc36337bb 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java
@@ -116,7 +116,7 @@ public abstract class MessageRecord extends DisplayRecord {
return new SpannableString(UpdateMessageBuilder.INSTANCE.buildGroupUpdateMessage(context, updateMessageData, getIndividualRecipient().getAddress().serialize(), isOutgoing()));
} else if (isExpirationTimerUpdate()) {
int seconds = (int) (getExpiresIn() / 1000);
- return new SpannableString(UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, getIndividualRecipient().getAddress().serialize(), getThreadId(), isOutgoing()));
+ return new SpannableString(UpdateMessageBuilder.INSTANCE.buildExpirationTimerMessage(context, seconds, getIndividualRecipient().getAddress().serialize(), getThreadId(), isOutgoing(), getTimestamp(), expireStarted));
} else if (isDataExtractionNotification()) {
if (isScreenshotNotification()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.SCREENSHOT, getIndividualRecipient().getAddress().serialize())));
else if (isMediaSavedNotification()) return new SpannableString((UpdateMessageBuilder.INSTANCE.buildDataExtractionMessage(context, DataExtractionNotificationInfoMessage.Kind.MEDIA_SAVED, getIndividualRecipient().getAddress().serialize())));
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0395f76d3a..ab8d322b8f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -906,6 +906,11 @@
Are you sure you want to join the %s open group?
Open URL?
Are you sure you want to open %s?
+ Follow Setting
+ Messages you send will no longer disappear. Are you sure you want to turn off disappearing messages?
+ Set your messages to disappear %1$s after they have been %2$s?
+ Set
+ Confirm
Open
Copy URL
Enable Link Previews?
diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt
index 159283238b..2584583734 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt
@@ -56,8 +56,6 @@ data class ExpirationTimerUpdate(var expiryMode: ExpiryMode, var syncTarget: Str
}
return try {
SignalServiceProtos.Content.newBuilder().apply {
- expirationType
- expirationTimer
dataMessage = dataMessageProto.build()
setExpirationConfigurationIfNeeded(threadID)
}.build()
diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt
index 9fb55b2494..1571bb22c9 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiver.kt
@@ -151,11 +151,10 @@ object MessageReceiver {
val isUserBlindedSender = sender == openGroupPublicKey?.let { SodiumUtilities.blindedKeyPair(it, MessagingModuleConfiguration.shared.getUserED25519KeyPair()!!) }?.let { SessionId(IdPrefix.BLINDED, it.publicKey.asBytes).hexString }
val isUserSender = sender == userPublicKey
- // Ignore self send if needed
- if (!message.isSelfSendValid && (isUserSender || isUserBlindedSender)) {
- throw Error.SelfSend
- }
+
if (isUserSender || isUserBlindedSender) {
+ // Ignore self send if needed
+ if (!message.isSelfSendValid) throw Error.SelfSend
message.isSenderSelf = true
}
// Guard against control messages in open groups
diff --git a/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt b/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt
index 503f1271f9..bc76fff841 100644
--- a/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt
+++ b/libsession/src/main/java/org/session/libsession/messaging/utilities/UpdateMessageBuilder.kt
@@ -12,14 +12,14 @@ import org.session.libsession.messaging.calls.CallMessageType.CALL_OUTGOING
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.messages.ExpirationConfiguration
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
-import org.session.libsession.utilities.Address
import org.session.libsession.utilities.ExpirationUtil
+import org.session.libsession.utilities.getExpirationTypeDisplayValue
import org.session.libsession.utilities.truncateIdForDisplay
object UpdateMessageBuilder {
val storage = MessagingModuleConfiguration.shared.storage
- fun getSenderName(senderId: String) = storage.getContactWithSessionID(senderId)
+ private fun getSenderName(senderId: String) = storage.getContactWithSessionID(senderId)
?.displayName(Contact.ContactContext.REGULAR)
?: truncateIdForDisplay(senderId)
@@ -76,11 +76,17 @@ object UpdateMessageBuilder {
}
}
- fun buildExpirationTimerMessage(context: Context, duration: Long, senderId: String? = null, threadId: Long, isOutgoing: Boolean = false): String {
+ fun buildExpirationTimerMessage(
+ context: Context,
+ duration: Long,
+ senderId: String? = null,
+ threadId: Long,
+ isOutgoing: Boolean = false,
+ timestamp: Long,
+ expireStarted: Long
+ ): String {
if (!isOutgoing && senderId == null) return ""
- val senderName: String = if (!isOutgoing) {
- getSenderName(senderId!!)
- } else { context.getString(R.string.MessageRecord_you) }
+ val senderName = if (isOutgoing) context.getString(R.string.MessageRecord_you) else getSenderName(senderId!!)
return if (duration <= 0) {
if (isOutgoing) {
if (ExpirationConfiguration.isNewConfigEnabled) {
@@ -98,11 +104,7 @@ object UpdateMessageBuilder {
} else {
val time = ExpirationUtil.getExpirationDisplayValue(context, duration.toInt())
val config = threadId.let { storage.getExpirationConfiguration(it) }
- val state = when (config?.expiryMode) {
- is ExpiryMode.AfterSend -> context.getString(R.string.MessageRecord_state_sent)
- is ExpiryMode.AfterRead -> context.getString(R.string.MessageRecord_state_read)
- else -> ""
- }
+ val state = context.getExpirationTypeDisplayValue(timestamp == expireStarted)
if (isOutgoing) {
if (ExpirationConfiguration.isNewConfigEnabled) {
context.getString(R.string.MessageRecord_you_set_messages_to_disappear_s_after_s, time, state)
diff --git a/libsession/src/main/java/org/session/libsession/utilities/ExpirationUtil.kt b/libsession/src/main/java/org/session/libsession/utilities/ExpirationUtil.kt
index 9834ee36fb..f3647fa4f8 100644
--- a/libsession/src/main/java/org/session/libsession/utilities/ExpirationUtil.kt
+++ b/libsession/src/main/java/org/session/libsession/utilities/ExpirationUtil.kt
@@ -1,10 +1,13 @@
package org.session.libsession.utilities
import android.content.Context
+import network.loki.messenger.libsession_util.util.ExpiryMode
import org.session.libsession.R
import java.util.concurrent.TimeUnit
import kotlin.time.Duration
+fun Context.getExpirationTypeDisplayValue(sent: Boolean) = if (sent) getString(R.string.MessageRecord_state_sent) else getString(R.string.MessageRecord_state_read)
+
object ExpirationUtil {
@JvmStatic
fun getExpirationDisplayValue(context: Context, duration: Duration): String = getExpirationDisplayValue(context, duration.inWholeSeconds.toInt())